origen_sim 0.15.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/application.rb +1 -1
- data/config/shared_commands.rb +13 -4
- data/config/version.rb +1 -1
- data/ext/bridge.c +521 -272
- data/ext/bridge.h +2 -0
- data/ext/defines.h.erb +8 -0
- data/ext/origen.c +2 -0
- data/lib/origen_sim.rb +21 -1
- data/lib/origen_sim/origen/pins/pin.rb +7 -2
- data/lib/origen_sim/origen_testers/api.rb +11 -2
- data/lib/origen_sim/simulation.rb +34 -4
- data/lib/origen_sim/simulator.rb +227 -19
- data/lib/origen_sim/stderr_reader.rb +9 -3
- data/lib/origen_sim/stdout_reader.rb +35 -12
- data/lib/origen_sim/tester.rb +209 -29
- data/lib/origen_sim_dev/dut.rb +31 -29
- data/pattern/test.rb +2 -0
- data/templates/origen_guides/simulation/debugging.md.erb +123 -6
- data/templates/origen_guides/simulation/environment.md.erb +3 -6
- data/templates/origen_guides/simulation/log.md.erb +1 -1
- data/templates/origen_guides/simulation/patterns.md.erb +35 -0
- data/templates/rtl_v/origen.v.erb +14 -49
- metadata +5 -5
data/ext/bridge.h
CHANGED
data/ext/defines.h.erb
CHANGED
@@ -3,5 +3,13 @@
|
|
3
3
|
|
4
4
|
#define ORIGEN_SIM_VERSION "<%= OrigenSim::VERSION %>"
|
5
5
|
#define ORIGEN_SIM_TESTBENCH_NAME "<%= options[:testbench_name] %>"
|
6
|
+
#define LOG_DEBUG 0
|
7
|
+
#define LOG_INFO 1
|
8
|
+
#define LOG_WARN 2
|
9
|
+
#define LOG_WARNING 2
|
10
|
+
#define LOG_SUCCESS 3
|
11
|
+
#define LOG_ERROR 4
|
12
|
+
#define LOG_DEPRECATE 5
|
13
|
+
#define LOG_DEPRECATED 5
|
6
14
|
|
7
15
|
#endif
|
data/ext/origen.c
CHANGED
data/lib/origen_sim.rb
CHANGED
@@ -87,7 +87,7 @@ module OrigenSim
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def self.verbose?
|
90
|
-
!!(@verbose || Origen.
|
90
|
+
!!(@verbose || Origen.log.log_level == :verbose || Origen.running_remotely?)
|
91
91
|
end
|
92
92
|
|
93
93
|
def self.flow=(val)
|
@@ -180,10 +180,30 @@ module OrigenSim
|
|
180
180
|
defined?(@fail_on_stderr) ? @fail_on_stderr : true
|
181
181
|
end
|
182
182
|
|
183
|
+
# Setting the max_errors here will override the value in the simulator environment
|
184
|
+
def self.max_errors=(val)
|
185
|
+
@max_errors = val
|
186
|
+
end
|
187
|
+
|
188
|
+
def self.max_errors
|
189
|
+
@max_errors
|
190
|
+
end
|
191
|
+
|
183
192
|
def self.error(message)
|
184
193
|
simulator.error(message)
|
185
194
|
end
|
186
195
|
|
196
|
+
# Change where sim_delay and sim_capture records are stored
|
197
|
+
def self.capture_dir=(val)
|
198
|
+
@capture_dir = val
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns where sim_delay and sim_capture records are stored, if not set then
|
202
|
+
# Origen.root/pattern/org/<target name> will be used by default
|
203
|
+
def self.capture_dir
|
204
|
+
@capture_dir ||= Origen.root.join('pattern', 'org', Origen.target.name)
|
205
|
+
end
|
206
|
+
|
187
207
|
def self.run(name, options = {}, &block)
|
188
208
|
# Load up the application and target
|
189
209
|
Origen.load_application
|
@@ -19,8 +19,8 @@ module Origen
|
|
19
19
|
end
|
20
20
|
|
21
21
|
alias_method :_orig_set_state, :set_state
|
22
|
-
def set_state(
|
23
|
-
ret = _orig_set_state(
|
22
|
+
def set_state(state)
|
23
|
+
ret = _orig_set_state(state)
|
24
24
|
update_simulation if simulation_running?
|
25
25
|
ret
|
26
26
|
end
|
@@ -67,6 +67,11 @@ module Origen
|
|
67
67
|
@simulator_value = value
|
68
68
|
simulator.put("2^#{simulation_index}^#{value}")
|
69
69
|
when :compare
|
70
|
+
if tester.read_reg_open?
|
71
|
+
tester.read_reg_cycles[tester.cycle_count + 1] ||= {}
|
72
|
+
tester.read_reg_cycles[tester.cycle_count + 1][self] = state_meta
|
73
|
+
tester.read_reg_meta_supplied = true if state_meta[:position]
|
74
|
+
end
|
70
75
|
@simulator_state = :compare
|
71
76
|
@simulator_value = value
|
72
77
|
simulator.put("4^#{simulation_index}^#{value}")
|
@@ -8,6 +8,15 @@ module OrigenTesters
|
|
8
8
|
end
|
9
9
|
alias_method :simulator?, :sim?
|
10
10
|
|
11
|
+
def read_register(reg_or_val, options = {})
|
12
|
+
yield
|
13
|
+
end
|
14
|
+
|
15
|
+
# Set a marker in the OrigenSim testbench
|
16
|
+
def marker=(val)
|
17
|
+
simulator.marker = val if sim?
|
18
|
+
end
|
19
|
+
|
11
20
|
def sim_delay(id, options = {}, &block)
|
12
21
|
if sim? && dut_version <= '0.12.0'
|
13
22
|
OrigenSim.error "Use of sim_delay requires a DUT model compiled with OrigenSim version > 0.12.0, the current dut was compiled with #{dut_version}"
|
@@ -17,7 +26,7 @@ module OrigenTesters
|
|
17
26
|
if @sim_capture || @sim_delay
|
18
27
|
fail 'Nesting of sim_capture and/or sim_delay blocks is not yet supported!'
|
19
28
|
end
|
20
|
-
Origen::OrgFile.open(id) do |org_file|
|
29
|
+
Origen::OrgFile.open(id, path: OrigenSim.capture_dir) do |org_file|
|
21
30
|
@org_file = org_file
|
22
31
|
if update_capture?
|
23
32
|
@sim_delay = true
|
@@ -81,7 +90,7 @@ module OrigenTesters
|
|
81
90
|
pins = pins.map { |p| p.is_a?(String) || p.is_a?(Symbol) ? dut.pin(p) : p }
|
82
91
|
pins.each(&:save)
|
83
92
|
@sim_capture = pins.map { |p| [p, "origen.dut.#{p.rtl_name}"] }
|
84
|
-
Origen::OrgFile.open(id) do |org_file|
|
93
|
+
Origen::OrgFile.open(id, path: OrigenSim.capture_dir) do |org_file|
|
85
94
|
@org_file = org_file
|
86
95
|
@update_capture = update_capture?
|
87
96
|
if @update_capture
|
@@ -23,6 +23,10 @@ module OrigenSim
|
|
23
23
|
# instruction is sent to the simulator.
|
24
24
|
attr_accessor :ended
|
25
25
|
|
26
|
+
attr_reader :log_files
|
27
|
+
|
28
|
+
attr_accessor :max_errors_exceeded
|
29
|
+
|
26
30
|
def initialize(id, view_wave_command)
|
27
31
|
@id = id
|
28
32
|
@view_wave_command = view_wave_command
|
@@ -31,7 +35,10 @@ module OrigenSim
|
|
31
35
|
@logged_errors = false
|
32
36
|
@ended = false
|
33
37
|
@error_count = 0
|
38
|
+
@cycle_count = 0
|
34
39
|
@socket_ids = {}
|
40
|
+
@log_files = []
|
41
|
+
@max_errors_exceeded = false
|
35
42
|
|
36
43
|
# Socket used to send Origen -> Verilog commands
|
37
44
|
@server = UNIXServer.new(socket_id)
|
@@ -47,6 +54,8 @@ module OrigenSim
|
|
47
54
|
end
|
48
55
|
|
49
56
|
def failed?(in_progress = false)
|
57
|
+
# Exit cleanly when the simulator didn't even start, e.g. because no compiled DUT existed
|
58
|
+
return true unless @stderr_reader
|
50
59
|
failed = stderr_logged_errors || logged_errors || failed_to_start || error_count > 0
|
51
60
|
if in_progress
|
52
61
|
failed
|
@@ -73,9 +82,10 @@ module OrigenSim
|
|
73
82
|
end
|
74
83
|
else
|
75
84
|
if in_progress
|
76
|
-
|
85
|
+
simulator.log("The simulation has #{error_count} error#{error_count > 1 ? 's' : ''}!", :error) if error_count > 0
|
77
86
|
else
|
78
87
|
Origen.log.error "The simulation failed with #{error_count} errors!" if error_count > 0
|
88
|
+
Origen.log.error "The simulation was aborted due to exceeding #{simulator.max_errors} errors!" if max_errors_exceeded
|
79
89
|
end
|
80
90
|
Origen.log.error 'The simulation log reported errors!' if logged_errors
|
81
91
|
Origen.log.error 'The simulation stderr reported errors!' if stderr_logged_errors
|
@@ -83,7 +93,7 @@ module OrigenSim
|
|
83
93
|
end
|
84
94
|
else
|
85
95
|
if in_progress
|
86
|
-
|
96
|
+
simulator.log 'The simulation is passing!', :success
|
87
97
|
else
|
88
98
|
Origen.log.success 'The simulation passed!'
|
89
99
|
end
|
@@ -157,6 +167,11 @@ module OrigenSim
|
|
157
167
|
end
|
158
168
|
end
|
159
169
|
|
170
|
+
def time_since_last_log
|
171
|
+
[@stdout_reader.time_since_last_message,
|
172
|
+
@stderr_reader.time_since_last_message].min
|
173
|
+
end
|
174
|
+
|
160
175
|
# Open the communication channels with the simulator
|
161
176
|
def open(monitor_pid, timeout)
|
162
177
|
@monitor_pid = monitor_pid
|
@@ -165,8 +180,10 @@ module OrigenSim
|
|
165
180
|
@stdout = @server_stdout.accept
|
166
181
|
@stderr = @server_stderr.accept
|
167
182
|
@status = @server_status.accept
|
168
|
-
@stdout_reader = StdoutReader.new(@stdout)
|
183
|
+
@stdout_reader = StdoutReader.new(@stdout, simulator)
|
169
184
|
@stderr_reader = StderrReader.new(@stderr)
|
185
|
+
@stdout_reader.priority = 1
|
186
|
+
@stderr_reader.priority = 2
|
170
187
|
|
171
188
|
Origen.log.debug 'The simulation monitor has started'
|
172
189
|
Origen.log.debug @status.gets.chomp # Starting simulator
|
@@ -180,7 +197,7 @@ module OrigenSim
|
|
180
197
|
# That's all status info done until the simulation process ends, start a thread
|
181
198
|
# to wait for that in case it ends before the VPI starts
|
182
199
|
Thread.new do
|
183
|
-
|
200
|
+
@status.gets.chomp # This will block until something is received
|
184
201
|
abort_connection
|
185
202
|
end
|
186
203
|
Origen.log.debug 'Waiting for Origen VPI to start...'
|
@@ -264,8 +281,21 @@ module OrigenSim
|
|
264
281
|
@socket_ids[type] ||= "#{OrigenSim.socket_dir || '/tmp'}/#{socket_number}#{type}.sock"
|
265
282
|
end
|
266
283
|
|
284
|
+
# Returns the current cycle count, this is Origen's local count
|
285
|
+
def cycle_count
|
286
|
+
@cycle_count
|
287
|
+
end
|
288
|
+
|
289
|
+
def cycle(number_of_cycles)
|
290
|
+
@cycle_count += number_of_cycles
|
291
|
+
end
|
292
|
+
|
267
293
|
private
|
268
294
|
|
295
|
+
def simulator
|
296
|
+
tester.simulator
|
297
|
+
end
|
298
|
+
|
269
299
|
def socket_number
|
270
300
|
@socket_number ||= (Process.pid.to_s + Time.now.to_f.to_s).sub('.', '')
|
271
301
|
end
|
data/lib/origen_sim/simulator.rb
CHANGED
@@ -11,6 +11,28 @@ module OrigenSim
|
|
11
11
|
include Artifacts
|
12
12
|
|
13
13
|
VENDORS = [:icarus, :cadence, :synopsys, :generic]
|
14
|
+
LOG_CODES = { debug: 0, info: 1, warn: 2, warning: 2, success: 3, error: 4, deprecate: 5, deprecated: 5 }
|
15
|
+
LOG_CODES_ = { 0 => :debug, 1 => :info, 2 => :warn, 3 => :success, 4 => :error, 5 => :deprecated }
|
16
|
+
|
17
|
+
TIMESCALES = { -15 => '1fs',
|
18
|
+
-14 => '10fs',
|
19
|
+
-13 => '100fs',
|
20
|
+
-12 => '1ps',
|
21
|
+
-11 => '10ps',
|
22
|
+
-10 => '100ps',
|
23
|
+
-9 => '1ns',
|
24
|
+
-8 => '10ns',
|
25
|
+
-7 => '100ns',
|
26
|
+
-6 => '1us',
|
27
|
+
-5 => '10us',
|
28
|
+
-4 => '100us',
|
29
|
+
-3 => '1ms',
|
30
|
+
-2 => '10ms',
|
31
|
+
-1 => '100ms',
|
32
|
+
0 => '1s',
|
33
|
+
1 => '10s',
|
34
|
+
2 => '100s'
|
35
|
+
}
|
14
36
|
|
15
37
|
attr_reader :configuration
|
16
38
|
alias_method :config, :configuration
|
@@ -19,6 +41,9 @@ module OrigenSim
|
|
19
41
|
# Returns an array containing all instances of OrigenSim::Simulation that were created
|
20
42
|
# in the order that they were created
|
21
43
|
attr_reader :simulations
|
44
|
+
# Returns a hash of pins where the key is the RTL name, used to quickly retrieve the pin
|
45
|
+
# object from the pin name returned by the simulator
|
46
|
+
attr_reader :pins_by_rtl_name
|
22
47
|
|
23
48
|
def initialize
|
24
49
|
@simulations = []
|
@@ -460,7 +485,6 @@ module OrigenSim
|
|
460
485
|
|
461
486
|
# Starts up the simulator process
|
462
487
|
def start
|
463
|
-
Origen.log.level = :verbose if Origen.debugger_enabled?
|
464
488
|
@simulation_open = true
|
465
489
|
@simulation = Simulation.new(wave_file_basename, view_wave_command)
|
466
490
|
simulations << @simulation
|
@@ -559,6 +583,8 @@ module OrigenSim
|
|
559
583
|
|
560
584
|
Origen.log.debug 'Starting the simulation monitor...'
|
561
585
|
|
586
|
+
Origen.log.flush # Required to stop any existing buffered log data being copied into this new process
|
587
|
+
|
562
588
|
monitor_pid = spawn("ruby -e \"#{launch_simulator}\"")
|
563
589
|
Process.detach(monitor_pid)
|
564
590
|
|
@@ -573,12 +599,31 @@ module OrigenSim
|
|
573
599
|
end
|
574
600
|
Origen.log.info "OrigenSim version #{Origen.app!.version}"
|
575
601
|
Origen.log.info "OrigenSim DUT version #{dut_version}"
|
602
|
+
unless dut_version > '0.15.0'
|
603
|
+
Origen.log.warning 'Progress comments may be out of sync with simulator output.'
|
604
|
+
Origen.log.warning 'Recompile your DUT with a newer version of OrigenSim to resolve this.'
|
605
|
+
end
|
576
606
|
# Tick the simulation on, this seems to be required since any VPI puts operations before
|
577
607
|
# the simulation has started are not applied.
|
578
608
|
# Note that this is not setting a tester timeset, so the application will still have to
|
579
609
|
# do that before generating any vectors.
|
580
|
-
|
610
|
+
put('1^0') # Set period to 0 so that time does not advance
|
581
611
|
cycle(1)
|
612
|
+
if dut_version > '0.15.0'
|
613
|
+
# Put cycle counter back to 0
|
614
|
+
put('p^0')
|
615
|
+
simulation.cycle(-1)
|
616
|
+
put("m^#{max_errors}")
|
617
|
+
# Intercept all log messages until the end of the simulation so that they can be synced to
|
618
|
+
# simulation time
|
619
|
+
@log_intercept_id = Origen.log.start_intercepting do |msg, type, options, original|
|
620
|
+
if options[:from_origen_sim]
|
621
|
+
original.call(msg, type, options)
|
622
|
+
else
|
623
|
+
log(msg, type)
|
624
|
+
end
|
625
|
+
end
|
626
|
+
end
|
582
627
|
Origen.listeners_for(:simulation_startup).each(&:simulation_startup)
|
583
628
|
end
|
584
629
|
|
@@ -586,10 +631,12 @@ module OrigenSim
|
|
586
631
|
def put(msg)
|
587
632
|
simulation.socket.write(msg + "\n")
|
588
633
|
rescue Errno::EPIPE => e
|
634
|
+
# :from_origen_sim is added here to ensure this goes straight to the Origen console logger
|
635
|
+
# and does not get sent via the simulator since it is clearly having problems
|
589
636
|
if simulation.running?
|
590
|
-
Origen.log.error 'Communication with the simulator has been lost (though it seems to still be running)!'
|
637
|
+
Origen.log.error 'Communication with the simulator has been lost (though it seems to still be running)!', from_origen_sim: true
|
591
638
|
else
|
592
|
-
Origen.log.error 'The simulator has stopped unexpectedly!'
|
639
|
+
Origen.log.error 'The simulator has stopped unexpectedly!', from_origen_sim: true
|
593
640
|
end
|
594
641
|
sleep 2 # To make sure that any log output from the simulator is captured before we pull the plug
|
595
642
|
exit 1
|
@@ -634,11 +681,22 @@ module OrigenSim
|
|
634
681
|
start
|
635
682
|
end
|
636
683
|
# Set the current pattern name in the simulation
|
637
|
-
|
684
|
+
name = name.sub(/\..*/, '')
|
685
|
+
put("a^#{name}")
|
686
|
+
log '#' * 100
|
687
|
+
log '#' * 100
|
688
|
+
log '##'
|
689
|
+
log "## START OF PATTERN: #{name}"
|
690
|
+
log '##'
|
691
|
+
log '#' * 100
|
692
|
+
log '#' * 100
|
693
|
+
@running_pattern_name = name
|
694
|
+
@pattern_starting_error_count = error_count
|
638
695
|
@pattern_count ||= 0
|
639
696
|
# If running a flow, give the user some feedback about pass/fail status after
|
640
697
|
# each individual pattern has completed
|
641
698
|
if @pattern_count > 0 && OrigenSim.flow
|
699
|
+
simulation.error_count = error_count
|
642
700
|
simulation.log_results(true)
|
643
701
|
# Require each pattern to set this upon successful completion
|
644
702
|
simulation.completed_cleanly = false unless @flow_running
|
@@ -654,7 +712,17 @@ module OrigenSim
|
|
654
712
|
def pattern_generated(path)
|
655
713
|
if simulation_tester?
|
656
714
|
sync_up
|
715
|
+
log '#' * 100
|
716
|
+
log '#' * 100
|
717
|
+
log '##'
|
718
|
+
log "## END OF PATTERN: #{@running_pattern_name}"
|
719
|
+
log "## Errors: #{error_count - @pattern_starting_error_count}"
|
720
|
+
log '##'
|
721
|
+
log '#' * 100
|
722
|
+
log '#' * 100
|
657
723
|
simulation.completed_cleanly = true unless @flow_running
|
724
|
+
# Ensure that everything is flushed to the log before it is closed
|
725
|
+
flush quiet: true
|
658
726
|
end
|
659
727
|
end
|
660
728
|
alias_method :complete_simulation, :pattern_generated
|
@@ -671,6 +739,18 @@ module OrigenSim
|
|
671
739
|
end
|
672
740
|
end
|
673
741
|
|
742
|
+
# Any messages passed in here will be output to the console log by making a round trip through
|
743
|
+
# the simulator. This ensures that the given log messages will be in sync with output from the
|
744
|
+
# simulator rather than potentially being ahead of the simulator if Origen were to output them
|
745
|
+
# immediately.
|
746
|
+
def log(msg, type = :info)
|
747
|
+
if dut_version > '0.15.0'
|
748
|
+
put("k^#{LOG_CODES[type]}^#{msg}")
|
749
|
+
else
|
750
|
+
Origen.log.send(type, msg)
|
751
|
+
end
|
752
|
+
end
|
753
|
+
|
674
754
|
# Applies the current state of all pins to the simulation
|
675
755
|
def put_all_pin_states
|
676
756
|
dut.rtl_pins.each do |name, pin|
|
@@ -695,7 +775,9 @@ module OrigenSim
|
|
695
775
|
# Tells the simulator about the pins in the current device so that it can
|
696
776
|
# set up internal handles to efficiently access them
|
697
777
|
def define_pins
|
778
|
+
@pins_by_rtl_name = {}
|
698
779
|
dut.rtl_pins.each_with_index do |(name, pin), i|
|
780
|
+
@pins_by_rtl_name[pin.rtl_name] = pin
|
699
781
|
pin.simulation_index = i
|
700
782
|
put("0^#{pin.rtl_name}^#{i}^#{pin.drive_wave.index}^#{pin.compare_wave.index}")
|
701
783
|
end
|
@@ -706,16 +788,15 @@ module OrigenSim
|
|
706
788
|
|
707
789
|
def wave_to_str(wave)
|
708
790
|
wave.evaluated_events.map do |time, data|
|
709
|
-
time = time * time_conversion_factor * (config[:time_factor] || 1)
|
710
791
|
if data == :x
|
711
792
|
data = 'X'
|
712
793
|
elsif data == :data
|
713
794
|
data = wave.drive? ? 'D' : 'C'
|
714
795
|
end
|
715
796
|
if data == 'C'
|
716
|
-
"#{time}_#{data}_#{time +
|
797
|
+
"#{ns_to_simtime_units(time)}_#{data}_#{ns_to_simtime_units(time + 1)}_X"
|
717
798
|
else
|
718
|
-
"#{time}_#{data}"
|
799
|
+
"#{ns_to_simtime_units(time)}_#{data}"
|
719
800
|
end
|
720
801
|
end.join('_')
|
721
802
|
end
|
@@ -734,12 +815,12 @@ module OrigenSim
|
|
734
815
|
end
|
735
816
|
|
736
817
|
def set_period(period_in_ns)
|
737
|
-
|
738
|
-
put("1^#{period_in_ps}")
|
818
|
+
put("1^#{ns_to_simtime_units(period_in_ns)}")
|
739
819
|
end
|
740
820
|
|
741
821
|
def cycle(number_of_cycles)
|
742
822
|
put("3^#{number_of_cycles}")
|
823
|
+
simulation.cycle(number_of_cycles)
|
743
824
|
end
|
744
825
|
|
745
826
|
# Blocks the Origen process until the simulator indicates that it has
|
@@ -753,19 +834,36 @@ module OrigenSim
|
|
753
834
|
end
|
754
835
|
|
755
836
|
# Flush any buffered simulation output, this should cause live wave viewers to
|
756
|
-
# reflect the latest state
|
757
|
-
def flush
|
837
|
+
# reflect the latest state.
|
838
|
+
def flush(options = {})
|
758
839
|
if dut_version > '0.12.0'
|
840
|
+
sync_up
|
759
841
|
put('j^')
|
760
842
|
sync_up
|
843
|
+
# By now, the simulator has generated all log output up to this point and flushed it out,
|
844
|
+
# however it may not be in the Origen log output yet because the main Origen thread has not
|
845
|
+
# given the stdout/err reader threads a chance to process it.
|
846
|
+
# This will now sleep the main Origen thread to allow that to get a chance to happen and we
|
847
|
+
# will proceed once it has been > 100ms since a log message was processed, at that point we
|
848
|
+
# can safely assume that they are all done and nothing is left in the buffer.
|
849
|
+
w = false
|
850
|
+
while !w || simulation.time_since_last_log < 0.1
|
851
|
+
w = true
|
852
|
+
sleep 0.1
|
853
|
+
end
|
854
|
+
# Finally, make sure the messages are not now sitting in an IO buffer
|
855
|
+
Origen.log.flush
|
856
|
+
nil # Keep the console clean if this is called interactively
|
761
857
|
else
|
762
|
-
|
858
|
+
unless options[:quiet]
|
859
|
+
OrigenSim.error "Use of flush requires a DUT model compiled with OrigenSim version > 0.12.0, the current dut was compiled with #{dut_version}"
|
860
|
+
end
|
763
861
|
end
|
764
862
|
end
|
765
863
|
|
766
864
|
def error(message)
|
767
865
|
simulation.logged_errors = true
|
768
|
-
|
866
|
+
log message, :error
|
769
867
|
end
|
770
868
|
|
771
869
|
# Returns the current simulation error count
|
@@ -870,6 +968,7 @@ module OrigenSim
|
|
870
968
|
simulation.error_count = error_count
|
871
969
|
Origen.listeners_for(:simulation_shutdown).each(&:simulation_shutdown)
|
872
970
|
sync_up
|
971
|
+
Origen.log.stop_intercepting @log_intercept_id
|
873
972
|
simulation.ended = true
|
874
973
|
end_simulation
|
875
974
|
# Give the simulator time to shut down
|
@@ -901,6 +1000,14 @@ module OrigenSim
|
|
901
1000
|
end
|
902
1001
|
end
|
903
1002
|
puts
|
1003
|
+
puts 'The following log files have been created:'
|
1004
|
+
puts
|
1005
|
+
simulations.each do |simulation|
|
1006
|
+
simulation.log_files.each do |f|
|
1007
|
+
puts " #{f}"
|
1008
|
+
end
|
1009
|
+
end
|
1010
|
+
puts
|
904
1011
|
if simulations.size == 1
|
905
1012
|
puts 'To view the simulation run the following command:'
|
906
1013
|
puts
|
@@ -966,18 +1073,52 @@ module OrigenSim
|
|
966
1073
|
end
|
967
1074
|
end
|
968
1075
|
|
1076
|
+
# Get the timescale of the current simulation, returns a number that maps as follows:
|
1077
|
+
# -15 - fs
|
1078
|
+
# -14 - 10fs
|
1079
|
+
# -13 - 100fs
|
1080
|
+
# -12 - ps
|
1081
|
+
# -11 - 10ps
|
1082
|
+
# -10 - 100ps
|
1083
|
+
# -9 - ns
|
1084
|
+
# -8 - 10ns
|
1085
|
+
# -7 - 100ns
|
1086
|
+
# -6 - us
|
1087
|
+
# -5 - 10us
|
1088
|
+
# -4 - 100us
|
1089
|
+
# -3 - ms
|
1090
|
+
# -2 - 10ms
|
1091
|
+
# -1 - 100ms
|
1092
|
+
# 0 - s
|
1093
|
+
# 1 - 10s
|
1094
|
+
# 2 - 100s
|
1095
|
+
def timescale
|
1096
|
+
put('l^')
|
1097
|
+
get.strip.to_i
|
1098
|
+
end
|
1099
|
+
|
969
1100
|
# Any vectors executed within the given block will increment the match_errors counter
|
970
1101
|
# rather than the errors counter.
|
971
1102
|
# The match_errors counter will be returned to 0 at the end.
|
972
1103
|
def match_loop
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
1104
|
+
if dut_version > '0.15.0'
|
1105
|
+
put('q^1')
|
1106
|
+
yield
|
1107
|
+
put('q^0')
|
1108
|
+
else
|
1109
|
+
poke("#{testbench_top}.pins.match_loop", 1)
|
1110
|
+
yield
|
1111
|
+
poke("#{testbench_top}.pins.match_loop", 0)
|
1112
|
+
poke("#{testbench_top}.pins.match_errors", 0)
|
1113
|
+
end
|
977
1114
|
end
|
978
1115
|
|
979
1116
|
def match_errors
|
980
|
-
|
1117
|
+
if dut_version > '0.15.0'
|
1118
|
+
peek("#{testbench_top}.debug.match_errors").to_i
|
1119
|
+
else
|
1120
|
+
peek("#{testbench_top}.pins.match_errors").to_i
|
1121
|
+
end
|
981
1122
|
end
|
982
1123
|
|
983
1124
|
def peek_str(signal)
|
@@ -997,8 +1138,75 @@ module OrigenSim
|
|
997
1138
|
alias_method :peek_string, :peek_str
|
998
1139
|
alias_method :string_peek, :peek_str
|
999
1140
|
|
1141
|
+
# Returns the number of errors that are allowed before a aborting a simulation
|
1142
|
+
def max_errors
|
1143
|
+
OrigenSim.max_errors || config[:max_errors] || 100
|
1144
|
+
end
|
1145
|
+
|
1146
|
+
def marker=(val)
|
1147
|
+
poke("#{testbench_top}.debug.marker", val)
|
1148
|
+
end
|
1149
|
+
|
1150
|
+
def start_read_reg_transaction
|
1151
|
+
put('n^1')
|
1152
|
+
end
|
1153
|
+
|
1154
|
+
def stop_read_reg_transaction
|
1155
|
+
put('n^0')
|
1156
|
+
data = get
|
1157
|
+
error_count, max_errors = *(data.strip.split(',').map(&:to_i))
|
1158
|
+
if error_count > 0
|
1159
|
+
errors = []
|
1160
|
+
error_count.times do |i|
|
1161
|
+
data = get # => "tdo,648,1,0\n"
|
1162
|
+
pin_name, cycle, expected, recieved = *(data.strip.split(','))
|
1163
|
+
errors << { pin_name: pin_name, cycle: cycle.to_i, expected: expected.to_i, recieved: recieved.to_i }
|
1164
|
+
end
|
1165
|
+
[true, error_count > max_errors, errors]
|
1166
|
+
end
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
# Returns the simulator cycle count, this should be the same as tester.cycle_count but this
|
1170
|
+
# gives the simulators count instead of Origen's
|
1171
|
+
def cycle_count
|
1172
|
+
put('o^')
|
1173
|
+
get.strip.to_i
|
1174
|
+
end
|
1175
|
+
|
1000
1176
|
private
|
1001
1177
|
|
1178
|
+
# Will be called when the simulator has aborted due to the max error count being exceeded
|
1179
|
+
def max_error_abort
|
1180
|
+
simulation.max_errors_exceeded = true
|
1181
|
+
end
|
1182
|
+
|
1183
|
+
def ns_to_simtime_units(time_in_ns)
|
1184
|
+
if dut_version > '0.15.0'
|
1185
|
+
(time_in_ns * time_factor).to_i
|
1186
|
+
else
|
1187
|
+
time_in_ns * time_conversion_factor * (config[:time_factor] || 1)
|
1188
|
+
end
|
1189
|
+
end
|
1190
|
+
|
1191
|
+
def simtime_units_to_ns(time)
|
1192
|
+
(time / time_factor).to_i
|
1193
|
+
end
|
1194
|
+
|
1195
|
+
def time_factor
|
1196
|
+
@time_factor ||= begin
|
1197
|
+
if config[:time_factor]
|
1198
|
+
Origen.log.warning 'Your simulation environment setup defines a :time_factor, however this is no longer used by OrigenSim'
|
1199
|
+
end
|
1200
|
+
t = timescale
|
1201
|
+
if t > -9
|
1202
|
+
msg = "The simulation is running with a timescale of #{TIMESCALES[timescale]}, this is greater than OrigenSim's min resolution of 1ns"
|
1203
|
+
OrigenSim.error(msg)
|
1204
|
+
exit 1
|
1205
|
+
end
|
1206
|
+
"1e#{-9 - t}".to_f.to_i
|
1207
|
+
end
|
1208
|
+
end
|
1209
|
+
|
1002
1210
|
# Pre 0.8.0 the simulator represented the time in ns instead of ps
|
1003
1211
|
def time_conversion_factor
|
1004
1212
|
@time_conversion_factor ||= dut_version < '0.8.0' ? 1 : 1000
|