origen_sim 0.15.0 → 0.16.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 +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
|