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 +4 -4
- data/config/shared_commands.rb +18 -0
- data/config/version.rb +1 -1
- data/ext/bridge.c +6 -6
- data/ext/common.h +4 -0
- data/ext/defines.h.erb +1 -0
- data/ext/origen.c +8 -0
- data/lib/origen_sim/commands/build.rb +4 -2
- data/lib/origen_sim/commands/pack.rb +37 -0
- data/lib/origen_sim/simulator.rb +206 -58
- data/lib/origen_sim/tester.rb +9 -2
- data/lib/origen_sim.rb +77 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f670da6bba360fa76ac30b10cd097cde48d6353a
|
4
|
+
data.tar.gz: 07a1c407163212fd4fd04b45336ff399751155e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f0bcd9d653bf6ba02617116e3d843c9e1f39c20f023544b9cf5bbf152289fd9fa5654be8d72b2bcd77928f0a26041ed4da9370110b1281b98e1e7568df73aa5
|
7
|
+
data.tar.gz: 1bd7de244589567b366d0213279df4f295f0ed374311bfc1b22d0666eacfd6855c19ecaa7fe4f7c6214452d54fb0ab4076b69f3714fae397dc9d25142ebfa580
|
data/config/shared_commands.rb
CHANGED
@@ -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
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, "
|
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("
|
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("
|
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("
|
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("
|
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("
|
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
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
|
data/lib/origen_sim/simulator.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
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
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
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
|
-
|
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
|
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(
|
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
|
592
|
-
sleep 1 while running?
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
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
|
-
@
|
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(
|
805
|
+
UNIXSocket.new(socket_id).puts("Time out\n")
|
658
806
|
end
|
659
807
|
end
|
660
808
|
yield
|
data/lib/origen_sim/tester.rb
CHANGED
@@ -5,8 +5,15 @@ module OrigenSim
|
|
5
5
|
|
6
6
|
TEST_PROGRAM_GENERATOR = OrigenSim::Generator
|
7
7
|
|
8
|
-
def initialize(options = {})
|
9
|
-
|
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.
|
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-
|
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:
|
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:
|
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
|