origen_sim 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d43e76c0e9a55fc9cdbcc5ba241ab8e76386aff85d711aef54e7c68293c5f8f
4
- data.tar.gz: 8f6582388d383142beebaf1c313936b78b6f495f0b2403193df02f8ae51f25f0
3
+ metadata.gz: a37dd737642a62e60b4cc98f47928b659004f3b89e771aa9efabfd2610622080
4
+ data.tar.gz: 74309fc46e200d299e8704e4599fdd3553abd1cb380ec56a9c7d926f1a7728f7
5
5
  SHA512:
6
- metadata.gz: dfa8d2b63ba5af0b216bda43900b24db81735a11a49f604053b34771c55d42a99d3e6a0f190f6f24815542bee91d1f281c423ba5fcadd01ea5d6e4406ba913d6
7
- data.tar.gz: 8a968093af5c18778e2835115f02c46ec3f638b1a5049124c9fe339dbe9007eb4f8a80aac3146a0e377aee0bcb920f147c54bf092b2721ccefd587614fee0fb6
6
+ metadata.gz: e94281aa75824657de8e4df717201db48d8b8fc02669b84b78e34f271533a119e88b6881a28d41ce6ecb5e2d12192d78d042764d6efabb2548e8c3fec7069080
7
+ data.tar.gz: 0404e46a47d0d02d5933ed238fc84b6660f3cbae5f70d7c632c4ca2cb87c8ada52b8a2b382becf4e59b2c276a423890b569de6a227b6d31f329eee26ca66711f
@@ -52,7 +52,8 @@ class OrigenSimApplication < Origen::Application
52
52
  dir: "example_rtl",
53
53
  rc_url: 'https://github.com/Origen-SDK/example_rtl.git',
54
54
  version: "master",
55
- development: true
55
+ development: true,
56
+ #path: "/home/stephen/Code/github/example_rtl"
56
57
  }
57
58
  ]
58
59
 
@@ -36,6 +36,10 @@ when "sim:unpack"
36
36
  OrigenSim::Commands::Pack.unpack
37
37
  exit 0
38
38
 
39
+ when "sim:run"
40
+ OrigenSim.run_source(ARGV[0])
41
+ exit 0
42
+
39
43
  #when "sim:list"
40
44
  # require "#{Origen.root!}/lib/origen_sim/commands/pack"
41
45
  # OrigenSim::Commands::Pack.list
data/config/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module OrigenSim
2
2
  MAJOR = 0
3
- MINOR = 14
3
+ MINOR = 15
4
4
  BUGFIX = 0
5
5
  DEV = nil
6
6
 
@@ -3,7 +3,7 @@ require 'origen_sim'
3
3
  require_relative '../../../config/version'
4
4
  require 'origen_verilog'
5
5
 
6
- options = { source_dirs: [], testbench_name: 'origen', defines: [] }
6
+ options = { incl_files: [], source_dirs: [], testbench_name: 'origen', defines: [], user_details: {}, initial_pin_states: {}, verilog_top_output_name: 'origen' }
7
7
 
8
8
  # App options are options that the application can supply to extend this command
9
9
  app_options = @application_options || []
@@ -22,9 +22,43 @@ Usage: origen sim:build TOP_LEVEL_VERILOG_FILE [options]
22
22
  opts.on('-s', '--source_dir PATH', 'Directories to look for include files in (the directory containing the top-level is already considered)') do |path|
23
23
  options[:source_dirs] << path
24
24
  end
25
+ opts.on('--sv', 'Generate a .sv file instead of a .v file.') { |t| options[:sv] = t }
26
+ opts.on('--verilog_top_output_name NAME', 'Renames the output filename from origen.v to NAME.v') do |name|
27
+ options[:verilog_top_output_name] = name
28
+ end
25
29
  opts.on('--define MACRO', 'Specify a compiler define') do |macro|
26
30
  options[:defines] << macro
27
31
  end
32
+ opts.on('--init_pin_state PIN_AND_STATE', 'Specify how the pins should be initialized.') do |pin_and_state|
33
+ name, state = pin_and_state.split(':')
34
+
35
+ # Make sure that we recognize the pin state option before building.
36
+ unless OrigenSim::INIT_PIN_STATE_MAPPING.include?(state)
37
+ fail "Provide state '#{state}' to --init_pin_state pin_and_state not recognized!"
38
+ end
39
+ (options[:initial_pin_states])[name.to_sym] = OrigenSim::INIT_PIN_STATE_MAPPING[state]
40
+ end
41
+ opts.on('--include FILE' 'Specify files to include in the top verilog file.') { |f| options[:incl_files] << f }
42
+
43
+ # Specifying snapshot details
44
+ opts.on('--device_name NAME', '(Snapshot Detail) Specify a device name') { |n| options[:device_name] = n }
45
+ opts.on('--testbench_version VER', '(Snapshot Detail) Specify a version of the testbench this snapshot was built from') { |v| options[:testbench_version] = v }
46
+ opts.on('--revision REV', '(Snapshot Detail) Specify a revision of the snapshot') { |r| options[:revision] = r }
47
+ opts.on('--revision_note REV_NOTE', '(Snapshot Detail) Specify a brief note on this revision of the snapshot') { |n| options[:revision_note] = n }
48
+ opts.on('--author AUTHOR', '(Snapshot Detail) Specify the author of the snapshot (default is just Origen.current_user)') { |a| options[:author] = a }
49
+
50
+ # User-defined snapshot details
51
+ opts.on('--USER_DETAIL NAME_AND_VALUE', 'Specify custom user-defined details to build into the snapshot details. Format as NAME:VALUE, e.g.: \'--USER_DETAIL BUILD_TYPE:RTL\'') do |name_and_value|
52
+ name, value = name_and_value.split(':')
53
+
54
+ unless name.upcase == name
55
+ Origen.log.warning "Non-capitalized user detail '#{name}' was given!"
56
+ Origen.log.warning 'OrigenSim forces the Verilog practice that parameters should be capitalized.'
57
+ Origen.log.warning "The parameter '#{name.upcase}' will be used instead"
58
+ name.upcase!
59
+ end
60
+ (options[:user_details])[name] = value
61
+ end
28
62
  opts.on('-d', '--debugger', 'Enable the debugger') { options[:debugger] = true }
