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.
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