origen_sim 0.8.0 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 07feeaf38e2cacb8a570887c9bfc2acd38b26956
4
- data.tar.gz: 693b70230e195a5b0fd49c586ec16f5116fe7d0d
3
+ metadata.gz: f670da6bba360fa76ac30b10cd097cde48d6353a
4
+ data.tar.gz: 07a1c407163212fd4fd04b45336ff399751155e2
5
5
  SHA512:
6
- metadata.gz: 295d5c1df56f7341fa5e60b35b902169d92d21c482a2bee4452827d84e847697975e218aa4eb86e07d10d79e0939bee3d4e2a58ede7a347c8599fb26733ac7b9
7
- data.tar.gz: e51c858045564989fa53ce7bc281d70afc887e5312f81908e44463a303c93d0c65d5a61cb15095a12892e7d3ff4dc3002bb5565f0735a3c37284298889500f7e
6
+ metadata.gz: 0f0bcd9d653bf6ba02617116e3d843c9e1f39c20f023544b9cf5bbf152289fd9fa5654be8d72b2bcd77928f0a26041ed4da9370110b1281b98e1e7568df73aa5
7
+ data.tar.gz: 1bd7de244589567b366d0213279df4f295f0ed374311bfc1b22d0666eacfd6855c19ecaa7fe4f7c6214452d54fb0ab4076b69f3714fae397dc9d25142ebfa580
@@ -16,10 +16,28 @@ when "sim:co", "origen_sim:co"
16
16
  require "#{Origen.root!}/lib/origen_sim/commands/co"
17
17
  exit 0
18
18
 
19
+ when "sim:pack"
20
+ require "#{Origen.root!}/lib/origen_sim/commands/pack"
21
+ OrigenSim::Commands::Pack.pack
22
+ exit 0
23
+
24
+ when "sim:unpack"
25
+ require "#{Origen.root!}/lib/origen_sim/commands/pack"
26
+ OrigenSim::Commands::Pack.unpack
27
+ exit 0
28
+
29
+ #when "sim:list"
30
+ # require "#{Origen.root!}/lib/origen_sim/commands/pack"
31
+ # OrigenSim::Commands::Pack.list
32
+ # exit 0
33
+
19
34
  else
20
35
  @plugin_commands << <<-EOT
21
36
  sim:ci Checkin a simulation snapshot
22
37
  sim:co Checkout a simulation snapshot
38
+ sim:pack Packs the snapshot into a compressed directory
39
+ sim:unpack Unpacks a snapshot
40
+ sim:list List the available snapshot packs
23
41
  EOT
24
42
 
25
43
  end
data/config/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module OrigenSim
2
2
  MAJOR = 0
3
- MINOR = 8
3
+ MINOR = 9
4
4
  BUGFIX = 0
5
5
  DEV = nil
6
6
 
data/ext/bridge.c CHANGED
@@ -83,7 +83,7 @@ static void bridge_define_pin(char * name, char * pin_ix, char * drive_wave_ix,
83
83
  (*pin).capture_en = false;
84
84
 
85
85
  char * driver = (char *) malloc(strlen(name) + 16);
86
- strcpy(driver, "origen.pins.");
86
+ strcpy(driver, ORIGEN_SIM_TESTBENCH_CAT("pins."));
87
87
  strcat(driver, name);
88
88
 
89
89
  char * data = (char *) malloc(strlen(driver) + 16);
@@ -661,7 +661,7 @@ PLI_INT32 bridge_wait_for_msg(p_cb_data data) {
661
661
  // Set Pattern Name
662
662
  // a^atd_ramp_25mhz
663
663
  case 'a' :
664
- handle = vpi_handle_by_name("origen.debug.pattern", NULL);
664
+ handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("debug.pattern"), NULL);
665
665
  arg1 = strtok(NULL, "^");
666
666
 
667
667
  v.format = vpiStringVal;
@@ -686,7 +686,7 @@ PLI_INT32 bridge_wait_for_msg(p_cb_data data) {
686
686
  // Set Comment
687
687
  // c^Some comment about the pattern
688
688
  case 'c' :
689
- handle = vpi_handle_by_name("origen.debug.comments", NULL);
689
+ handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("debug.comments"), NULL);
690
690
  arg1 = strtok(NULL, "^");
691
691
 
692
692
  v.format = vpiStringVal;
@@ -710,14 +710,14 @@ PLI_INT32 bridge_wait_for_msg(p_cb_data data) {
710
710
  break;
711
711
  // Sync enable
712
712
  case 'f' :
713
- handle = vpi_handle_by_name("origen.pins.sync", NULL);
713
+ handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("pins.sync"), NULL);
714
714
  v.format = vpiDecStrVal;
715
715
  v.value.str = "1";
716
716
  vpi_put_value(handle, &v, NULL, vpiNoDelay);
717
717
  break;
718
718
  // Sync disable
719
719
  case 'g' :
720
- handle = vpi_handle_by_name("origen.pins.sync", NULL);
720
+ handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("pins.sync"), NULL);
721
721
  v.format = vpiDecStrVal;