29
63
  app_options.each do |app_option|
30
64
  opts.on(*app_option) {}
@@ -82,19 +116,37 @@ rtl_top_module = mod.name
82
116
 
83
117
  mod.to_top_level # Creates dut
84
118
 
119
+ # Update the pins with any setings from the command line
120
+ options[:initial_pin_states].each do |pin, state|
121
+ dut.pins(pin).meta[:origen_sim_init_pin_state] = state
122
+ end
123
+
85
124
  if $_testing_build_return_dut_
86
125
  dut
87
126
 
88
127
  else
89
128
 
90
129
  output_directory = options[:output] || Origen.config.output_directory
130
+ output_name = options[:sv] ? "#{options[:verilog_top_output_name]}.sv" : "#{options[:verilog_top_output_name]}.v"
91
131
 
92
132
  Origen.app.runner.launch action: :compile,
93
133
  files: "#{Origen.root!}/templates/rtl_v/origen.v.erb",
134
+ output_file_name: output_name,
94
135
  output: output_directory,
95
136
  check_for_changes: false,
96
137
  quiet: true,
97
- options: { vendor: :cadence, top: dut.name, incl: options[:incl_files] }
138
+ preserve_target: true,
139
+ options: {
140
+ vendor: :cadence,
141
+ top: dut.name,
142
+ incl: options[:incl_files],
143
+ device_name: options[:device_name],
144
+ revision: options[:revision],
145
+ revision_note: options[:revision_note],
146
+ parent_tb_version: options[:testbench_version],
147
+ user_details: options[:user_details],
148
+ author: options[:author]
149
+ }
98
150
 
99
151
  Origen.app.runner.launch action: :compile,
100
152
  files: "#{Origen.root!}/ext",
@@ -113,7 +165,7 @@ else
113
165
  puts
114
166
  puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
115
167
  puts
116
- puts " #{output_directory}/origen.v \\"
168
+ puts " #{output_directory}/#{output_name} \\"
117
169
  puts " #{output_directory}/*.c \\"
118
170
  puts ' -ccargs "-std=c99" \\'
119
171
  puts ' -top origen \\'
@@ -124,7 +176,7 @@ else
124
176
  puts
125
177
  puts 'Here is an example which may work for the file you just parsed (add additional -incdir options at the end if required):'
126
178
  puts
127
- puts " #{ENV['ORIGEN_SIM_IRUN'] || 'irun'} #{rtl_top} #{output_directory}/origen.v #{output_directory}/*.c -ccargs \"-std=c99\" -top origen -elaborate -snapshot origen -access +rw -timescale 1ns/1ns -incdir #{Pathname.new(rtl_top).dirname}"
179
+ puts " #{ENV['ORIGEN_SIM_IRUN'] || 'irun'} #{rtl_top} #{output_directory}/#{output_name} #{output_directory}/*.c -ccargs \"-std=c99\" -top origen -elaborate -snapshot origen -access +rw -timescale 1ns/1ns -incdir #{Pathname.new(rtl_top).dirname}"
128
180
  puts
129
181
  puts 'Copy the following directory (produced by irun) to simulation/<target>/cadence/. within your Origen application:'
130
182
  puts
@@ -136,7 +188,7 @@ else
136
188
  puts
137
189
  puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
138
190
  puts
139
- puts " #{output_directory}/origen.v \\"
191
+ puts " #{output_directory}/#{output_name} \\"
140
192
  puts " #{output_directory}/bridge.c \\"
141
193
  puts " #{output_directory}/client.c \\"
142
194
  puts ' -CFLAGS "-std=c99" \\'
@@ -149,7 +201,7 @@ else
149
201
  puts
150
202
  puts 'Here is an example which may work for the file you just parsed (add additional -incdir options at the end if required):'
151
203
  puts
152
- puts " #{ENV['ORIGEN_SIM_VCS'] || 'vcs'} #{rtl_top} #{output_directory}/origen.v #{output_directory}/bridge.c #{output_directory}/client.c -CFLAGS \"-std=c99\" +vpi #{output_directory}/origen.c -timescale=1ns/1ns +define+ORIGEN_VPD=1 +incdir+#{Pathname.new(rtl_top).dirname} -debug_access+all -PP"
204
+ puts " #{ENV['ORIGEN_SIM_VCS'] || 'vcs'} #{rtl_top} #{output_directory}/#{output_name} #{output_directory}/bridge.c #{output_directory}/client.c -CFLAGS \"-std=c99\" +vpi #{output_directory}/origen.c -timescale=1ns/1ns +define+ORIGEN_VPD=1 +incdir+#{Pathname.new(rtl_top).dirname} -debug_access+all -PP"
153
205
  puts
154
206
  puts 'Copy the following files (produced by vcs) to simulation/<target>/synopsys/. within your Origen application:'
155
207
  puts
@@ -166,13 +218,13 @@ else
166
218
  puts
167
219
  puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
168
220
  puts
169
- puts " #{output_directory}/origen.v \\"
221
+ puts " #{output_directory}/#{output_name} \\"
170
222
  puts ' -o origen.vvp \\'
171
223
  puts ' -DORIGEN_VCD'
172
224
  puts
173
225
  puts 'Here is an example which may work for the file you just parsed (add additional source dirs with more -I options at the end if required):'
174
226
  puts
