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.
data/ext/bridge.h CHANGED
@@ -5,5 +5,7 @@
5
5
 
6
6
  PLI_INT32 bridge_wait_for_msg(p_cb_data);
7
7
  PLI_INT32 bridge_init(void);
8
+ PLI_INT32 bridge_on_miscompare(PLI_BYTE8*);
9
+ void bridge_register_system_tasks(void);
8
10
 
9
11
  #endif
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
@@ -14,6 +14,8 @@ static void init() {
14
14
  register_callback(cbStartOfSimulation, origen_startup);
15
15
 
16
16
  register_callback(cbEndOfSimulation, origen_shutdown);
17
+
18
+ bridge_register_system_tasks();
17
19
  }
18
20
 
19
21
 
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.debugger_enabled? || Origen.running_remotely?)
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(val)
23
- ret = _orig_set_state(val)
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
- Origen.log.error "The simulation has #{error_count} error#{error_count > 1 ? 's' : ''}!" if error_count > 0
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
- Origen.log.success 'The simulation is passing!'
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
- Origen.log.debug @status.gets.chomp # This will block until something is received
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
@@ -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
- set_period(100)
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
- put("a^#{name.sub(/\..*/, '')}")
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 + (time_conversion_factor * (config[:time_factor] || 1))}_X"
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
- period_in_ps = period_in_ns * time_conversion_factor * (config[:time_factor] || 1)
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
- OrigenSim.error "Use of flush requires a DUT model compiled with OrigenSim version > 0.12.0, the current dut was compiled with #{dut_version}"
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
- Origen.log.error message
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
- poke("#{testbench_top}.pins.match_loop", 1)
974
- yield
975
- poke("#{testbench_top}.pins.match_loop", 0)
976
- poke("#{testbench_top}.pins.match_errors", 0)
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
- peek("#{testbench_top}.pins.match_errors").to_i
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