origen_sim 0.20.6 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/config/commands.rb +27 -1
- data/config/shared_commands.rb +9 -2
- data/config/version.rb +2 -2
- data/ext/bridge.c +27 -13
- data/ext/common.h +1 -0
- data/ext/defines.h.erb +3 -0
- data/lib/origen_sim/commands/build.rb +191 -92
- data/lib/origen_sim/origen/pins/pin.rb +4 -4
- data/lib/origen_sim/origen/top_level.rb +17 -8
- data/lib/origen_sim/origen_testers/api.rb +1 -1
- data/lib/origen_sim/simulator.rb +129 -21
- data/lib/origen_sim/tester.rb +61 -25
- data/lib/origen_sim.rb +13 -0
- data/lib/origen_sim_dev/dut.rb +4 -0
- data/pattern/test.rb +9 -2
- data/templates/origen_guides/simulation/patterns.md.erb +8 -0
- data/templates/probe.tcl.erb +1 -2
- data/templates/rtl_v/origen.v.erb +104 -34
- metadata +5 -6
@@ -6,18 +6,27 @@ module Origen
|
|
6
6
|
# Optionally pass in a type: option set to either :analog or :digital to
|
7
7
|
# have only the pins with that type returned
|
8
8
|
def rtl_pins(options = {})
|
9
|
+
_add_rtl_pin_ = lambda do |name, pin, opts, p|
|
10
|
+
options = {}
|
11
|
+
unless pin.rtl_name.to_s.downcase == 'nc' ||
|
12
|
+
(opts[:type] && pin.type && opts[:type] != pin.type) ||
|
13
|
+
(pin.meta[:origen_sim_init_pin_state] && pin.meta[:origen_sim_init_pin_state] == -2)
|
14
|
+
if pin.primary_group
|
15
|
+
options[:group] = true
|
16
|
+
end
|
17
|
+
p << [name, pin, options]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
pin_roles = [:pins, :power_pins, :ground_pins, :virtual_pins, :other_pins]
|
9
22
|
@rtl_pins ||= {}
|
10
23
|
@rtl_pins[options[:type]] ||= begin
|
11
24
|
opts = options.dup
|
12
25
|
p = []
|
13
|
-
pins.each do |name, pin|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
if pin.primary_group
|
18
|
-
options[:group] = true
|
19
|
-
end
|
20
|
-
p << [name, pin, options]
|
26
|
+
# pins.each do |name, pin|
|
27
|
+
pin_roles.each do |role|
|
28
|
+
dut.send(role).each do |name, pin|
|
29
|
+
_add_rtl_pin_.call(name, pin, opts, p)
|
21
30
|
end
|
22
31
|
end
|
23
32
|
p
|
@@ -26,7 +26,7 @@ module OrigenTesters
|
|
26
26
|
if @sim_capture || @sim_delay
|
27
27
|
fail 'Nesting of sim_capture and/or sim_delay blocks is not yet supported!'
|
28
28
|
end
|
29
|
-
Origen::OrgFile.open(id, path: OrigenSim.capture_dir) do |org_file|
|
29
|
+
Origen::OrgFile.open(id, path: (options[:path] || OrigenSim.capture_dir)) do |org_file|
|
30
30
|
@org_file = org_file
|
31
31
|
if update_capture?
|
32
32
|
@sim_delay = true
|
data/lib/origen_sim/simulator.rb
CHANGED
@@ -21,7 +21,7 @@ module OrigenSim
|
|
21
21
|
|
22
22
|
# These config attributes are accepted by OrigenSim, but cannot be
|
23
23
|
# 'Marshal-ed'.
|
24
|
-
NON_DATA_CONFIG_ATTRIBUTES = [:post_process_run_cmd]
|
24
|
+
NON_DATA_CONFIG_ATTRIBUTES = [:post_process_run_cmd, :post_process_view_wave_cmd, :post_process_probe_cmd]
|
25
25
|
|
26
26
|
TIMESCALES = { -15 => '1fs',
|
27
27
|
-14 => '10fs',
|
@@ -86,6 +86,26 @@ module OrigenSim
|
|
86
86
|
config[:post_process_run_cmd]
|
87
87
|
end
|
88
88
|
|
89
|
+
def post_process_view_wave_cmd
|
90
|
+
config[:post_process_view_wave_cmd]
|
91
|
+
end
|
92
|
+
|
93
|
+
def post_process_probe_cmd
|
94
|
+
config[:post_process_probe_cmd]
|
95
|
+
end
|
96
|
+
|
97
|
+
def post_process_probe_cmd?
|
98
|
+
!post_process_probe_cmd.nil?
|
99
|
+
end
|
100
|
+
|
101
|
+
def force_config_update?
|
102
|
+
!!config[:force_config_update]
|
103
|
+
end
|
104
|
+
|
105
|
+
def debug_path
|
106
|
+
config[:debug_module_path] || 'debug'
|
107
|
+
end
|
108
|
+
|
89
109
|
def fetch_simulation_objects(options = {})
|
90
110
|
sid = options[:id] || id
|
91
111
|
ldir = "#{Origen.root}/simulation/#{sid}"
|
@@ -166,8 +186,8 @@ module OrigenSim
|
|
166
186
|
clear_artifacts
|
167
187
|
|
168
188
|
# Add any artifacts in the given artifact path
|
169
|
-
if Dir.exist?(default_artifact_dir)
|
170
|
-
default_artifact_dir.children.each { |a| artifact(a.basename.to_s, target: a) }
|
189
|
+
if Dir.exist?(self.class.default_artifact_dir)
|
190
|
+
self.class.default_artifact_dir.children.each { |a| artifact(a.basename.to_s, target: a) }
|
171
191
|
end
|
172
192
|
|
173
193
|
# Add any artifacts from the target-specific path (simulation/<target>/artifacts). Files of the same name
|
@@ -197,7 +217,7 @@ module OrigenSim
|
|
197
217
|
self
|
198
218
|
end
|
199
219
|
|
200
|
-
def default_artifact_dir
|
220
|
+
def self.default_artifact_dir
|
201
221
|
# Removed this from a constant at the top of the file since it gave boot errors when the file was
|
202
222
|
# being required while Origen.app was still loading
|
203
223
|
Pathname("#{Origen.app.root}/simulation/application/artifacts")
|
@@ -212,7 +232,7 @@ module OrigenSim
|
|
212
232
|
end
|
213
233
|
|
214
234
|
def target_artifact_dir
|
215
|
-
Pathname(@configuration[:target_artifact_dir] || "#{Origen.app.root}/simulation
|
235
|
+
Pathname(@configuration[:target_artifact_dir] || "#{Origen.app.root}/simulation/").join("#{id}/artifacts")
|
216
236
|
end
|
217
237
|
|
218
238
|
def artifact_run_dir
|
@@ -253,9 +273,11 @@ module OrigenSim
|
|
253
273
|
# be checked into your Origen app's repository
|
254
274
|
def compiled_dir
|
255
275
|
@compiled_dir ||= begin
|
256
|
-
|
257
|
-
|
258
|
-
|
276
|
+
config[:compiled_dir] || begin
|
277
|
+
d = "#{Origen.root}/simulation/#{id}/#{config[:vendor]}"
|
278
|
+
FileUtils.mkdir_p(d)
|
279
|
+
d
|
280
|
+
end
|
259
281
|
end
|
260
282
|
end
|
261
283
|
|
@@ -323,24 +345,46 @@ module OrigenSim
|
|
323
345
|
when :cadence
|
324
346
|
input_file = "#{tmp_dir}/#{wave_file_basename}.tcl"
|
325
347
|
if !File.exist?(input_file) || config_changed?
|
348
|
+
probe_cmd = "probe -create -shm #{testbench_top} -depth all -database waves"
|
349
|
+
if post_process_probe_cmd?
|
350
|
+
probe_cmd = post_process_probe_cmd.call(probe_cmd, self, fast_probe: false)
|
351
|
+
end
|
352
|
+
|
326
353
|
Origen.app.runner.launch action: :compile,
|
327
354
|
files: "#{Origen.root!}/templates/probe.tcl.erb",
|
328
355
|
output: tmp_dir,
|
329
356
|
check_for_changes: false,
|
330
357
|
quiet: true,
|
331
|
-
options: { dir:
|
358
|
+
options: { dir: wave_dir,
|
359
|
+
wave_file: wave_file_basename,
|
360
|
+
force: config[:force],
|
361
|
+
setup: config[:setup],
|
362
|
+
tcl_inputs: config[:tcl_inputs],
|
363
|
+
probe_cmd: probe_cmd
|
364
|
+
},
|
332
365
|
output_file_name: "#{wave_file_basename}.tcl",
|
333
366
|
preserve_target: true
|
334
367
|
end
|
368
|
+
|
335
369
|
input_file_fast = "#{tmp_dir}/#{wave_file_basename}_fast.tcl"
|
336
370
|
if !File.exist?(input_file_fast) || config_changed?
|
337
371
|
fast_probe_depth = config[:fast_probe_depth] || 1
|
372
|
+
probe_cmd = "probe -create -shm #{testbench_top} -depth #{fast_probe_depth} -database waves"
|
373
|
+
if post_process_probe_cmd?
|
374
|
+
probe_cmd = post_process_probe_cmd.call(probe_cmd, self, fast_probe: true)
|
375
|
+
end
|
376
|
+
|
338
377
|
Origen.app.runner.launch action: :compile,
|
339
378
|
files: "#{Origen.root!}/templates/probe.tcl.erb",
|
340
379
|
output: tmp_dir,
|
341
380
|
check_for_changes: false,
|
342
381
|
quiet: true,
|
343
|
-
options: { dir:
|
382
|
+
options: { dir: wave_dir,
|
383
|
+
wave_file: wave_file_basename,
|
384
|
+
force: config[:force],
|
385
|
+
setup: config[:setup],
|
386
|
+
probe_cmd: probe_cmd
|
387
|
+
},
|
344
388
|
output_file_name: "#{wave_file_basename}_fast.tcl",
|
345
389
|
preserve_target: true
|
346
390
|
end
|
@@ -353,10 +397,11 @@ module OrigenSim
|
|
353
397
|
cmd += " -nclibdirpath #{compiled_dir}"
|
354
398
|
|
355
399
|
when :synopsys
|
400
|
+
syn_comp_n = config[:synopsys_compiled_name] || 'simv'
|
356
401
|
if configuration[:verdi]
|
357
|
-
cmd = "#{compiled_dir}
|
402
|
+
cmd = "#{compiled_dir}/#{syn_comp_n} +socket+#{socket_id} +FSDB_ON +fsdbfile+#{Origen.root}/waves/#{id}/#{wave_file_basename}.fsdb +memcbk +vcsd"
|
358
403
|
else
|
359
|
-
cmd = "#{compiled_dir}
|
404
|
+
cmd = "#{compiled_dir}/#{syn_comp_n} +socket+#{socket_id} -vpd_file #{wave_file_basename}.vpd"
|
360
405
|
end
|
361
406
|
|
362
407
|
when :generic
|
@@ -478,6 +523,10 @@ module OrigenSim
|
|
478
523
|
Origen.log.warn "OrigenSim does not know the command to view waveforms for vendor :#{config[:vendor]}!"
|
479
524
|
|
480
525
|
end
|
526
|
+
|
527
|
+
cmd = post_process_view_wave_cmd.call(cmd, self) if post_process_view_wave_cmd
|
528
|
+
fail "OrigenSim: :post_process_view_wave_cmd returned object of class #{cmd.class}. Must return a String." unless cmd.is_a?(String)
|
529
|
+
|
481
530
|
cmd
|
482
531
|
end
|
483
532
|
|
@@ -894,13 +943,13 @@ module OrigenSim
|
|
894
943
|
|
895
944
|
def error(message)
|
896
945
|
simulation.logged_errors = true
|
897
|
-
poke "#{testbench_top}.
|
946
|
+
poke "#{testbench_top}.#{debug_path}.errors", error_count + 1
|
898
947
|
log message, :error
|
899
948
|
end
|
900
949
|
|
901
950
|
# Returns the current simulation error count
|
902
951
|
def error_count
|
903
|
-
peek("#{testbench_top}.
|
952
|
+
peek("#{testbench_top}.#{debug_path}.errors").to_i
|
904
953
|
end
|
905
954
|
|
906
955
|
# Returns the current value of the given net, or nil if the given path does not
|
@@ -1079,7 +1128,7 @@ module OrigenSim
|
|
1079
1128
|
|
1080
1129
|
# Returns true if the config has been changed since the last time we called save_config_signature
|
1081
1130
|
def config_changed?
|
1082
|
-
Origen.app.session.origen_sim["#{id}_config"] != config.except(*NON_DATA_CONFIG_ATTRIBUTES)
|
1131
|
+
config[:force_config_update] || Origen.app.session.origen_sim["#{id}_config"] != config.except(*NON_DATA_CONFIG_ATTRIBUTES)
|
1083
1132
|
end
|
1084
1133
|
|
1085
1134
|
# Locally saves a signature for the current config, this will cause config_changed? to return false
|
@@ -1142,7 +1191,7 @@ module OrigenSim
|
|
1142
1191
|
|
1143
1192
|
def match_errors
|
1144
1193
|
if dut_version > '0.15.0'
|
1145
|
-
peek("#{testbench_top}.
|
1194
|
+
peek("#{testbench_top}.#{debug_path}.match_errors").to_i
|
1146
1195
|
else
|
1147
1196
|
peek("#{testbench_top}.pins.match_errors").to_i
|
1148
1197
|
end
|
@@ -1153,7 +1202,7 @@ module OrigenSim
|
|
1153
1202
|
unless val.nil?
|
1154
1203
|
# All zeros seems to be what an empty string is returned from the VPI,
|
1155
1204
|
# Otherwise, break the string up into 8-bit chunks and decode the ASCII>
|
1156
|
-
val = (val.to_s == 'b00000000' ? '' : val.to_s[1..-1].scan(/.{1,8}/).collect { |char| char.to_i(2).chr }.join)
|
1205
|
+
val = (val.to_s == 'b00000000' ? '' : val.to_s[1..-1].scan(/.{1,8}/).select { |char| char != '00000000' }.collect { |char| char.to_i(2).chr }.join)
|
1157
1206
|
end
|
1158
1207
|
val
|
1159
1208
|
end
|
@@ -1167,7 +1216,7 @@ module OrigenSim
|
|
1167
1216
|
end
|
1168
1217
|
|
1169
1218
|
def marker=(val)
|
1170
|
-
poke("#{testbench_top}.
|
1219
|
+
poke("#{testbench_top}.#{debug_path}.marker", val)
|
1171
1220
|
end
|
1172
1221
|
|
1173
1222
|
def start_read_reg_transaction
|
@@ -1204,14 +1253,73 @@ module OrigenSim
|
|
1204
1253
|
end
|
1205
1254
|
end
|
1206
1255
|
|
1256
|
+
# Returns true if the snapshot has been compiled with some kind of REAL support.
|
1257
|
+
# Not picky about what type of real support though.
|
1258
|
+
def real?
|
1259
|
+
@real ||= begin
|
1260
|
+
if dut_version > '0.19.0' && dut_version < '0.20.3'
|
1261
|
+
# These versions of OrigenSim only support WREAL
|
1262
|
+
if wreal?
|
1263
|
+
@real_type = :wreal
|
1264
|
+
true
|
1265
|
+
else
|
1266
|
+
false
|
1267
|
+
end
|
1268
|
+
elsif dut_version >= '0.20.3'
|
1269
|
+
# These versions support multiple REAL types.
|
1270
|
+
if peek_str("#{testbench_top}.#{debug_path}.real_type").nil?
|
1271
|
+
@real_type = false
|
1272
|
+
else
|
1273
|
+
@real_type = peek_str("#{testbench_top}.#{debug_path}.real_type").to_sym
|
1274
|
+
peek("#{testbench_top}.#{debug_path}.real_enabled").to_i == 1
|
1275
|
+
end
|
1276
|
+
else
|
1277
|
+
# Older version don't support REAL at all
|
1278
|
+
@real_type = false
|
1279
|
+
false
|
1280
|
+
end
|
1281
|
+
end
|
1282
|
+
end
|
1283
|
+
alias_method :real_enabled?, :real?
|
1284
|
+
|
1285
|
+
# Returns the type of REAL support or <code>false</code> if no REAL support is enabled.
|
1286
|
+
# @note Calling {#real?} will set the value of <code>real_type</code> appropriately
|
1287
|
+
def real_type
|
1288
|
+
@real_type || begin
|
1289
|
+
real?
|
1290
|
+
@real_type
|
1291
|
+
end
|
1292
|
+
end
|
1293
|
+
|
1207
1294
|
# Returns true if the snapshot has been compiled with WREAL support
|
1208
1295
|
def wreal?
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1296
|
+
if dut_version > '0.19.0' && dut_version < '0.20.3'
|
1297
|
+
@wreal ||= peek("#{testbench_top}.#{debug_path}.wreal_enabled").to_i == 1
|
1298
|
+
elsif dut_version >= '0.20.3'
|
1299
|
+
puts 'wreal?'.cyan
|
1300
|
+
puts @real_type.class
|
1301
|
+
puts @real_type[0]
|
1302
|
+
puts @real_type.to_s.size
|
1303
|
+
puts 'wreal'.size
|
1304
|
+
puts @real_type.to_s == 'wreal'
|
1305
|
+
(@real_type || begin
|
1306
|
+
real?
|
1307
|
+
@real_type
|
1308
|
+
end) == :wreal
|
1309
|
+
else
|
1310
|
+
false
|
1311
|
+
end
|
1212
1312
|
end
|
1213
1313
|
alias_method :wreal_enabled?, :wreal?
|
1214
1314
|
|
1315
|
+
def wrealavg?
|
1316
|
+
(@real_type || begin
|
1317
|
+
real?
|
1318
|
+
@real_type
|
1319
|
+
end) == :wrealavg
|
1320
|
+
end
|
1321
|
+
alias_method :wrealavg_enabled?, :wrealavg?
|
1322
|
+
|
1215
1323
|
private
|
1216
1324
|
|
1217
1325
|
# Will be called when the simulator has aborted due to the max error count being exceeded
|
data/lib/origen_sim/tester.rb
CHANGED
@@ -41,9 +41,25 @@ module OrigenSim
|
|
41
41
|
end
|
42
42
|
@sync_pins.map do |pin|
|
43
43
|
if @sync_cycles.size == 1
|
44
|
-
simulator.peek("#{simulator.testbench_top}.pins.#{pin.id}.sync_memory")[0]
|
44
|
+
b = simulator.peek("#{simulator.testbench_top}.pins.#{pin.id}.sync_memory")[0]
|
45
|
+
if b.is_a?(Integer)
|
46
|
+
b
|
47
|
+
else
|
48
|
+
Origen.log.warning "The data captured on pin #{pin.id} was undefined (X or Z), the captured value is not correct!"
|
49
|
+
0
|
50
|
+
end
|
45
51
|
else
|
46
|
-
|
52
|
+
val = 0
|
53
|
+
mem = simulator.peek("#{simulator.testbench_top}.pins.#{pin.id}.sync_memory")
|
54
|
+
@sync_cycles.times do |i|
|
55
|
+
b = mem[i]
|
56
|
+
if b.is_a?(Integer)
|
57
|
+
val |= b << i
|
58
|
+
else
|
59
|
+
Origen.log.warning "The data captured on cycle #{i} of pin #{pin.id} was undefined (X or Z), the captured value is not correct!"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
val
|
47
63
|
end
|
48
64
|
end
|
49
65
|
end
|
@@ -65,11 +81,15 @@ module OrigenSim
|
|
65
81
|
simulator.flush(*args)
|
66
82
|
end
|
67
83
|
|
68
|
-
def set_timeset(name, period_in_ns)
|
84
|
+
def set_timeset(name, period_in_ns = nil)
|
69
85
|
super
|
86
|
+
|
70
87
|
# Need to remove this once OrigenTesters does it
|
71
|
-
|
72
|
-
|
88
|
+
# OrigenTesters with decompiler supports this.
|
89
|
+
if period_in_ns
|
90
|
+
dut.timeset = name
|
91
|
+
dut.current_timeset_period = period_in_ns
|
92
|
+
end
|
73
93
|
|
74
94
|
# Now update the simulator with the new waves
|
75
95
|
simulator.on_timeset_changed
|
@@ -166,25 +186,21 @@ module OrigenSim
|
|
166
186
|
if options[:pin2]
|
167
187
|
expected_val2 = options[:state2] == :high ? 1 : 0
|
168
188
|
end
|
169
|
-
|
170
|
-
|
171
|
-
|
189
|
+
matched = false
|
190
|
+
start_cycle = cycle_count
|
191
|
+
resolution = match_loop_resolution(timeout_in_cycles, options)
|
192
|
+
until matched || cycle_count > start_cycle + timeout_in_cycles
|
193
|
+
resolution.cycles
|
172
194
|
current_val = simulator.peek("dut.#{pin.rtl_name}").to_i
|
173
195
|
if options[:pin2]
|
174
196
|
current_val2 = simulator.peek("dut.#{options[:pin2].rtl_name}").to_i
|
175
|
-
|
176
|
-
timed_out = false
|
177
|
-
break
|
178
|
-
end
|
197
|
+
matched = current_val == expected_val || current_val2 == expected_val2
|
179
198
|
else
|
180
|
-
|
181
|
-
timed_out = false
|
182
|
-
break
|
183
|
-
end
|
199
|
+
matched = current_val == expected_val
|
184
200
|
end
|
185
201
|
end
|
186
202
|
# Final assertion to make the pattern fail if the loop timed out
|
187
|
-
|
203
|
+
unless matched
|
188
204
|
pin.restore_state do
|
189
205
|
pin.assert!(expected_val)
|
190
206
|
end
|
@@ -207,23 +223,22 @@ module OrigenSim
|
|
207
223
|
else
|
208
224
|
match_conditions.add(&block)
|
209
225
|
end
|
210
|
-
|
226
|
+
matched = false
|
227
|
+
start_cycle = cycle_count
|
228
|
+
resolution = match_loop_resolution(timeout_in_cycles, options)
|
211
229
|
simulator.match_loop do
|
212
|
-
|
213
|
-
|
230
|
+
until matched || cycle_count > start_cycle + timeout_in_cycles
|
231
|
+
resolution.cycles
|
214
232
|
# Consider the match resolved if any condition can execute without generating errors
|
215
|
-
|
233
|
+
matched = match_conditions.any? do |condition|
|
216
234
|
e = simulator.match_errors
|
217
235
|
condition.call
|
218
236
|
e == simulator.match_errors
|
219
237
|
end
|
220
|
-
timed_out = false
|
221
|
-
break
|
222
|
-
end
|
223
238
|
end
|
224
239
|
end
|
225
240
|
# Final execution to make the pattern fail if the loop timed out
|
226
|
-
|
241
|
+
unless matched
|
227
242
|
if fail_conditions.instance_variable_get(:@block_args).empty?
|
228
243
|
match_conditions.each(&:call)
|
229
244
|
else
|
@@ -232,6 +247,27 @@ module OrigenSim
|
|
232
247
|
end
|
233
248
|
end
|
234
249
|
|
250
|
+
# @api private
|
251
|
+
def match_loop_resolution(timeout_in_cycles, options)
|
252
|
+
if options[:resolution]
|
253
|
+
if options[:resolution].is_a?(Hash)
|
254
|
+
return time_to_cycles(options[:resolution])
|
255
|
+
else
|
256
|
+
return options[:resolution]
|
257
|
+
end
|
258
|
+
else
|
259
|
+
# Used to use the supplied timeout / 10, thinking that the supplied number would be
|
260
|
+
# roughly how long it would take. However, found that when users didn't know the timeout
|
261
|
+
# they would just put in really large numbers, like 1sec, which would mean we would not
|
262
|
+
# check until 100ms for an operation that might be done after 100us.
|
263
|
+
# So now if the old default comes out less than the new one, then use it, otherwise use
|
264
|
+
# the newer more fine-grained default.
|
265
|
+
old_default = timeout_in_cycles / 10
|
266
|
+
new_default = time_to_cycles(time_in_us: 100)
|
267
|
+
return old_default < new_default ? old_default : new_default
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
235
271
|
def wait(*args)
|
236
272
|
super
|
237
273
|
if Origen.running_interactively? ||
|
data/lib/origen_sim.rb
CHANGED
@@ -64,6 +64,15 @@ module OrigenSim
|
|
64
64
|
'disconnected' => -2
|
65
65
|
}
|
66
66
|
|
67
|
+
FORCE_PIN_TYPES_MAPPING = {
|
68
|
+
'real' => :analog,
|
69
|
+
'ana' => :analog,
|
70
|
+
'analog' => :analog,
|
71
|
+
|
72
|
+
'dig' => :digital,
|
73
|
+
'digital' => :digital
|
74
|
+
}
|
75
|
+
|
67
76
|
def self.__instantiate_simulator__
|
68
77
|
@simulator ||= Simulator.new
|
69
78
|
end
|
@@ -216,6 +225,10 @@ module OrigenSim
|
|
216
225
|
Origen.load_application
|
217
226
|
Origen.app.load_target!
|
218
227
|
|
228
|
+
unless tester.simulator?
|
229
|
+
Origen.app!.fail!(message: 'OrigenSim.run cannot be used when the simulator is not the current tester!')
|
230
|
+
end
|
231
|
+
|
219
232
|
# Start up the simulator and run whatever's in the target block.
|
220
233
|
# After the block completes, shutdown the simulator
|
221
234
|
tester.simulator.setup_simulation(name)
|
data/lib/origen_sim_dev/dut.rb
CHANGED
@@ -35,6 +35,10 @@ module OrigenSimDev
|
|
35
35
|
w.drive 0, at: 0
|
36
36
|
w.drive :data, at: 'period / 2'
|
37
37
|
end
|
38
|
+
# Generate drive timing that has only a data event which isn't at t0
|
39
|
+
t.wave :din_port do |w|
|
40
|
+
w.drive :data, at: 'period / 2'
|
41
|
+
end
|
38
42
|
end
|
39
43
|
|
40
44
|
add_reg :dr, 0x0, size: 66 do |reg|
|
data/pattern/test.rb
CHANGED
@@ -127,7 +127,7 @@ Pattern.create do
|
|
127
127
|
peek("dut.real_val", 1.25)
|
128
128
|
end
|
129
129
|
|
130
|
-
if tester.simulator.wreal?
|
130
|
+
if tester.simulator.wreal? || tester.simulator.wrealavg?
|
131
131
|
ss "Test analog pin API by ramping dut.vdd"
|
132
132
|
v = 0
|
133
133
|
dut.power_pin(:vdd).drive!(v)
|
@@ -218,6 +218,13 @@ Pattern.create do
|
|
218
218
|
60.cycles
|
219
219
|
end
|
220
220
|
|
221
|
+
ss "Test timing implementation - drive timing, single data event only, not at t0"
|
222
|
+
dut.pins(:din_port).dont_care
|
223
|
+
tester.cycle
|
224
|
+
dut.pins(:din_port).drive! 1
|
225
|
+
dut.pins(:din_port).drive! 0
|
226
|
+
dut.pins(:din_port).drive! 1
|
227
|
+
|
221
228
|
ss "Test the command works with static vectors"
|
222
229
|
dut.pin(:done).assert!(1)
|
223
230
|
dut.pin(:done).dont_care
|
@@ -262,7 +269,7 @@ Pattern.create do
|
|
262
269
|
5.cycles
|
263
270
|
dut.pin(:done).assert!(0)
|
264
271
|
dut.pin(:done).dont_care
|
265
|
-
tester.wait match: true,
|
272
|
+
tester.wait match: true, time_in_s: 2 do
|
266
273
|
dut.pin(:done).assert!(1)
|
267
274
|
end
|
268
275
|
dut.pin(:done).assert!(1)
|
@@ -28,6 +28,14 @@ normally have two options:
|
|
28
28
|
Both of these are fully supported by OrigenSim, see the
|
29
29
|
[Timing and Waiting guide](<%= path "guides/pattern/timing" %>) for more information on these APIs.
|
30
30
|
|
31
|
+
<div class="alert alert-info" role="alert"> <strong>A Note on Match Loops</strong>
|
32
|
+
<br>
|
33
|
+
When waiting for a match, the DUT will be polled every 100us by default or timeout / 10 if that
|
34
|
+
is less than 100us.
|
35
|
+
If you need it to poll more often (at the expense of simulation speed) then a `:resolution` option can
|
36
|
+
be supplied in the same way as described for the `sim_delay` method below.
|
37
|
+
</div>
|
38
|
+
|
31
39
|
However, if your pattern generation flow is going to be supported by simulation, then you also have
|
32
40
|
a third option - to derive the required wait time from the simulation itself.
|
33
41
|
|
data/templates/probe.tcl.erb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
database -open waves -into <%= options[:dir] %>/<%= options[:wave_file] %> -default -event
|
2
|
-
|
3
|
-
#probe -create -assertions -transaction origen -depth all -database waves
|
2
|
+
<%= options[:probe_cmd] %>
|
4
3
|
% Array(options[:tcl_inputs]).each do |line|
|
5
4
|
<%= line %>
|
6
5
|
% end
|