175
- puts " #{ENV['ORIGEN_SIM_IVERILOG'] || 'iverilog'} #{rtl_top} #{output_directory}/origen.v -o origen.vvp -DORIGEN_VCD -I #{Pathname.new(rtl_top).dirname}"
227
+ puts " #{ENV['ORIGEN_SIM_IVERILOG'] || 'iverilog'} #{rtl_top} #{output_directory}/#{output_name} -o origen.vvp -DORIGEN_VCD -I #{Pathname.new(rtl_top).dirname}"
176
228
  puts
177
229
  puts 'Copy the following files (produced by iverilog) to simulation/<target>/icarus/. within your Origen application:'
178
230
  puts
@@ -185,8 +237,8 @@ else
185
237
  puts
186
238
  puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
187
239
  puts
188
- puts " #{output_directory}/origen.v \\"
189
- puts " #{output_directory}/bridge.c \\"
240
+ puts " #{output_directory}/#{output_name} \\"
241
+ puts " #{output_directory}/brdige.c \\"
190
242
  puts " #{output_directory}/client.c \\"
191
243
  puts ' -CFLAGS "-std=c99" \\'
192
244
  puts ' +vpi \\'
@@ -202,7 +254,7 @@ else
202
254
  puts
203
255
  puts 'Here is an example which may work for the file you just parsed (add additional -incdir options at the end if required):'
204
256
  puts
205
- puts " #{ENV['ORIGEN_SIM_VCS'] || 'vcs'} #{rtl_top} #{output_directory}/origen.v #{output_directory}/bridge.c #{output_directory}/client.c -CFLAGS \"-std=c99\" +vpi #{output_directory}/origen.c +define+ORIGEN_FSDB=1 +incdir+#{Pathname.new(rtl_top).dirname} -debug_access+all +lint=all,noVCDE,noIWU,noVNGS,noCAWM-L,noPORTFRC,noZERO,noNS -PP -timescale=1ns/100ps -full64 -lca -kdb"
257
+ puts " #{ENV['ORIGEN_SIM_VCS'] || 'vcs'} #{rtl_top} #{output_directory}/#{output_name} #{output_directory}/bridge.c #{output_directory}/client.c -CFLAGS \"-std=c99\" +vpi #{output_directory}/origen.c +define+ORIGEN_FSDB=1 +incdir+#{Pathname.new(rtl_top).dirname} -debug_access+all +lint=all,noVCDE,noIWU,noVNGS,noCAWM-L,noPORTFRC,noZERO,noNS -PP -timescale=1ns/100ps -full64 -lca -kdb"
206
258
  puts
207
259
  puts 'Copy the following files (produced by vcs) to simulation/<target>/verdi/. within your Origen application:'
208
260
  puts
@@ -1,7 +1,7 @@
1
1
  require 'thread'
2
2
  module OrigenSim
3
3
  class Heartbeat < Thread
4
- attr_reader :socket
4
+ attr_reader :socket, :simulation
5
5
 
6
6
  # Can't use this with threads currently because Byebug pauses the sleep,
7
7
  # during a breakpoint, which means that the simulator is killed.
@@ -9,7 +9,8 @@ module OrigenSim
9
9
  # whenever this is set to false.
10
10
  THREADSAFE = false
11
11
 
12
- def initialize(socket)
12
+ def initialize(simulation, socket)
13
+ @simulation = simulation
13
14
  @socket = socket
14
15
  @continue = true
15
16
  super do
@@ -17,8 +18,12 @@ module OrigenSim
17
18
  begin
18
19
  socket.write("OK\n")
19
20
  rescue Errno::EPIPE => e
20
- Origen.log.error 'Communication with the simulation monitor has been lost!'
21
- sleep 2
21
+ exit 0 if simulation.ended
22
+ if simulation.monitor_running?
23
+ Origen.log.error 'Communication with the simulation monitor has been lost (though it seems to still be running)!'
24
+ else
25
+ Origen.log.error 'The simulation monitor has stopped unexpectedly!'
26
+ end
22
27
  exit 1
23
28
  end
24
29
  sleep 5
@@ -18,6 +18,10 @@ module OrigenSim
18
18
  # Returns the communication socket used for sending commands to the Origen VPI running
19
19
  # in the simulation process
20
20
  attr_reader :socket
21
+ # Returns false when the simulation is running and will be set to true once all instructions
22
+ # have been sent and executed by the simulator and immediately before the end_simulation
23
+ # instruction is sent to the simulator.
24
+ attr_accessor :ended
21
25
 
22
26
  def initialize(id, view_wave_command)
23
27
  @id = id
@@ -25,6 +29,7 @@ module OrigenSim
25
29
  @completed_cleanly = false
26
30
  @failed_to_start = false
27
31
  @logged_errors = false
32
+ @ended = false
28
33
  @error_count = 0
29
34
  @socket_ids = {}
30
35
 
@@ -85,6 +90,24 @@ module OrigenSim
85
90
  end
86
91
  end
87
92
 
93
+ def ended=(val)
94
+ # If running the heartbeat from a fork we need to communicate to it that the simulation has
95
+ # ended by writing to a file
96
+ if val == true && !Heartbeat::THREADSAFE
97
+ FileUtils.touch(ended_file)
98
+ else
99
+ @ended = val
100
+ end
101
+ end
102
+
103
+ def ended_file
104
+ @ended_file ||= begin
105
+ dir = Origen.root.join('tmp', 'origen_sim', 'ended')
106
+ FileUtils.mkdir_p(dir.to_s)
107
+ dir.join(socket_number).to_s
108
+ end
109
+ end
110
+
88
111
  # Provide a heartbeat to let the parallel Ruby process in charge of the simulator
89
112
  # know that the master Origen process is still alive. If the Origen process crashes and leaves
90
113
  # the simulator running, the child process will automatically reap it after a couple of missed
@@ -92,20 +115,25 @@ module OrigenSim
92
115
  def start_heartbeat
93
116
  @heartbeat = @server_heartbeat.accept
