origen_sim 0.5.5 → 0.6.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/application.rb +12 -1
- data/config/commands.rb +31 -10
- data/config/global_commands.rb +12 -0
- data/config/shared_commands.rb +11 -4
- data/config/version.rb +2 -2
- data/ext/bridge.c +18 -8
- data/ext/client.c +1 -1
- data/ext/defines.h.erb +6 -0
- data/ext/origen.c +6 -6
- data/lib/origen_sim/commands/build.rb +119 -81
- data/lib/origen_sim/commands/ci.rb +36 -0
- data/lib/origen_sim/commands/co.rb +36 -0
- data/lib/origen_sim/origen/pins/pin.rb +7 -13
- data/lib/origen_sim/origen_testers/api.rb +66 -0
- data/lib/origen_sim/simulator.rb +123 -43
- data/lib/origen_sim_dev/dut.rb +6 -4
- data/pattern/test.rb +28 -16
- data/templates/empty.gtkw +26 -0
- data/templates/rtl_v/origen.v.erb +10 -49
- metadata +24 -6
- data/ext/README.md +0 -2
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'origen/commands/helpers'
|
3
|
+
|
4
|
+
options = {}
|
5
|
+
|
6
|
+
# App options are options that the application can supply to extend this command
|
7
|
+
app_options = @application_options || []
|
8
|
+
opt_parser = OptionParser.new do |opts|
|
9
|
+
opts.banner = <<-EOT
|
10
|
+
Checkin the simulation object for the current or given environment/target.
|
11
|
+
|
12
|
+
Note that this will commit whatever is in your workspace as the latest version, regardless
|
13
|
+
of whether there exists any more recent version in the repository.
|
14
|
+
|
15
|
+
Usage: origen sim:ci [options]
|
16
|
+
EOT
|
17
|
+
opts.on('-e', '--environment NAME', String, 'Override the default environment, NAME can be a full path or a fragment of an environment file name') { |e| options[:environment] = e }
|
18
|
+
opts.on('-t', '--target NAME', String, 'Override the default target, NAME can be a full path or a fragment of a target file name') { |t| options[:target] = t }
|
19
|
+
opts.on('-d', '--debugger', 'Enable the debugger') { options[:debugger] = true }
|
20
|
+
# Apply any application option extensions to the OptionParser
|
21
|
+
opts.separator ''
|
22
|
+
opts.on('-h', '--help', 'Show this message') { puts opts; exit }
|
23
|
+
end
|
24
|
+
|
25
|
+
opt_parser.parse! ARGV
|
26
|
+
|
27
|
+
Origen.environment.temporary = options[:environment] if options[:environment]
|
28
|
+
Origen.target.temporary = options[:target] if options[:target]
|
29
|
+
Origen.load_target
|
30
|
+
|
31
|
+
unless tester.sim?
|
32
|
+
Origen.log.error 'To run the sim:ci command your target/environment must instantiate an OrigenSim::Tester'
|
33
|
+
exit 1
|
34
|
+
end
|
35
|
+
|
36
|
+
tester.simulator.commit_simulation_objects(options)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'origen/commands/helpers'
|
3
|
+
|
4
|
+
options = {}
|
5
|
+
|
6
|
+
# App options are options that the application can supply to extend this command
|
7
|
+
app_options = @application_options || []
|
8
|
+
opt_parser = OptionParser.new do |opts|
|
9
|
+
opts.banner = <<-EOT
|
10
|
+
Checkout the simulation object for the current or given environment/target.
|
11
|
+
|
12
|
+
Note that this will force a new checkout and will overwrite whatever is in your workspace.
|
13
|
+
|
14
|
+
Usage: origen sim:co [options]
|
15
|
+
EOT
|
16
|
+
opts.on('-e', '--environment NAME', String, 'Override the default environment, NAME can be a full path or a fragment of an environment file name') { |e| options[:environment] = e }
|
17
|
+
opts.on('-t', '--target NAME', String, 'Override the default target, NAME can be a full path or a fragment of a target file name') { |t| options[:target] = t }
|
18
|
+
opts.on('-d', '--debugger', 'Enable the debugger') { options[:debugger] = true }
|
19
|
+
# Apply any application option extensions to the OptionParser
|
20
|
+
opts.separator ''
|
21
|
+
opts.on('-h', '--help', 'Show this message') { puts opts; exit }
|
22
|
+
end
|
23
|
+
|
24
|
+
opt_parser.parse! ARGV
|
25
|
+
|
26
|
+
Origen.environment.temporary = options[:environment] if options[:environment]
|
27
|
+
Origen.target.temporary = options[:target] if options[:target]
|
28
|
+
Origen.load_target
|
29
|
+
|
30
|
+
unless tester.sim?
|
31
|
+
Origen.log.error 'To run the sim:co command your target/environment must instantiate an OrigenSim::Tester'
|
32
|
+
exit 1
|
33
|
+
end
|
34
|
+
|
35
|
+
options[:force] = true
|
36
|
+
tester.simulator.fetch_simulation_objects(options)
|
@@ -5,24 +5,12 @@ module Origen
|
|
5
5
|
class Pin
|
6
6
|
# The index number that is used to refer to the pin within the simulation
|
7
7
|
attr_accessor :simulation_index
|
8
|
-
# When generating a testbench the top-level signal will be tied off to the given
|
9
|
-
# logic level if this is set to 0 or 1
|
10
|
-
attr_accessor :tie_off
|
11
8
|
|
12
9
|
alias_method :_orig_initialize, :initialize
|
13
10
|
def initialize(id, owner, options = {})
|
14
|
-
@tie_off = options[:tie_off]
|
15
11
|
_orig_initialize(id, owner, options)
|
16
12
|
end
|
17
13
|
|
18
|
-
def rtl_name
|
19
|
-
if primary_group
|
20
|
-
(@rtl_name || primary_group.id).to_s
|
21
|
-
else
|
22
|
-
(@rtl_name || id).to_s
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
14
|
alias_method :_orig_set_value, :set_value
|
27
15
|
def set_value(val)
|
28
16
|
ret = _orig_set_value(val)
|
@@ -63,10 +51,16 @@ module Origen
|
|
63
51
|
@simulator_value = nil
|
64
52
|
end
|
65
53
|
|
54
|
+
def apply_force
|
55
|
+
if force
|
56
|
+
simulator.put("2^#{simulation_index}^#{force}")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
66
60
|
# Applies the current pin state to the simulation, this is triggered everytime
|
67
61
|
# the pin state or value changes
|
68
62
|
def update_simulation
|
69
|
-
return if
|
63
|
+
return if force || !simulation_index || !tester.timeset || !simulator_needs_update?
|
70
64
|
case state
|
71
65
|
when :drive
|
72
66
|
@simulator_state = :drive
|
@@ -7,5 +7,71 @@ module OrigenTesters
|
|
7
7
|
is_a?(OrigenSim::Tester)
|
8
8
|
end
|
9
9
|
alias_method :simulator?, :sim?
|
10
|
+
|
11
|
+
def sim_capture(id, *pins)
|
12
|
+
if @sim_capture
|
13
|
+
fail 'Nesting of sim_capture blocks is not yet supported!'
|
14
|
+
end
|
15
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
16
|
+
pins = pins.map { |p| p.is_a?(String) || p.is_a?(Symbol) ? dut.pin(p) : p }
|
17
|
+
pins.each(&:save)
|
18
|
+
@sim_capture = pins.map { |p| [p, "origen.dut.#{p.rtl_name}"] }
|
19
|
+
Origen::OrgFile.open(id) do |org_file|
|
20
|
+
@org_file = org_file
|
21
|
+
if update_capture?
|
22
|
+
@sim_capture.each { |pin, net| pin.record_to_org_file(only: :assert) }
|
23
|
+
end
|
24
|
+
yield
|
25
|
+
end
|
26
|
+
pins.each(&:restore)
|
27
|
+
@sim_capture = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
alias_method :_origen_testers_cycle, :cycle
|
31
|
+
def cycle(options = {})
|
32
|
+
if @sim_capture
|
33
|
+
# Need to un-roll all repeats to be sure we observe the true data, can't
|
34
|
+
# really assume that it will be constant for all cycles covered by the repeat
|
35
|
+
cycles = options.delete(:repeat) || 1
|
36
|
+
cycles.times do
|
37
|
+
if update_capture?
|
38
|
+
_origen_testers_cycle(options)
|
39
|
+
@sim_capture.each do |pin, net|
|
40
|
+
pin.assert(simulator.peek(net))
|
41
|
+
# Remove the assertion since it is for the previous cycle in terms of the current simulation,
|
42
|
+
# this won't be captured to the org file
|
43
|
+
pin.dont_care
|
44
|
+
end
|
45
|
+
Origen::OrgFile.cycle
|
46
|
+
else
|
47
|
+
unless @org_file.exist?
|
48
|
+
fail "The simulation capture \"#{id}\" has not been made yet, re-run this pattern with a simulation target first!"
|
49
|
+
end
|
50
|
+
apply_captured_data
|
51
|
+
_origen_testers_cycle(options)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
else
|
55
|
+
_origen_testers_cycle(options)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def apply_captured_data
|
60
|
+
if @apply_captured_data_cycles && @apply_captured_data_cycles > 1
|
61
|
+
@apply_captured_data_cycles -= 1
|
62
|
+
else
|
63
|
+
@org_file.read_line do |operations, cycles|
|
64
|
+
@apply_captured_data_cycles = cycles
|
65
|
+
operations.each do |object, operation, *args|
|
66
|
+
object.send(operation, *args)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def update_capture?
|
73
|
+
return @update_capture if defined? @update_capture
|
74
|
+
@update_capture = sim? && (!@org_file.exist? || Origen.app!.update_sim_captures)
|
75
|
+
end
|
10
76
|
end
|
11
77
|
end
|
data/lib/origen_sim/simulator.rb
CHANGED
@@ -22,14 +22,72 @@ module OrigenSim
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
def fetch_simulation_objects(options = {})
|
26
|
+
sid = options[:id] || id
|
27
|
+
ldir = "#{Origen.root}/simulation/#{sid}"
|
28
|
+
tmp_dir = "#{Origen.root}/tmp/origen_sim/tmp"
|
29
|
+
if config[:rc_dir_url]
|
30
|
+
unless config[:rc_version]
|
31
|
+
puts "You must supply an :rc_version option when using :rc_dir_url (you can set this to something like 'Trunk' or 'master' if you want)"
|
32
|
+
exit 1
|
33
|
+
end
|
34
|
+
if !File.exist?(compiled_dir) ||
|
35
|
+
(File.exist?(compiled_dir) && Dir.entries(compiled_dir).size <= 2) ||
|
36
|
+
(Origen.app.session.origen_sim[sid] != config[:rc_version]) ||
|
37
|
+
options[:force]
|
38
|
+
Origen.log.info "Fetching the simulation object for #{sid}..."
|
39
|
+
Origen.app.session.origen_sim[sid] = nil # Clear this up front, if the checkout fails we won't know what we have
|
40
|
+
FileUtils.rm_rf(tmp_dir) if File.exist?(tmp_dir)
|
41
|
+
FileUtils.mkdir_p(tmp_dir)
|
42
|
+
FileUtils.mkdir_p("#{Origen.root}/simulation")
|
43
|
+
rc = Origen::RevisionControl.new remote: config[:rc_dir_url], local: tmp_dir
|
44
|
+
rc.checkout "#{sid}.tar.gz", force: true, version: config[:rc_version]
|
45
|
+
FileUtils.mv "#{tmp_dir}/#{sid}.tar.gz", "#{Origen.root}/simulation"
|
46
|
+
FileUtils.rm_rf(ldir) if File.exist?(ldir)
|
47
|
+
Dir.chdir "#{Origen.root}/simulation/" do
|
48
|
+
system "tar -xvf #{sid}.tar.gz"
|
49
|
+
end
|
50
|
+
Origen.app.session.origen_sim[sid] = config[:rc_version]
|
51
|
+
end
|
52
|
+
else
|
53
|
+
if !File.exist?(compiled_dir) ||
|
54
|
+
(File.exist?(compiled_dir) && Dir.entries(compiled_dir).size <= 2)
|
55
|
+
puts "There is no previously compiled simulation object in: #{compiled_dir}"
|
56
|
+
exit 1
|
57
|
+
end
|
58
|
+
end
|
59
|
+
ensure
|
60
|
+
FileUtils.rm_f "#{ldir}.tar.gz" if File.exist?("#{ldir}.tar.gz")
|
61
|
+
FileUtils.rm_rf tmp_dir if File.exist?(tmp_dir)
|
62
|
+
end
|
63
|
+
|
64
|
+
def commit_simulation_objects(options = {})
|
65
|
+
sid = options[:id] || id
|
66
|
+
ldir = "#{Origen.root}/simulation/#{sid}"
|
67
|
+
tmp_dir = "#{Origen.root}/tmp/origen_sim/tmp"
|
68
|
+
unless File.exist?(ldir)
|
69
|
+
fail "The simulation directory to check in does not exist: #{ldir}"
|
70
|
+
end
|
71
|
+
Dir.chdir "#{Origen.root}/simulation/" do
|
72
|
+
system "tar -cvzf #{sid}.tar.gz #{sid}"
|
73
|
+
end
|
74
|
+
|
75
|
+
FileUtils.rm_rf(tmp_dir) if File.exist?(tmp_dir)
|
76
|
+
FileUtils.mkdir_p(tmp_dir)
|
77
|
+
FileUtils.cp "#{ldir}.tar.gz", tmp_dir
|
78
|
+
|
79
|
+
rc = Origen::RevisionControl.new remote: config[:rc_dir_url], local: tmp_dir
|
80
|
+
rc.checkin "#{sid}.tar.gz", unmanaged: true, force: true, comment: 'Checked in via sim:rc command'
|
81
|
+
ensure
|
82
|
+
FileUtils.rm_f "#{ldir}.tar.gz" if File.exist?("#{ldir}.tar.gz")
|
83
|
+
FileUtils.rm_rf tmp_dir if File.exist?(tmp_dir)
|
84
|
+
end
|
85
|
+
|
25
86
|
def configure(options)
|
26
87
|
fail 'A vendor must be supplied, e.g. OrigenSim::Tester.new(vendor: :icarus)' unless options[:vendor]
|
27
88
|
unless VENDORS.include?(options[:vendor])
|
28
89
|
fail "Unknown vendor #{options[:vendor]}, valid values are: #{VENDORS.map { |v| ':' + v.to_s }.join(', ')}"
|
29
90
|
end
|
30
|
-
unless options[:rtl_top]
|
31
|
-
fail "The name of the file containing the DUT top-level must be supplied, e.g. OrigenSim::Tester.new(rtl_top: 'my_ip')" unless options[:rtl_top]
|
32
|
-
end
|
33
91
|
@configuration = options
|
34
92
|
@tmp_dir = nil
|
35
93
|
end
|
@@ -49,14 +107,6 @@ module OrigenSim
|
|
49
107
|
end
|
50
108
|
end
|
51
109
|
|
52
|
-
def artifacts_dir
|
53
|
-
@artifacts_dir ||= begin
|
54
|
-
d = "#{Origen.root}/simulation/#{id}/artifacts"
|
55
|
-
FileUtils.mkdir_p(d)
|
56
|
-
d
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
110
|
# Returns the directory where the compiled simulation object lives, this should
|
61
111
|
# be checked into your Origen app's repository
|
62
112
|
def compiled_dir
|
@@ -93,20 +143,20 @@ module OrigenSim
|
|
93
143
|
|
94
144
|
def wave_config_file
|
95
145
|
@wave_config_file ||= begin
|
96
|
-
f = "#{wave_config_dir}/#{User.current.id}
|
146
|
+
f = "#{wave_config_dir}/#{User.current.id}.#{wave_config_ext}"
|
97
147
|
unless File.exist?(f)
|
98
148
|
# Take a default wave if one has been set up
|
99
|
-
d = "#{wave_config_dir}/default
|
149
|
+
d = "#{wave_config_dir}/default.#{wave_config_ext}"
|
100
150
|
if File.exist?(d)
|
101
151
|
FileUtils.cp(d, f)
|
102
152
|
else
|
103
153
|
# Otherwise seed it with the latest existing setup by someone else
|
104
|
-
d = Dir.glob("#{wave_config_dir}
|
154
|
+
d = Dir.glob("#{wave_config_dir}/*.#{wave_config_ext}").max { |a, b| File.ctime(a) <=> File.ctime(b) }
|
105
155
|
if d
|
106
156
|
FileUtils.cp(d, f)
|
107
157
|
else
|
108
158
|
# We tried our best, start from scratch
|
109
|
-
d = "#{Origen.root!}/templates/empty
|
159
|
+
d = "#{Origen.root!}/templates/empty.#{wave_config_ext}"
|
110
160
|
FileUtils.cp(d, f)
|
111
161
|
end
|
112
162
|
end
|
@@ -115,15 +165,24 @@ module OrigenSim
|
|
115
165
|
end
|
116
166
|
end
|
117
167
|
|
168
|
+
def wave_config_ext
|
169
|
+
case config[:vendor]
|
170
|
+
when :icarus
|
171
|
+
'gtkw'
|
172
|
+
when :cadence
|
173
|
+
'svcf'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
118
177
|
def run_cmd
|
119
178
|
case config[:vendor]
|
120
179
|
when :icarus
|
121
180
|
cmd = configuration[:vvp] || 'vvp'
|
122
|
-
cmd += " -M#{compiled_dir} -morigen #{compiled_dir}/
|
181
|
+
cmd += " -M#{compiled_dir} -morigen #{compiled_dir}/origen.vvp +socket+#{socket_id}"
|
123
182
|
|
124
183
|
when :cadence
|
125
184
|
input_file = "#{tmp_dir}/#{id}.tcl"
|
126
|
-
|
185
|
+
if !File.exist?(input_file) || config_changed?
|
127
186
|
Origen.app.runner.launch action: :compile,
|
128
187
|
files: "#{Origen.root!}/templates/probe.tcl.erb",
|
129
188
|
output: tmp_dir,
|
@@ -133,7 +192,7 @@ module OrigenSim
|
|
133
192
|
output_file_name: "#{id}.tcl"
|
134
193
|
end
|
135
194
|
input_file_fast = "#{tmp_dir}/#{id}_fast.tcl"
|
136
|
-
if
|
195
|
+
if !File.exist?(input_file_fast) || config_changed?
|
137
196
|
fast_probe_depth = config[:fast_probe_depth] || 1
|
138
197
|
Origen.app.runner.launch action: :compile,
|
139
198
|
files: "#{Origen.root!}/templates/probe.tcl.erb",
|
@@ -143,8 +202,8 @@ module OrigenSim
|
|
143
202
|
options: { dir: wave_dir, force: config[:force], setup: config[:setup], depth: fast_probe_depth },
|
144
203
|
output_file_name: "#{id}_fast.tcl"
|
145
204
|
end
|
146
|
-
|
147
|
-
# input file is already generated
|
205
|
+
save_config_signature
|
206
|
+
wave_dir # Ensure this exists since it won't be referenced above if the input file is already generated
|
148
207
|
|
149
208
|
cmd = configuration[:irun] || 'irun'
|
150
209
|
cmd += " -r origen -snapshot origen +socket+#{socket_id}"
|
@@ -157,6 +216,15 @@ module OrigenSim
|
|
157
216
|
def view_wave_command
|
158
217
|
cmd = nil
|
159
218
|
case config[:vendor]
|
219
|
+
when :icarus
|
220
|
+
edir = Pathname.new(wave_config_dir).relative_path_from(Pathname.pwd)
|
221
|
+
cmd = "cd #{edir} && "
|
222
|
+
cmd += configuration[:gtkwave] || 'gtkwave'
|
223
|
+
dir = Pathname.new(wave_dir).relative_path_from(edir.expand_path)
|
224
|
+
cmd += " #{dir}/origen.vcd "
|
225
|
+
f = Pathname.new(wave_config_file).relative_path_from(edir.expand_path)
|
226
|
+
cmd += " --save #{f} &"
|
227
|
+
|
160
228
|
when :cadence
|
161
229
|
edir = Pathname.new(wave_config_dir).relative_path_from(Pathname.pwd)
|
162
230
|
cmd = "cd #{edir} && "
|
@@ -165,6 +233,7 @@ module OrigenSim
|
|
165
233
|
cmd += " #{dir}/#{id}.dsn #{dir}/#{id}.trn"
|
166
234
|
f = Pathname.new(wave_config_file).relative_path_from(edir.expand_path)
|
167
235
|
cmd += " -input #{f} &"
|
236
|
+
|
168
237
|
end
|
169
238
|
cmd
|
170
239
|
end
|
@@ -178,22 +247,12 @@ module OrigenSim
|
|
178
247
|
end
|
179
248
|
end
|
180
249
|
|
181
|
-
def link_artifacts
|
182
|
-
done = "#{run_dir}/.artifacts_linked"
|
183
|
-
unless File.exist?(done)
|
184
|
-
Dir.foreach(artifacts_dir) do |item|
|
185
|
-
next if item == '.' || item == '..'
|
186
|
-
FileUtils.ln_s("#{artifacts_dir}/#{item}", "#{run_dir}/#{item}") unless File.exist?("#{run_dir}/#{item}")
|
187
|
-
end
|
188
|
-
FileUtils.touch(done)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
250
|
# Starts up the simulator process
|
193
251
|
def start
|
252
|
+
fetch_simulation_objects
|
253
|
+
|
194
254
|
server = UNIXServer.new(socket_id)
|
195
255
|
verbose = Origen.debugger_enabled?
|
196
|
-
link_artifacts
|
197
256
|
cmd = run_cmd + ' & echo \$!'
|
198
257
|
|
199
258
|
launch_simulator = %(
|
@@ -224,7 +283,7 @@ module OrigenSim
|
|
224
283
|
simulator_parent_process = spawn("ruby -e \"#{launch_simulator}\"")
|
225
284
|
Process.detach(simulator_parent_process)
|
226
285
|
|
227
|
-
timeout_connection(config[:startup_timeout] ||
|
286
|
+
timeout_connection(config[:startup_timeout] || 60) do
|
228
287
|
@socket = server.accept
|
229
288
|
@connection_established = true
|
230
289
|
if @connection_timed_out
|
@@ -350,10 +409,11 @@ module OrigenSim
|
|
350
409
|
# set up internal handles to efficiently access them
|
351
410
|
def define_pins
|
352
411
|
dut.rtl_pins.each_with_index do |(name, pin), i|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
412
|
+
pin.simulation_index = i
|
413
|
+
put("0^#{pin.rtl_name}^#{i}^#{pin.drive_wave.index}^#{pin.compare_wave.index}")
|
414
|
+
end
|
415
|
+
dut.rtl_pins.each do |name, pin|
|
416
|
+
pin.apply_force
|
357
417
|
end
|
358
418
|
end
|
359
419
|
|
@@ -407,11 +467,13 @@ module OrigenSim
|
|
407
467
|
|
408
468
|
# Returns the current simulation error count
|
409
469
|
def error_count
|
410
|
-
peek('origen.debug.errors')
|
470
|
+
peek('origen.debug.errors').to_i
|
411
471
|
end
|
412
472
|
|
413
473
|
# Returns the current value of the given net, or nil if the given path does not
|
414
474
|
# resolve to a valid node
|
475
|
+
#
|
476
|
+
# The value is returned as an instance of Origen::Value
|
415
477
|
def peek(net)
|
416
478
|
# The Verilog spec does not specify that underlying VPI put method should
|
417
479
|
# handle a part select, so some simulators do not handle it. Therefore we
|
@@ -427,21 +489,20 @@ module OrigenSim
|
|
427
489
|
|
428
490
|
sync_up
|
429
491
|
put("9^#{clean(net)}")
|
430
|
-
|
431
492
|
m = get.strip
|
493
|
+
|
432
494
|
if m == 'FAIL'
|
433
495
|
return nil
|
434
496
|
else
|
435
|
-
m = m.to_i
|
436
497
|
if msb
|
437
498
|
# Setting a range of bits
|
438
499
|
if lsb
|
439
|
-
m[msb..lsb]
|
500
|
+
Origen::Value.new('b' + m[(m.size - 1 - msb)..(m.size - 1 - lsb)])
|
440
501
|
else
|
441
|
-
m[msb]
|
502
|
+
Origen::Value.new('b' + m[m.size - 1 - msb])
|
442
503
|
end
|
443
504
|
else
|
444
|
-
m
|
505
|
+
Origen::Value.new('b' + m)
|
445
506
|
end
|
446
507
|
end
|
447
508
|
end
|
@@ -587,6 +648,25 @@ module OrigenSim
|
|
587
648
|
@sync_active
|
588
649
|
end
|
589
650
|
|
651
|
+
# Returns true if the config has been changed since the last time we called save_config_signature
|
652
|
+
def config_changed?
|
653
|
+
Origen.app.session.origen_sim["#{id}_config"] != config
|
654
|
+
end
|
655
|
+
|
656
|
+
# Locally saves a signature for the current config, this will cause config_changed? to return false
|
657
|
+
# until its contents change
|
658
|
+
def save_config_signature
|
659
|
+
Origen.app.session.origen_sim["#{id}_config"] = config
|
660
|
+
end
|
661
|
+
|
662
|
+
# Returns the version of Origen Sim that the current DUT object was compiled with
|
663
|
+
def dut_version
|
664
|
+
@dut_version ||= begin
|
665
|
+
put('i^')
|
666
|
+
Origen::VersionString.new(get.strip)
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
590
670
|
private
|
591
671
|
|
592
672
|
def clean(net)
|