722
722
  v.value.str = "0";
723
723
  vpi_put_value(handle, &v, NULL, vpiNoDelay);
@@ -751,7 +751,7 @@ static void end_simulation() {
751
751
  s_vpi_value v;
752
752
 
753
753
  // Setting this node will cause the testbench to call $finish
754
- handle = vpi_handle_by_name("origen.finish", NULL);
754
+ handle = vpi_handle_by_name(ORIGEN_SIM_TESTBENCH_CAT("finish"), NULL);
755
755
  v.format = vpiDecStrVal;
756
756
  v.value.str = "1";
757
757
  vpi_put_value(handle, &v, NULL, vpiNoDelay);
data/ext/common.h CHANGED
@@ -11,6 +11,10 @@
11
11
 
12
12
  #define ENABLE_DEBUG
13
13
 
14
+ /// Prepends the testbench name to the signal.
15
+ /// e.g.: TESTBENCH_CAT(pins) => TESTBENCH_NAME.pins => origen.pins
16
+ #define ORIGEN_SIM_TESTBENCH_CAT(signal) ORIGEN_SIM_TESTBENCH_NAME "." signal
17
+
14
18
  #ifdef ENABLE_DEBUG
15
19
  /* #define DEBUG(fmt, args...) fprintf(stderr, "DEBUG: %s:%d:%s(): " fmt, \
16
20
  __FILE__, __LINE__, __func__, ##args) */
data/ext/defines.h.erb CHANGED
@@ -2,5 +2,6 @@
2
2
  #define DEFINES_H
3
3
 
4
4
  #define ORIGEN_SIM_VERSION "<%= OrigenSim::VERSION %>"
5
+ #define ORIGEN_SIM_TESTBENCH_NAME "<%= options[:testbench_name] %>"
5
6
 
6
7
  #endif
data/ext/origen.c CHANGED
@@ -85,6 +85,14 @@ PLI_INT32 origen_shutdown(p_cb_data data) {
85
85
  return 0;
86
86
  }
87
87
 
88
+ /// Function to call the init PLI's init function
89
+ /// Some toolchains will call this automatically, some will not
90
+ /// Available here for those which do not automatically call init() for each PLI
91
+ PLI_INT32 bootstrap(p_cb_data data) {
92
+ vpi_printf("Origen Bootstrap Called!\n");
93
+ init();
94
+ return 0;
95
+ }
88
96
 
89
97
  ///
90
98
  /// Registers a very basic VPI callback with reason and handler.
@@ -3,7 +3,7 @@ require 'origen_sim'
3
3
  require_relative '../../../config/version'
4
4
  require 'origen_verilog'
5
5
 
6
- options = { source_dirs: [] }
6
+ options = { source_dirs: [], testbench_name: 'origen' }
7
7
 
8
8
  # App options are options that the application can supply to extend this command
9
9
  app_options = @application_options || []
@@ -18,6 +18,7 @@ Usage: origen sim:build TOP_LEVEL_VERILOG_FILE [options]
18
18
  EOT
19
19
  opts.on('-o', '--output DIR', String, 'Override the default output directory') { |t| options[:output] = t }
20
20
  opts.on('-t', '--top NAME', String, 'Specify the top-level Verilog module name if OrigenSim can\'t work it out') { |t| options[:top_level_name] = t }
21
+ opts.on('--testbench NAME', String, 'Specify the testbench name if different from \'origen\'') { |t| options[:testbench_name] = t }
21
22
  opts.on('-s', '--source_dir PATH', 'Directories to look for include files in (the directory containing the top-level is already considered)') do |path|
22
23
  options[:source_dirs] << path
23
24
  end
@@ -86,7 +87,8 @@ Origen.app.runner.launch action: :compile,
86
87
  files: "#{Origen.root!}/ext",
87
88
  output: output_directory,
88
89
  check_for_changes: false,
89
- quiet: true
90
+ quiet: true,
91
+ options: options
90
92
 
91
93
  dut.export(rtl_top_module, dir: "#{output_directory}", namespace: nil)
92
94
 
@@ -0,0 +1,37 @@
1
+ module OrigenSim
2
+ module Commands
3
+ module Pack
4
+ # Note, making this a module instead of straight code so it can be called
5
+ # programatically to auto-unpack a snapshot.
6
+
7
+ def self.pack(options = {})
8
+ testbench = "#{Origen.app.root}/simulation"
9
+ unless Dir.exist?(testbench)
10
+ fail "Could not find path #{testbench}/#{ARGV[0]}"
11
+ end
12
+
13
+ FileUtils.mkdir("#{Origen.app.root}/simulation/static") unless Dir.exist?("#{Origen.app.root}/simulation/static")
14
+
15
+ output = "#{Origen.app.root}/simulation/static/#{ARGV[0]}.tar.gz"
16
+ puts "Packing #{testbench} into #{output}..."
17
+ system "tar vczf #{output} -C #{testbench} #{Origen.target.name}"
18
+ end
19
+
20
+ def self.unpack(options = {})
21
+ testbench = "#{Origen.app.root}/simulation/static/#{ARGV[0]}.tar.gz"
22
+ unless File.exist?(testbench)
23
+ fail "Could not find #{testbench}"
24
+ end
25
+
26
+ output = "#{Origen.app.root}/simulation"
27
+ FileUtils.mkdir(output) unless Dir.exist?(output)
28
+
29
+ puts "Unpakcing Testbench into #{output}"
30
+ system "tar vxzf #{testbench} -C #{output} #{ARGV[0]}"
31
+ end
32
+
33
+ def self.list(options = {})
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,4 +1,5 @@
1
1
  require 'socket'
2
+ require 'io/wait'
2
3
  module OrigenSim
3
4
  # Responsible for managing and communicating with the simulator
4
5
  # process, a single instance of this class is instantiated as
@@ -6,10 +7,16 @@ module OrigenSim
6
7
  class Simulator
7
8
  include Origen::PersistentCallbacks
8
9
 
9
- VENDORS = [:icarus, :cadence, :synopsys]
10
+ VENDORS = [:icarus, :cadence, :synopsys, :generic]
10
11
 
11
- attr_reader :socket, :failed, :configuration
12
+ attr_reader :socket, :failed, :configuration, :stderr, :stdout, :heartbeat
12
13
  alias_method :config, :configuration
14
+ # Returns the PID of the simulator process
15
+ attr_reader :pid
16
+
17
+ def initialize
18
+ @socket_ids = {}
19
+ end
13
20
 
14
21
  # When set to true the simulator will log all messages it receives, note that
15
22
  # this must be run in conjunction with -d supplied to the Origen command to actually
@@ -22,6 +29,22 @@ module OrigenSim
22
29
  end
23
30
  end
24
31
 
32
+ def testbench_top
33
+ config[:testbench_top] || 'origen'
34
+ end
35
+
36
+ def rtl_top
37
+ config[:rtl_top] || 'dut'
38
+ end
39
+
40
+ def generic_run_cmd
41
+ config[:generic_run_cmd]
42
+ end
43
+
44
+ def post_process_run_cmd
45
+ config[:post_process_run_cmd]
46
+ end
47
+
25
48
  def fetch_simulation_objects(options = {})
26
49
  sid = options[:id] || id
27
50
  ldir = "#{Origen.root}/simulation/#{sid}"
@@ -83,7 +106,7 @@ module OrigenSim
83
106
  FileUtils.rm_rf tmp_dir if File.exist?(tmp_dir)
84
107
  end
85
108
 
86
- def configure(options)
109
+ def configure(options, &block)
87
110
  fail 'A vendor must be supplied, e.g. OrigenSim::Tester.new(vendor: :icarus)' unless options[:vendor]
88
111
  unless VENDORS.include?(options[:vendor])
89
112
  fail "Unknown vendor #{options[:vendor]}, valid values are: #{VENDORS.map { |v| ':' + v.to_s }.join(', ')}"
@@ -125,14 +148,6 @@ module OrigenSim
125
148
  end
126
149
  end
127
150
 
128
- def pid_dir
129
- @pid_dir ||= begin
130
- d = "#{Origen.root}/tmp/origen_sim/pids"
131
- FileUtils.mkdir_p(d)
132
- d
133
- end
134
- end
135
-
136
151
  def wave_config_dir
137
152
  @wave_config_dir ||= begin
138
153
  d = "#{Origen.root}/config/waves/#{id}"
@@ -215,10 +230,42 @@ module OrigenSim
215
230
  when :synopsys
216
231
  cmd = "#{compiled_dir}/simv +socket+#{socket_id} -vpd_file origen.vpd"
217
232
 
233
+ when :generic
234
+ # Generic tester requires that a generic_run_command option/block be provided.
235
+ # This should either be a string, an array (which will be joined here), or a block that needs to return either
236
+ # a string or array. In the event of a block, the block will be given the simulator.
237
+ if generic_run_cmd
238
+ cmd = generic_run_cmd
239
+ if cmd.is_a?(Proc)
240
+ cmd = cmd.call(self)
241
+ end
242
+
243
+ if cmd.is_a?(Array)
244
+ # We'll join this together with the '; ' string. This means that each array element will be run
245
+ # sequentially.
246
+ cmd = cmd.join(' && ')
247
+ elsif !cmd.is_a?(String)
248
+ # If its Proc, it was already run, and if its a Array if would have gone into the other case.
249
+ # So, this is either another proc, not an array and not a string, so not sure what to do with this.
250
+ # Complain about the cmd.
251
+ fail "OrigenSim :generic_run_cmd is of class #{generic_run_cmd.class}. It must be either an Array, String, or a Proc that returns an Array or String."
252
+ end
253
+ else
254
+ fail 'OrigenSim Generic Toolchain/Vendor requires a :generic_run_cmd option/block to be provided. No options/block provided!'
255
+ end
256
+
218
257
  else
219
258
  fail "Run cmd not defined yet for simulator #{config[:vendor]}"
220
259
 
221
260
  end
261
+
262
+ # Allow the user to post-process the command. This should be a block which will be given two parameters:
263
+ # 1. the command, and 2. the simulation object (self).
264
+ # In the event of a generic tester, this *could* replace the launch command, but that's not the real intention,
265
+ # since a simulator could be made that inherits from a generic simulator setup and still post process the command.
266
+ cmd = post_process_run_cmd.call(cmd, self) if post_process_run_cmd
267
+ fail "OrigenSim: :post_process_run_cmd returned object of class #{cmd.class}. Must return a String." unless cmd.is_a?(String)
268
+
222
269
  cmd
223
270
  end
224
271
 
@@ -253,6 +300,20 @@ module OrigenSim
253
300
  cmd += " -session #{f}"
254
301
  cmd += ' &'
255
302
 
303
+ when :generic
304
+ # Since this could be anything, the simulator will need to set this up. But, once it is, we can print it here.
305
+ if config[:view_waveform_cmd]
306
+ cmd = config[:view_waveform_cmd]
307
+ else
308
+ Origen.log.warn 'OrigenSim cannot provide a view-waveform command for a :generic vendor.'
309
+ Origen.log.warn 'Please supply a view-waveform command though the :view_waveform_cmd option during the OrigenSim::Generic instantiation.'
310
+ end
311
+
312
+ else
313
+ # Print a warning stating an unknown vendor was reached here.
314
+ # This shouldn't happen, but just in case.
315
+ Origen.log.warn "OrigenSim does not know the command to view waveforms for vendor :#{config[:vendor]}!"
316
+
256
317
  end
257
318
  cmd
258
319
  end
@@ -270,31 +331,86 @@ module OrigenSim
270
331
  def start
271
332
  fetch_simulation_objects
272
333
 
334
+ # Socket used for Origen -> Verilog commands
273
335
  server = UNIXServer.new(socket_id)
274
- verbose = Origen.debugger_enabled?
336
+ # Socket used to capture stdout from the simulator
337
+ stdout_socket_id = socket_id(:stdout)
338
+ # Socket used to capture stderr from the simulator
339
+ stderr_socket_id = socket_id(:stderr)
340
+ # Socket used to provide a heartbeat to let the Ruby process in charge of the simulator
341
+ # know that the mast Origen process is still alive. If the Origen process crashes and leaves
342
+ # the simulator running, the child process will automatically reap it after a couple of missed
343
+ # heartbeats
344
+ heartbeat_socket_id = socket_id(:heartbeat)
345
+ server_stdout = UNIXServer.new(stdout_socket_id)
346
+ server_stderr = UNIXServer.new(stderr_socket_id)
347
+ server_heartbeat = UNIXServer.new(heartbeat_socket_id)
275
348
  cmd = run_cmd + ' & echo \$!'
276
349
 
277
350
  launch_simulator = %(
278
351
  require 'open3'
352
+ require 'socket'
353
+ require 'io/wait'
354
+ require 'origen'
355
+
356
+ pid = nil
357
+
358
+ stdout_socket = UNIXSocket.new('#{stdout_socket_id}')
359
+ stderr_socket = UNIXSocket.new('#{stderr_socket_id}')
360
+ heartbeat = UNIXSocket.new('#{heartbeat_socket_id}')
361
+
362
+ begin
363
+
364
+ Dir.chdir '#{run_dir}' do
365
+ Open3.popen3('#{cmd}') do |stdin, stdout, stderr, thread|
366
+ pid = stdout.gets.strip.to_i
367
+ heartbeat.puts(pid.to_s)
368
+
369
+ # Listen for a heartbeat from the main Origen process every 5 seconds, kill the
370
+ # simulator after two missed heartbeats
371
+ Thread.new do
372
+ missed_heartbeats = 0
373
+ loop do
374
+ sleep 5
375
+ if heartbeat.ready?
376
+ while heartbeat.ready? do
377
+ heartbeat.gets
378
+ end
379
+ missed_heartbeats = 0
380
+ else
381
+ missed_heartbeats += 1
382
+ end
383
+ if missed_heartbeats > 1
384
+ Process.kill('KILL', pid)
385
+ exit!(1)
386
+ end
387
+ end
388
+ end
279
389
 
280
- Dir.chdir '#{run_dir}' do
281
- Open3.popen3('#{cmd}') do |stdin, stdout, stderr, thread|
282
- pid = stdout.gets.strip
283
- File.open '#{pid_dir}/#{socket_number}', 'w' do |f|
284
- f.puts pid
285
- end
286
- threads = []
287
- threads << Thread.new do
288
- until (line = stdout.gets).nil?
289
- puts line if #{verbose ? 'true' : 'false'}
390
+ threads = []
391
+ threads << Thread.new do
392
+ until (line = stdout.gets).nil?
393
+ stdout_socket.puts line
394
+ end
290
395
  end
291
- end
292
- threads << Thread.new do
293
- until (line = stderr.gets).nil?
294
- puts line
396
+ threads << Thread.new do
397
+ until (line = stderr.gets).nil?
398
+ stderr_socket.puts line
399
+ end
295
400
  end
401
+ threads.each(&:join)
296
402
  end
297
- threads.each(&:join)
403
+ end
404
+
405
+ ensure
406
+ # Make sure this process never finishes and leaves the simulator running
407
+ begin
408
+ # If the process already finished, then we will see an Errno exception.
409
+ # It does not harm anything, but looks ugly, so catch it here and ignore.
410
+ Process.kill('KILL', pid) if pid
411
+ 0
412
+ rescue Errno::ESRCH => e
413
+ 0
298
414
  end
299
415
  end
300
416
  )
@@ -303,6 +419,19 @@ module OrigenSim
303
419
  Process.detach(simulator_parent_process)
304
420
 
305
421
  timeout_connection(config[:startup_timeout] || 60) do
422
+ @heartbeat = server_heartbeat.accept
423
+ @pid = heartbeat.gets.chomp.to_i
424
+
425
+ # Send a heartbeat to the child process running the simulator every 5 seconds
426
+ Thread.new do
427
+ loop do
428
+ heartbeat.write("OK\n")
429
+ sleep 5
430
+ end
431
+ end
432
+
433
+ @stdout = server_stdout.accept
434
+ @stderr = server_stderr.accept
306
435
  @socket = server.accept
307
436
  @connection_established = true
308
437
  if @connection_timed_out
@@ -327,22 +456,9 @@ module OrigenSim
327
456
  Origen.listeners_for(:simulation_startup).each(&:simulation_startup)
328
457
  end
329
458
 
330
- # Returns the pid of the simulator process
331
- def pid
332
- return @pid if @pid_set
333
- @pid = File.readlines(pid_file).first.strip.to_i if File.exist?(pid_file)
334
- @pid ||= 0
335
- @pid_set = true
336
- @pid
337
- end
338
-
339
- def pid_file
340
- "#{Origen.root}/tmp/origen_sim/pids/#{socket_number}"
341
- end
342
-
343
459
  # Returns true if the simulator process is running
344
460
  def running?
345
- return false if pid == 0
461
+ return false unless pid
346
462
  begin
347
463
  Process.getpgid(pid)
348
464
  true
@@ -474,6 +590,7 @@ module OrigenSim
474
590
 
475
591
  def cycle(number_of_cycles)
476
592
  put("3^#{number_of_cycles}")
593
+ read_sim_output
477
594
  end
478
595
 
479
596
  # Blocks the Origen process until the simulator indicates that it has
@@ -484,11 +601,42 @@ module OrigenSim
484
601
  unless data.strip == 'OK!'
485
602
  fail 'Origen and the simulator are out of sync!'
486
603
  end
604
+ read_sim_output
605
+ end
606
+
607
+ def read_sim_output
608
+ while stdout.ready?
609
+ line = stdout.gets.chomp
610
+ if OrigenSim.error_strings.any? { |s| line =~ /#{s}/ } &&
611
+ !OrigenSim.error_string_exceptions.any? { |s| line =~ /#{s}/ }
612
+ @simulator_logged_errors = true
613
+ Origen.log.error "(STDOUT): #{line}"
614
+ else
615
+ if OrigenSim.verbose? ||
616
+ OrigenSim.log_strings.any? { |s| line =~ /#{s}/ }
617
+ Origen.log.info line
618
+ else
619
+ Origen.log.debug line
620
+ end
621
+ end
622
+ end
623
+ while stderr.ready?
624
+ line = stderr.gets.chomp
625
+ if OrigenSim.fail_on_stderr && !OrigenSim.stderr_string_exceptions.any? { |s| line =~ /#{s}/ }
626
+ # We're failing on stderr, so print its results and log as errors if its not an exception.
627
+ @stderr_logged_errors = true
628
+ Origen.log.error "(STDERR): #{line}"
629
+ elsif OrigenSim.verbose?
630
+ # We're not failing on stderr, or the string in stderr is an exception.
631
+ # Print the string as regular output if verbose is set, otherwise just ignore.
632
+ Origen.log.info line
633
+ end
634
+ end
487
635
  end
488
636
 
489
637
  # Returns the current simulation error count
490
638
  def error_count
491
- peek('origen.debug.errors').to_i
639
+ peek("#{testbench_top}.debug.errors").to_i
492
640
  end
493
641
 
494
642
  # Returns the current value of the given net, or nil if the given path does not
@@ -546,7 +694,6 @@ module OrigenSim
546
694
 
547
695
  v = peek(path)
548
696
  return nil unless v
549
-
550
697
  # Setting a range of bits
551
698
  if lsb
552
699
  upper = v >> (msb + 1)
@@ -588,15 +735,16 @@ module OrigenSim
588
735
  Origen.listeners_for(:simulation_shutdown).each(&:simulation_shutdown)
589
736
  ended = Time.now
590
737
  end_simulation
591
- # Give the simulator a few seconds to shut down, otherwise kill it
592
- sleep 1 while running? && (Time.now - ended) < 10
593
- Process.kill(15, pid) if running?
594
- sleep 0.1
595
- # Leave the pid file around if we couldn't verify the simulator
596
- # has stopped
597
- FileUtils.rm_f(pid_file) if File.exist?(pid_file) && !running?
598
- @socket.close if @socket
738
+ # Give the simulator time to shut down
739
+ sleep 0.1 while running?
740
+ socket.close if socket
741
+ stderr.close if stderr
742
+ stdout.close if stdout
743
+ heartbeat.close if heartbeat
599
744
  File.unlink(socket_id) if File.exist?(socket_id)
745
+ File.unlink(socket_id(:stderr)) if File.exist?(socket_id(:stderr))
746
+ File.unlink(socket_id(:stdout)) if File.exist?(socket_id(:stdout))
747
+ File.unlink(socket_id(:heartbeat)) if File.exist?(socket_id(:heartbeat))
600
748
  end
601
749
 
602
750
  def on_origen_shutdown
@@ -605,9 +753,11 @@ module OrigenSim
605
753
  Origen.log.debug 'Shutting down simulator...'
606
754
  unless @failed_to_start
607
755
  c = error_count
608
- if c > 0
756
+ if c > 0 || @simulator_logged_errors || @stderr_logged_errors
609
757
  @failed = true
610
- Origen.log.error "The simulation failed with #{c} errors!"
758
+ Origen.log.error "The simulation failed with #{c} errors!" if c > 0
759
+ Origen.log.error 'The simulation log reported errors!' if @simulator_logged_errors
760
+ Origen.log.error 'The simulation stderr reported errors!' if @stderr_logged_errors
611
761
  elsif !@simulation_completed_cleanly
612
762
  @failed = true
613
763
  Origen.log.error 'The simulation exited early!'
@@ -630,12 +780,10 @@ module OrigenSim
630
780
  puts
631
781
  end
632
782
  end
633
- ensure
634
- Process.kill(15, pid) if @enabled && running?
635
783
  end
636
784
 
637
- def socket_id
638
- @socket_id ||= "/tmp/#{socket_number}.sock"
785
+ def socket_id(type = nil)
786
+ @socket_ids[type] ||= "/tmp/#{socket_number}#{type}.sock"
639
787
  end
640
788
 
641
789
  def socket_number
@@ -654,7 +802,7 @@ module OrigenSim
654
802
  # release our process and then exit
655
803
  unless @connection_established
656
804
  @connection_timed_out = true
657
- UNIXSocket.new(socket_id).puts(message)
805
+ UNIXSocket.new(socket_id).puts("Time out\n")
658
806
  end
659
807
  end
660
808
  yield
@@ -5,8 +5,15 @@ module OrigenSim
5
5
 
6
6
  TEST_PROGRAM_GENERATOR = OrigenSim::Generator
7
7
 
8
- def initialize(options = {})
9
- simulator.configure(options)
8
+ def initialize(options = {}, &block)
9
+ # Use Origen's collector to allow options to be set either from the options hash, or from the block
10
+ if block_given?
11
+ opts = Origen::Utility.collector(hash: options, merge_method: :keep_hash, &block).to_hash
12
+ else
13
+ opts = options
14
+ end
15
+
16
+ simulator.configure(opts, &block)
10
17
  super()
11
18
  end
12
19
 
data/lib/origen_sim.rb CHANGED
@@ -23,5 +23,82 @@ module OrigenSim
23
23
  def self.simulator
24
24
  @simulator
25
25
  end
26
+
27
+ # Provide some shortcut methods to set the vendor
28
+ def self.generic(options = {}, &block)
29
+ Tester.new(options.merge(vendor: :generic), &block)
30
+ end
31
+
32
+ def self.cadence(options = {}, &block)
33
+ Tester.new(options.merge(vendor: :cadence), &block)
34
+ end
35
+
36
+ def self.synopsys(optoins = {}, &block)
37
+ Tester.new(options.merge(vendor: :synopsys), &block)
38
+ end
39
+
40
+ def self.icarus(options = {}, &block)
41
+ Tester.new(options.merge(vendor: :icarus), &block)
42
+ end
43
+
44
+ def self.verbose=(val)
45
+ @verbose = val
46
+ end
47
+
48
+ def self.verbose?
49
+ !!(@verbose || Origen.debugger_enabled?)
50
+ end
51
+
52
+ def self.error_strings
53
+ @error_strings ||= ['ERROR']
54
+ end
55
+
56
+ def self.error_strings=(val)
57
+ unless val.is_a?(Array)
58
+ fail 'OrigenSim.error_strings can only be set to an array of string values!'
59
+ end
60
+ @error_strings = val
61
+ end
62
+
63
+ def self.error_string_exceptions
64
+ @error_string_exceptions ||= []
65
+ end
66
+
67
+ def self.error_string_exceptions=(val)
68
+ unless val.is_a?(Array)
69
+ fail 'OrigenSim.error_string_exceptions can only be set to an array of string values!'
70
+ end
71
+ @error_string_exceptions = val
72
+ end
73
+
74
+ def self.stderr_string_exceptions
75
+ @stderr_string_exceptions ||= []
76
+ end
77
+
78
+ def self.stderr_string_exceptions=(val)
79
+ unless val.is_a?(Array)
80
+ fail 'OrigenSim.error_string_exceptions can only be set to an array of string values!'
81
+ end
82
+ @stderr_string_exceptions = val
83
+ end
84
+
85
+ def self.log_strings
86
+ @log_strings ||= []
87
+ end
88
+
89
+ def self.log_strings=(val)
90
+ unless val.is_a?(Array)
91
+ fail 'OrigenSim.log_strings can only be set to an array of string values!'
92
+ end
93
+ @log_strings = val
94
+ end
95
+
96
+ def self.fail_on_stderr=(val)
97
+ @fail_on_stderr = val
98
+ end
99
+
100
+ def self.fail_on_stderr
101
+ defined?(@fail_on_stderr) ? @fail_on_stderr : true
102
+ end
26
103
  end
27
104
  OrigenSim.__instantiate_simulator__
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: origen_sim
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen McGinty
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-06 00:00:00.000000000 Z
11
+ date: 2018-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: origen
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0.32'
19
+ version: 0.33.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0.32'
26
+ version: 0.33.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: origen_testers
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -78,6 +78,7 @@ files:
78
78
  - lib/origen_sim/commands/build.rb
79
79
  - lib/origen_sim/commands/ci.rb
80
80
  - lib/origen_sim/commands/co.rb
81
+ - lib/origen_sim/commands/pack.rb
81
82
  - lib/origen_sim/flow.rb
82
83
  - lib/origen_sim/generator.rb
83
84
  - lib/origen_sim/origen/pins/pin.rb