94
117
  if Heartbeat::THREADSAFE
95
- @heartbeat_thread = Heartbeat.new(@heartbeat)
118
+ @heartbeat_thread = Heartbeat.new(self, @heartbeat)
96
119
  else
120
+ ended_file # Cache this file name before forking
97
121
  @heartbeat_pid = fork do
98
122
  loop do
99
123
  begin
100
124
  @heartbeat.write("OK\n")
101
125
  rescue Errno::EPIPE => e
102
- if monitor_running?
103
- Origen.log.error 'Communication with the simulation monitor has been lost (though it seems to still be running)!'
126
+ if File.exist?(ended_file)
127
+ FileUtils.rm_f(ended_file)
128
+ exit 0
104
129
  else
105
- Origen.log.error 'The simulation monitor has stopped unexpectedly!'
130
+ if monitor_running?
131
+ Origen.log.error 'Communication with the simulation monitor has been lost (though it seems to still be running)!'
132
+ else
133
+ Origen.log.error 'The simulation monitor has stopped unexpectedly!'
134
+ end
135
+ exit 1
106
136
  end
107
- sleep 2 # To make sure that any log output from the simulator is captured before we pull the plug
108
- exit 1
109
137
  end
110
138
  sleep 5
111
139
  end
@@ -125,6 +153,7 @@ module OrigenSim
125
153
  rescue Errno::ECHILD
126
154
  # Heartbeat process has already stopped, so ignore this.
127
155
  end
156
+ FileUtils.rm_f(ended_file) if File.exist?(ended_file)
128
157
  end
129
158
  end
130
159
 
@@ -74,6 +74,10 @@ module OrigenSim
74
74
  alias_method :pop_method, :populate_method
75
75
 
76
76
  def populate
77
+ unless Dir.exist?(run_target.dirname)
78
+ FileUtils.mkdir_p(run_target.dirname)
79
+ end
80
+
77
81
  if populate_method == :symlink
78
82
  File.symlink(target, run_target)
79
83
  elsif populate_method == :copy
@@ -0,0 +1,59 @@
1
+ require 'origen_sim/simulator/user_details'
2
+
3
+ module OrigenSim
4
+ class Simulator
5
+ # The SnapshotDetails and UserDetails share a lot in common, with the
6
+ # SnapshotDetails containing a bit of extra stuff.
7
+ class SnapshotDetails < UserDetails
8
+ attr_reader :_user_details
9
+
10
+ def initialize(simulator:, cache: true)
11
+ # @fetch_error_message = "OrigenSim was unable to find net #{detail_names_net} in the snapshot! Unable to retrieve snapshot details!"
12
+ super(simulator: simulator, cache: cache)
13
+
14
+ @_user_details = UserDetails.new(simulator: simulator, cache: cache)
15
+ end
16
+
17
+ def detail_to_net(d)
18
+ "#{@simulator.testbench_top}.debug.snapshot_details.#{d}"
19
+ end
20
+
21
+ def _missing_detail_message(d)
22
+ "Detail '#{d}' is not an available snapshot detail name!"
23
+ end
24
+
25
+ ### The user details interface is the same as the snapshot_details ###
26
+ ### just on the snapshot_details itself ###
27
+
28
+ def user_details(d = nil)
29
+ if d
30
+ _user_details[d]
31
+ else
32
+ _user_details
33
+ end
34
+ end
35
+
36
+ def user_detail(d)
37
+ user_details(d)
38
+ end
39
+ end
40
+
41
+ ### Add the following methods to the simulator ###
42
+
43
+ def _snapshot_details
44
+ @_snapshot_details ||= SnapshotDetails.new(simulator: self, **@configuration[:snapshot_details_options])
45
+ end
46
+
47
+ def snapshot_details(d = nil)
48
+ if d
49
+ _snapshot_details[d]
50
+ else
51
+ _snapshot_details
52
+ end
53
+ end
54
+
55
+ def snapshot_detail(d)
56
+ snapshot_details(d)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,107 @@
1
+ module OrigenSim
2
+ class Simulator
3
+ class UserDetails
4
+ DETAIL_NAMES_NET = '_AVAILABLE_DETAILS_'
5
+
6
+ attr_reader :cache
7
+ attr_reader :details
8
+
9
+ def initialize(simulator:, cache: true)
10
+ @simulator = simulator
11
+ @fetch_error_message = "OrigenSim was unable to find net #{detail_names_net} in the snapshot! Unable to retrieve snapshot details!"
12
+ @details = fetch
13
+ @cache = cache
14
+ end
15
+
16
+ # This gets called for some reason when 'puts' is used for the object.
17
+ # Provide something here to avoid seeing the error message.
18
+ def to_ary
19
+ nil
20
+ end
21
+
22
+ def method_missing(method, *args, &block)
23
+ self[method]
24
+ end
25
+
26
+ def [](d)
27
+ _d = d.to_s.upcase
28
+ if cache
29
+ if details
30
+ if details.key?(_d)
31
+ details[_d]
32
+ else
33
+ Origen.log.error(_missing_detail_message(_d))
34
+ nil
35
+ end
36
+ else
37
+ # if detail fetching failed, but the user is still trying to query
38
+ # details, re-print the fetch error message
39
+ Origen.log.error(@fetch_error_message)
40
+ nil
41
+ end
42
+ else
43
+ details = fetch
44
+ if details
45
+ if details.key?(_d)
46
+ details[_d]
47
+ else
48
+ Origen.log.error(_missing_detail_message(_d))
49
+ nil
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def _missing_detail_message(d)
56
+ "Detail '#{d}' was not provided in this snapshot!"
57
+ end
58
+
59
+ # Fetches the details available in the snapshot.
60
+ # This is done at runtime to get the latest details list from the snapshot
61
+ # but can be cached for future use.
62
+ # @note This requires the details <code>origen.debug.AVAILABLE_DETAILS</code>
63
+ # to be defined. This should be a comma-separeted string of the available values.
64
+ # It will be assumed that each details will be defined in the snapshot.
65
+ def fetch
66
+ puts 'FETCHING!'.cyan
67
+ # Read the available details.
68
+ # names = str_peek("#{debug_module}.PARAMETER_NAMES").split(',')
69
+ names = @simulator.peek_str(detail_names_net)
70
+ if names.nil?
71
+ Origen.log.error(@fetch_error_message)
72
+
73
+ # Returning false indicates that the fetch failed.
74
+ false
75
+ elsif names.empty?
76
+ # Empty string was returned. No available details/no details given.
77
+ {}
78
+ else
79
+ # Fetch each detail value and return as a Hash
80
+ names.split(',').map do |n|
81
+ [n, @simulator.str_peek(detail_to_net(n))]
82
+ end.to_h
83
+ end
84
+ end
85
+
86
+ def available_details
87
+ if details
88
+ details.keys
89
+ else
90
+ details = fetch
91
+ @details = details if cache
92
+ if details
93
+ details.keys
94
+ end
95
+ end
96
+ end
97
+
98
+ def detail_to_net(d)
99
+ "#{@simulator.testbench_top}.debug.snapshot_details.user_details.#{d}"
100
+ end
101
+
102
+ def detail_names_net
103
+ detail_to_net(DETAIL_NAMES_NET)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -1,5 +1,6 @@
1
1
  require 'origen_sim/simulation'
