origen_sim 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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