2
- require 'origen_sim/artifacts'
2
+ require 'origen_sim/simulator/artifacts'
3
+ require 'origen_sim/simulator/snapshot_details'
3
4
 
4
5
  module OrigenSim
5
6
  # Responsible for managing and communicating with the simulator
@@ -117,7 +118,9 @@ module OrigenSim
117
118
  unless VENDORS.include?(options[:vendor])
118
119
  fail "Unknown vendor #{options[:vendor]}, valid values are: #{VENDORS.map { |v| ':' + v.to_s }.join(', ')}"
119
120
  end
120
- @configuration = options
121
+ @configuration = {
122
+ snapshot_details_options: {}
123
+ }.merge(options)
121
124
  @tmp_dir = nil
122
125
 
123
126
  # Temporary workaround for bug in componentable, which is making the container a class object, instead of an
@@ -171,7 +174,7 @@ module OrigenSim
171
174
  end
172
175
 
173
176
  def target_artifact_dir
174
- Pathname(@configuration[:target_artifact_dir] || "#{Origen.app.root}/simulation/#{Origen.target.name}/artifacts")
177
+ Pathname(@configuration[:target_artifact_dir] || "#{Origen.app.root}/simulation/#{id}/artifacts")
175
178
  end
176
179
 
177
180
  def artifact_run_dir
@@ -311,7 +314,7 @@ module OrigenSim
311
314
 
312
315
  when :synopsys
313
316
  if configuration[:verdi]
314
- cmd = "#{compiled_dir}/simv +socket+#{socket_id} +FSDB_ON +fsdbfile+#{Origen.root}/waves/#{Origen.target.name}/#{wave_file_basename}.fsdb +memcbk +vcsd"
317
+ cmd = "#{compiled_dir}/simv +socket+#{socket_id} +FSDB_ON +fsdbfile+#{Origen.root}/waves/#{id}/#{wave_file_basename}.fsdb +memcbk +vcsd"
315
318
  else
316
319
  cmd = "#{compiled_dir}/simv +socket+#{socket_id} -vpd_file #{wave_file_basename}.vpd"
317
320
  end
@@ -364,12 +367,12 @@ module OrigenSim
364
367
  OrigenSim.flow.to_s
365
368
  else
366
369
  if Origen.app.current_job
367
- @last_wafe_file_basename = Pathname.new(Origen.app.current_job.output_file).basename('.*').to_s
370
+ @last_wave_file_basename = Pathname.new(Origen.app.current_job.output_file).basename('.*').to_s
368
371
  else
369
372
  if Origen.interactive?
370
373
  'interactive'
371
374
  else
372
- @last_wafe_file_basename
375
+ @last_wave_file_basename || 'unnamed_pattern'
373
376
  end
374
377
  end
375
378
  end
@@ -407,7 +410,7 @@ module OrigenSim
407
410
  cmd = "cd #{edir} && "
408
411
  cmd += configuration[:verdi] || 'verdi'
409
412
  dir = Pathname.new(wave_dir).relative_path_from(edir.expand_path)
410
- cmd += " -ssz -dbdir #{Origen.root}/simulation/#{Origen.target.name}/synopsys/simv.daidir/ -ssf #{dir}/#{wave_file_basename}.fsdb"
413
+ cmd += " -ssz -dbdir #{Origen.root}/simulation/#{id}/synopsys/simv.daidir/ -ssf #{dir}/#{wave_file_basename}.fsdb"
411
414
  f = Pathname.new(wave_config_file).relative_path_from(edir.expand_path)
412
415
  cmd += " -sswr #{f}"
413
416
  cmd += ' &'
@@ -643,6 +646,7 @@ module OrigenSim
643
646
  @pattern_count += 1
644
647
  end
645
648
  end
649
+ alias_method :setup_simulation, :before_pattern
646
650
 
647
651
  # This will be called at the end of every pattern, make
648
652
  # sure the simulator is not running behind before potentially
@@ -653,6 +657,7 @@ module OrigenSim
653
657
  simulation.completed_cleanly = true unless @flow_running
654
658
  end
655
659
  end
660
+ alias_method :complete_simulation, :pattern_generated
656
661
 
657
662
  def write_comment(line, comment)
658
663
  return if line >= OrigenSim::NUMBER_OF_COMMENT_LINES
@@ -864,6 +869,8 @@ module OrigenSim
864
869
  @simulation_open = false
865
870
  simulation.error_count = error_count
866
871
  Origen.listeners_for(:simulation_shutdown).each(&:simulation_shutdown)
872
+ sync_up
873
+ simulation.ended = true
867
874
  end_simulation
868
875
  # Give the simulator time to shut down
869
876
  sleep 0.1 while simulation.running?
@@ -973,6 +980,23 @@ module OrigenSim
973
980
  peek("#{testbench_top}.pins.match_errors").to_i
974
981
  end
975
982
 
983
+ def peek_str(signal)
984
+ val = tester.simulator.peek(signal)
985
+ unless val.nil?
986
+ puts val
987
+ puts val.class
988
+ # All zeros seems to be what an empty string is returned from the VPI,
989
+ # Otherwise, break the string up into 8-bit chunks and decode the ASCII>
990
+ val = (val.to_s == 'b00000000' ? '' : val.to_s[1..-1].scan(/.{1,8}/).collect { |char| char.to_i(2).chr }.join)
991
+ end
992
+ val
993
+ # puts "Peaking #{signal}: #{a}: #{a.class}"
994
+ # tester.simulator.peek(signal).to_s[1..-1].scan(/.{1,8}/).collect { |char| char.to_i(2).chr }.join
995
+ end
996
+ alias_method :str_peek, :peek_str
997
+ alias_method :peek_string, :peek_str
998
+ alias_method :string_peek, :peek_str
999
+
976
1000
  private
977
1001
 
978
1002
  # Pre 0.8.0 the simulator represented the time in ns instead of ps
@@ -225,6 +225,10 @@ module OrigenSim
225
225
  flush if Origen.running_interactively? && dut_version > '0.12.1'
226
226
  end
227
227
 
228
+ # def method_missing(m, *args, &block)
229
+ # super
230
+ # end
231
+
228
232
  private
229
233
 
230
234
  def flush_comments
data/lib/origen_sim.rb CHANGED
@@ -19,6 +19,44 @@ module OrigenSim
19
19
  autoload :Tester, 'origen_sim/tester'
20
20
  autoload :Generator, 'origen_sim/generator'
21
21
 
22
+ # Include a mapping for various sematics.
23
+ INIT_PIN_STATE_MAPPING = {
24
+ # Drive Low Options
25
+ 'drive_lo' => 0,
26
+ 'drive-lo' => 0,
27
+ 'drive_low' => 0,
28
+ 'drive-low' => 0,
29
+ 'lo' => 0,
30
+ 'low' => 0,
31
+ '0' => 0,
32
+
33
+ # Drive High Options
34
+ 'drive_hi' => 1,
35
+ 'drive-hi' => 1,
36
+ 'drive_high' => 1,
37
+ 'drive-high' => 1,
38
+ 'hi' => 1,
39
+ 'high' => 1,
40
+ '1' => 1,
41
+
42
+ # High Impedance Options
43
+ 'z' => 2,
44
+ 'high_z' => 2,
45
+ 'high-z' => 2,
46
+ 'hi_z' => 2,
47
+ 'hi-z' => 2,
48
+ 'high_impedance' => 2,
49
+ 'high-impedance' => 2,
50
+ '2' => 2,
51
+
52
+ # Disable Options
53
+ '-1' => -1,
54
+ 'disable' => -1,
55
+ 'disabled' => -1,
56
+ 'no_action' => -1,
57
+ 'no-action' => -1
58
+ }
59
+
22
60
  def self.__instantiate_simulator__
23
61
  @simulator ||= Simulator.new
24
62
  end
@@ -145,5 +183,23 @@ module OrigenSim
145
183
  def self.error(message)
146
184
  simulator.error(message)
147
185
  end
186
+
187
+ def self.run(name, options = {}, &block)
188
+ # Load up the application and target
189
+ Origen.load_application
190
+ Origen.app.load_target!
191
+
192
+ # Start up the simulator and run whatever's in the target block.
193
+ # After the block completes, shutdown the simulator
194
+ tester.simulator.setup_simulation(name)
195
+ yield
196
+ tester.simulator.complete_simulation(name)
197
+ end
198
+
199
+ def self.run_source(source, options = {})
200
+ OrigenSim.run(source) do
201
+ OrigenTesters::Decompiler.decompile(source).execute
202
+ end
203
+ end
148
204
  end
149
205
  OrigenSim.__instantiate_simulator__
@@ -72,6 +72,9 @@ module OrigenSimDev
72
72
  reg.bits 6..4, :b5
73
73
  reg.bits 2..0, :b6
74
74
  end
75
+
76
+ sub_block :ip1, class_name: 'IP'
77
+ sub_block :ip2, class_name: 'IP'
75
78
  end
76
79
 
77
80
  def interactive_startup
@@ -98,12 +101,23 @@ module OrigenSimDev
98
101
  end
99
102
 
100
103
  def write_register(reg, options = {})
101
- jtag.write_ir(0x8, size: 4)
102
- dr.rg_enable.write(1)
103
- dr.rg_read.write(0)
104
- dr.rg_addr.write(reg.address)
105
- dr.rg_data.write(reg.data)
106
- jtag.write_dr(dr)
104
+ if reg.path =~ /ip(\d)/
105
+ ir_val = 0b0100 | Regexp.last_match(1).to_i
106
+ jtag.write_ir(ir_val, size: 4)
107
+ ip = reg.parent
108
+ ip.dr.bits(:write).write(1)
109
+ ip.dr.bits(:address).write(reg.address)
110
+ ip.dr.bits(:data).write(reg.data)
111
+ jtag.write_dr(ip.dr)
112
+ # Write to top-level reg
113
+ else
114
+ jtag.write_ir(0x8, size: 4)
115
+ dr.rg_enable.write(1)
116
+ dr.rg_read.write(0)
117
+ dr.rg_addr.write(reg.address)
118
+ dr.rg_data.write(reg.data)
119
+ jtag.write_dr(dr)
120
+ end
107
121
  end
108
122
 
109
123
  def read_register(reg, options = {})
@@ -119,14 +133,26 @@ module OrigenSimDev
119
133
  1.cycle
120
134
  dut.pins(:dout).dont_care
121
135
  else
122
- jtag.write_ir(0x8, size: 4)
123
- dr.rg_enable.write(1)
124
- dr.rg_read.write(1)
125
- dr.rg_addr.write(reg.address)
126
- jtag.write_dr(dr)
127
- dr.rg_enable.write(0)
128
- dr.rg_data.copy_all(reg)
129
- jtag.read_dr(dr)
136
+ if reg.path =~ /ip(\d)/
137
+ ir_val = 0b0100 | Regexp.last_match(1).to_i
138
+ jtag.write_ir(ir_val, size: 4)
139
+ ip = reg.parent
140
+ ip.dr.bits(:write).write(0)
141
+ ip.dr.bits(:address).write(reg.address)
142
+ ip.dr.bits(:data).write(0)
143
+ jtag.write_dr(ip.dr)
144
+ ip.dr.bits(:data).copy_all(reg)
145
+ jtag.read_dr(ip.dr)
146
+ else
147
+ jtag.write_ir(0x8, size: 4)
148
+ dr.rg_enable.write(1)
149
+ dr.rg_read.write(1)
150
+ dr.rg_addr.write(reg.address)
151
+ jtag.write_dr(dr)
152
+ dr.rg_enable.write(0)
153
+ dr.rg_data.copy_all(reg)
154
+ jtag.read_dr(dr)
155
+ end
130
156
  end
131
157
  end
132
158
  end
@@ -0,0 +1,53 @@
1
+ module OrigenSimDev
2
+ class IP
3
+ include Origen::Model
4
+
5
+ def initialize
6
+ # Virtual reg to implement the JTAG scan chain
7
+ add_reg :dr, 0x0, size: 49 do |reg|
8
+ reg.bit 48, :write
9
+ reg.bits 47..32, :address
10
+ reg.bits 31..0, :data
11
+ end
12
+
13
+ # User regs
14
+ add_reg :cmd, 0x0
15
+
16
+ reg :status, 0x4 do |reg|
17
+ reg.bit 2, :error, access: :w1c
18
+ reg.bit 1, :fail, access: :w1c
19
+ reg.bit 0, :busy
20
+ end
21
+
22
+ add_reg :data, 0x8
23
+ end
24
+
25
+ def communication_test
26
+ ss "Communication test with #{name}"
27
+ data.write!(0x1234)
28
+ data.read!
29
+ data.read!
30
+ data.write!(0x5555_AAAA)
31
+ data.read!
32
+ end
33
+
34
+ def execute_cmd(code)
35
+ ss "Execute command #{code}"
36
+ # Verify that no command is currently running
37
+ status.read!(0)
38
+
39
+ cmd.write!(code)
40
+ 10.cycles
41
+ # Verify that the command has started
42
+
43
+ status.busy.read!(1)
44
+
45
+ # Wait for the command to complete, a 'command' lasts for
46
+ # 1000 cycles times the command code
47
+ (code * 1000).cycles
48
+
49
+ # Verify that the command completed and passed
50
+ status.read!(0)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,9 @@
1
+ Pattern.create do
2
+
3
+ dut.ip1.communication_test
4
+
5
+ dut.ip1.execute_cmd(1)
6
+
7
+ dut.ip1.execute_cmd(50)
8
+
9
+ end
@@ -0,0 +1,8 @@
1
+ Pattern.create do
2
+
3
+ dut.ip2.communication_test
4
+
5
+ dut.ip2.execute_cmd(10)
6
+ dut.ip2.execute_cmd(10)
7
+ dut.ip2.execute_cmd(10)
8
+ end
@@ -11,6 +11,12 @@
11
11
  //
12
12
  // 0 - Force data 0
13
13
  // 1 - Force data 1
14
+ //
15
+ // Parameter init_drive
16
+ // 0 - Initialize drive and assign to 0
17
+ // 1 - Initialize drive and assign to 1
18
+ // 2 - Don't initialize drive and assign to Z (default)
19
+ // -1 - Don't initialize drive or assign. Pin will be left unknown
14
20
  module pin_driver(error, pin, sync, match_loop);
15
21
  parameter init_drive = 2; // Which means don't drive initially, set to 0 or 1 to drive
16
22
  parameter pin_name = "undefined_name";
@@ -33,7 +39,9 @@ module pin_driver(error, pin, sync, match_loop);
33
39
  wire drive_data = force_data[0] ? 0 : (force_data[1] ? 1 : data[0]);
34
40
  wire contention = drive ? (pin !== drive_data ? 1 : 0) : 0;
35
41
 
36
- assign pin = drive ? drive_data : 1'bz;
42
+ if (init_drive != -1) begin
43
+ assign pin = drive ? drive_data : 1'bz;
44
+ end
37
45
 
38
46
  // Debug signal to show the expected data in the waves
39
47
  wire expect_data = compare ? data[0] : 1'bz;
@@ -113,14 +121,43 @@ module pin_drivers(errors, <%= dut.rtl_pins.map { |n, p, o| "#{p.id}_o" }.join('
113
121
  end
114
122
 
115
123
  % dut.rtl_pins.each do |name, pin, options|
116
- pin_driver #(.init_drive(<%= pin.driving? ? "#{pin.value}" : '2' %>), .pin_name("<%= pin.id %>")) <%= pin.id %>(.pin(<%= pin.id %>_o), .error(<%= pin.id %>_err), .sync(sync), .match_loop(match_loop));
124
+ pin_driver #(<%= pin.meta[:origen_sim_init_pin_state].nil? ? '' : ".init_drive(#{pin.meta[:origen_sim_init_pin_state]}), "%>.pin_name("<%= pin.id %>")) <%= pin.id %>(.pin(<%= pin.id %>_o), .error(<%= pin.id %>_err), .sync(sync), .match_loop(match_loop));
117
125
  % end
118
126
 
127
+
119
128
  endmodule
120
129
 
130
+ // Placeholder for user notes. This will be an empty module if no notes were given
131
+ module user_details;
132
+ parameter _AVAILABLE_DETAILS_ = "<%= options[:user_details].empty? ? "" : options[:user_details].keys.join(',') %>";
133
+
134
+ % options[:user_details].each do |name, note|
135
+ parameter <%= name %> = "<%= note %>";
136
+ % end
137
+ endmodule
121
138
 
122
- module debug(errors);
123
139
 
140
+ // SnapshotDetails module. Just stores some traceability details into the snapshot
141
+ // that can be queried by OrigenSim or viewed in the waveform viewer.
142
+ module snapshot_details;
143
+ // Add a parameter that lists the available parameters. OrigenSim can use this known parameter to query any others that are
144
+ // added here.
145
+ parameter _AVAILABLE_DETAILS_ = "ORIGEN_SIM_VERSION,COMPILATION_TIME_STAMP,COMPILATION_PATH,DEVICE_NAME,REVISION,REVISION_NOTE,TESTBENCH_VERSION,AUTHOR";
146
+
147
+ parameter ORIGEN_SIM_VERSION = "<%= OrigenSim::VERSION %>";
148
+ parameter COMPILATION_TIME_STAMP = "<%= Time.now %>";
149
+ parameter COMPILATION_PATH = "<%= Dir.pwd %>";
150
+ parameter DEVICE_NAME = "<%= options[:device_name] || 'No --device_name specified' %>";
151
+ parameter REVISION = "<%= options[:revision] || 'No --revision specified' %>";
152
+ parameter REVISION_NOTE = "<%= options[:revision_note] || 'No --revision_note specified' %>";
153
+ parameter TESTBENCH_VERSION = "<%= options[:parent_tb_version] || 'No --testbench_version specified' %>";
154
+ parameter AUTHOR = "<%= options[:author] || Origen.current_user.username %>";
155
+
156
+ user_details user_details();
157
+
158
+ endmodule
159
+
160
+ module debug(errors);
124
161
  input [31:0] errors;
125
162
 
126
163
  reg [1023:0] pattern = 0;
@@ -130,6 +167,8 @@ module debug(errors);
130
167
 
131
168
  reg handshake;
132
169
 
170
+ snapshot_details snapshot_details();
171
+
133
172
  endmodule
134
173
 
135
174
  module origen;
@@ -157,14 +196,17 @@ module origen;
157
196
  % dut.ground_pins.each do |name, pin, options|
158
197
  .<%= pin.id %>(<%= pin.id %>),
159
198
  % end
199
+ % # Keep track of the primary groups seen.
200
+ % seen_groups = []
160
201
  % dut.rtl_pins.each_with_index do |(name, pin, options), i|
161
202
  % if options[:group]
162
- % if pin.group_index == 0
203
+ % unless seen_groups.include?(pin.primary_group)
163
204
  .<%= pin.primary_group.id %>({
164
205
  % pin.primary_group.each_with_index do |pin, i|
165
206
  <%= pin.id %><%= i == (pin.primary_group.size - 1) ? '' : ',' %>
166
207
  % end
167
208
  })<%= i == (dut.rtl_pins.size - 1) ? '' : ',' %>
209
+ % seen_groups << pin.primary_group
168
210
  % end
169
211
  % else
170
212
  .<%= pin.rtl_name %>(<%= pin.id %>)<%= i == (dut.rtl_pins.size - 1) ? '' : ',' %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: origen_sim
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen McGinty
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-27 00:00:00.000000000 Z
11
+ date: 2019-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: origen
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.35.0
19
+ version: 0.41.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.35.0
26
+ version: 0.41.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: origen_testers
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 0.5.1
47
+ version: 0.5.2
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 0.5.1
54
+ version: 0.5.2
55
55
  description:
56
56
  email:
57
57
  - stephen.f.mcginty@gmail.com
@@ -75,7 +75,6 @@ files:
75
75
  - ext/origen.h
76
76
  - ext/vpi_user.h
77
77
  - lib/origen_sim.rb
78
- - lib/origen_sim/artifacts.rb
79
78
  - lib/origen_sim/commands/build.rb
80
79
  - lib/origen_sim/commands/ci.rb
81
80
  - lib/origen_sim/commands/co.rb
@@ -89,11 +88,17 @@ files:
89
88
  - lib/origen_sim/origen_testers/api.rb
90
89
  - lib/origen_sim/simulation.rb
91
90
  - lib/origen_sim/simulator.rb
91
+ - lib/origen_sim/simulator/artifacts.rb
92
+ - lib/origen_sim/simulator/snapshot_details.rb
93
+ - lib/origen_sim/simulator/user_details.rb
92
94
  - lib/origen_sim/stderr_reader.rb
93
95
  - lib/origen_sim/stdout_reader.rb
94
96
  - lib/origen_sim/tester.rb
95
97
  - lib/origen_sim_dev/dut.rb
98
+ - lib/origen_sim_dev/ip.rb
96
99
  - lib/tasks/origen_sim.rake
100
+ - pattern/ip1_test.rb
101
+ - pattern/ip2_test.rb
97
102
  - pattern/test.rb
98
103
  - pattern/test2.rb
99
104
  - program/p1.rb
@@ -138,7 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
143
  version: 1.8.11
139
144
  requirements: []
140
145
  rubyforge_project:
141
- rubygems_version: 2.7.6
146
+ rubygems_version: 2.7.7
142
147
  signing_key:
143
148
  specification_version: 4
144
149
  summary: Plugin that provides a testbench environment to simulate Origen test patterns