origen_sim 0.9.0 → 0.10.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 +4 -4
- data/config/application.rb +3 -1
- data/config/shared_commands.rb +3 -0
- data/config/version.rb +1 -1
- data/lib/origen_sim/commands/build.rb +127 -109
- data/lib/origen_sim/heartbeat.rb +21 -0
- data/lib/origen_sim/origen/application/runner.rb +19 -0
- data/lib/origen_sim/simulation.rb +157 -0
- data/lib/origen_sim/simulator.rb +156 -162
- data/lib/origen_sim.rb +14 -1
- data/pattern/test.rb +5 -5
- data/pattern/test2.rb +1 -0
- data/program/p1.rb +2 -2
- data/program/p2.rb +1 -0
- data/templates/probe.tcl.erb +1 -1
- data/templates/rtl_v/origen.v.erb +1 -1
- metadata +10 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b31bfc2f252031780f05373507dbbb75db36300
|
4
|
+
data.tar.gz: fb37cfeb67cde82e1f829630b36ea6752e581189
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f86cbee77db2cd17707e7c68aa96a70a18922772207e302b7abf6c416d9e28a2a0c2035339d28f3fde56214a6331a6e657a0be3b1b3945dfc5b1566d673d1e91
|
7
|
+
data.tar.gz: 865533e70e134f220837accecdbefa616f1df14f8cf185bc3584a923e3c5af4afe2d5a3b7662221de125b0b45c5eb975569bfe51da679dc442d10e4c5f38e0df
|
data/config/application.rb
CHANGED
@@ -57,7 +57,9 @@ class OrigenSimApplication < Origen::Application
|
|
57
57
|
|
58
58
|
# An example of how to set application specific LSF parameters
|
59
59
|
#config.lsf.project = "msg.te"
|
60
|
-
|
60
|
+
config.lsf.queue = ENV["ORIGEN_LSF_QUEUE"] if ENV["ORIGEN_LSF_QUEUE"]
|
61
|
+
config.lsf.resource = ENV["ORIGEN_LSF_RESOURCE"] if ENV["ORIGEN_LSF_RESOURCE"]
|
62
|
+
|
61
63
|
# An example of how to specify a prefix to add to all generated patterns
|
62
64
|
#config.pattern_prefix = "nvm"
|
63
65
|
|
data/config/shared_commands.rb
CHANGED
@@ -5,9 +5,12 @@ when 'generate'
|
|
5
5
|
$use_fast_probe_depth = false
|
6
6
|
@application_options << ["--fast", "Fast simulation, minimum probe depth"]
|
7
7
|
$use_fast_probe_depth = ARGV.include?('--fast')
|
8
|
+
|
8
9
|
@application_options << ["--sim_capture", "Update sim captures (ignored when not running a simulation)"]
|
9
10
|
Origen.app!.update_sim_captures = ARGV.include?('--sim_capture')
|
10
11
|
|
12
|
+
@application_options << ["--flow NAME", "Simulate multiple patterns back-back within a single simulation with the given name", ->(options, name) { OrigenSim.flow = name }]
|
13
|
+
|
11
14
|
when "sim:ci", "origen_sim:ci"
|
12
15
|
require "#{Origen.root!}/lib/origen_sim/commands/ci"
|
13
16
|
exit 0
|
data/config/version.rb
CHANGED
@@ -3,7 +3,7 @@ require 'origen_sim'
|
|
3
3
|
require_relative '../../../config/version'
|
4
4
|
require 'origen_verilog'
|
5
5
|
|
6
|
-
options = { source_dirs: [], testbench_name: 'origen' }
|
6
|
+
options = { source_dirs: [], testbench_name: 'origen', defines: [] }
|
7
7
|
|
8
8
|
# App options are options that the application can supply to extend this command
|
9
9
|
app_options = @application_options || []
|
@@ -22,6 +22,9 @@ Usage: origen sim:build TOP_LEVEL_VERILOG_FILE [options]
|
|
22
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|
|
23
23
|
options[:source_dirs] << path
|
24
24
|
end
|
25
|
+
opts.on('--define MACRO', 'Specify a compiler define') do |macro|
|
26
|
+
options[:defines] << macro
|
27
|
+
end
|
25
28
|
opts.on('-d', '--debugger', 'Enable the debugger') { options[:debugger] = true }
|
26
29
|
app_options.each do |app_option|
|
27
30
|
opts.on(*app_option) {}
|
@@ -32,21 +35,30 @@ end
|
|
32
35
|
|
33
36
|
opt_parser.parse! ARGV
|
34
37
|
|
38
|
+
def _exit_fail_
|
39
|
+
if $_testing_build_return_dut_
|
40
|
+
return nil
|
41
|
+
else
|
42
|
+
exit 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
35
46
|
unless ARGV.size > 0
|
36
47
|
puts 'You must supply a path to the top-level RTL file'
|
37
|
-
|
48
|
+
_exit_fail_
|
38
49
|
end
|
39
|
-
|
50
|
+
files = ARGV.first
|
51
|
+
rtl_top = files.split(/\s+/).last
|
40
52
|
unless File.exist?(rtl_top)
|
41
53
|
puts "File does not exist: #{rtl_top}"
|
42
|
-
|
54
|
+
_exit_fail_
|
43
55
|
end
|
44
56
|
|
45
|
-
ast = OrigenVerilog.parse_file(
|
57
|
+
ast = OrigenVerilog.parse_file(files, options)
|
46
58
|
|
47
59
|
unless ast
|
48
60
|
puts 'Sorry, but the given top-level RTL file failed to parse'
|
49
|
-
|
61
|
+
_exit_fail_
|
50
62
|
end
|
51
63
|
|
52
64
|
candidates = ast.top_level_modules
|
@@ -54,7 +66,7 @@ candidates = ast.modules if candidates.empty?
|
|
54
66
|
|
55
67
|
if candidates.size == 0
|
56
68
|
puts "Sorry, couldn't find any Verilog module declarations in that file"
|
57
|
-
|
69
|
+
_exit_fail_
|
58
70
|
elsif candidates.size > 1
|
59
71
|
if options[:top_level_name]
|
60
72
|
mod = candidates.find { |c| c.name == options[:top_level_name] }
|
@@ -64,7 +76,7 @@ elsif candidates.size > 1
|
|
64
76
|
candidates.each do |c|
|
65
77
|
puts " #{c.name}"
|
66
78
|
end
|
67
|
-
|
79
|
+
_exit_fail_
|
68
80
|
end
|
69
81
|
else
|
70
82
|
mod = candidates.first
|
@@ -74,104 +86,110 @@ rtl_top_module = mod.name
|
|
74
86
|
|
75
87
|
mod.to_top_level # Creates dut
|
76
88
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
puts
|
101
|
-
puts
|
102
|
-
puts
|
103
|
-
puts
|
104
|
-
puts
|
105
|
-
puts
|
106
|
-
puts
|
107
|
-
puts
|
108
|
-
puts
|
109
|
-
puts
|
110
|
-
puts
|
111
|
-
puts
|
112
|
-
puts
|
113
|
-
puts
|
114
|
-
puts '
|
115
|
-
puts
|
116
|
-
puts
|
117
|
-
puts
|
118
|
-
puts ' -
|
119
|
-
puts
|
120
|
-
puts '
|
121
|
-
puts
|
122
|
-
puts
|
123
|
-
puts
|
124
|
-
puts
|
125
|
-
puts
|
126
|
-
puts
|
127
|
-
puts
|
128
|
-
puts
|
129
|
-
puts '
|
130
|
-
puts
|
131
|
-
puts
|
132
|
-
puts
|
133
|
-
puts
|
134
|
-
puts
|
135
|
-
puts
|
136
|
-
puts
|
137
|
-
puts '
|
138
|
-
puts
|
139
|
-
puts "
|
140
|
-
puts
|
141
|
-
puts
|
142
|
-
puts ' -
|
143
|
-
puts '
|
144
|
-
puts
|
145
|
-
puts '
|
146
|
-
puts
|
147
|
-
puts
|
148
|
-
puts
|
149
|
-
puts
|
150
|
-
puts
|
151
|
-
puts
|
152
|
-
puts '
|
153
|
-
puts
|
154
|
-
puts '
|
155
|
-
puts
|
156
|
-
puts '
|
157
|
-
puts
|
158
|
-
puts
|
159
|
-
puts
|
160
|
-
puts
|
161
|
-
puts
|
162
|
-
puts
|
163
|
-
puts
|
164
|
-
puts
|
165
|
-
puts '
|
166
|
-
puts
|
167
|
-
puts
|
168
|
-
puts
|
169
|
-
puts
|
170
|
-
puts
|
171
|
-
puts
|
172
|
-
puts
|
173
|
-
puts
|
174
|
-
puts
|
175
|
-
puts '
|
176
|
-
puts
|
177
|
-
puts
|
89
|
+
if $_testing_build_return_dut_
|
90
|
+
dut
|
91
|
+
|
92
|
+
else
|
93
|
+
|
94
|
+
output_directory = options[:output] || Origen.config.output_directory
|
95
|
+
|
96
|
+
Origen.app.runner.launch action: :compile,
|
97
|
+
files: "#{Origen.root!}/templates/rtl_v/origen.v.erb",
|
98
|
+
output: output_directory,
|
99
|
+
check_for_changes: false,
|
100
|
+
quiet: true,
|
101
|
+
options: { vendor: :cadence, top: dut.name, incl: options[:incl_files] }
|
102
|
+
|
103
|
+
Origen.app.runner.launch action: :compile,
|
104
|
+
files: "#{Origen.root!}/ext",
|
105
|
+
output: output_directory,
|
106
|
+
check_for_changes: false,
|
107
|
+
quiet: true,
|
108
|
+
options: options
|
109
|
+
|
110
|
+
dut.export(rtl_top_module, dir: "#{output_directory}", namespace: nil)
|
111
|
+
|
112
|
+
puts
|
113
|
+
puts
|
114
|
+
puts 'Testbench and VPI extension created!'
|
115
|
+
puts
|
116
|
+
puts 'This file can be imported into an Origen top-level DUT model to define the pins:'
|
117
|
+
puts
|
118
|
+
puts " #{output_directory}/#{rtl_top_module}.rb"
|
119
|
+
puts
|
120
|
+
puts 'See below for what to do now to create an Origen-enabled simulation object for your particular simulator:'
|
121
|
+
puts
|
122
|
+
puts '-----------------------------------------------------------'
|
123
|
+
puts 'Cadence Incisive (irun)'
|
124
|
+
puts '-----------------------------------------------------------'
|
125
|
+
puts
|
126
|
+
puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
|
127
|
+
puts
|
128
|
+
puts " #{output_directory}/origen.v \\"
|
129
|
+
puts " #{output_directory}/*.c \\"
|
130
|
+
puts ' -ccargs "-std=c99" \\'
|
131
|
+
puts ' -top origen \\'
|
132
|
+
puts ' -elaborate \\'
|
133
|
+
puts ' -snapshot origen \\'
|
134
|
+
puts ' -access +rw \\'
|
135
|
+
puts ' -timescale 1ns/1ns'
|
136
|
+
puts
|
137
|
+
puts 'Here is an example which may work for the file you just parsed (add additional -incdir options at the end if required):'
|
138
|
+
puts
|
139
|
+
puts " #{ENV['ORIGEN_SIM_IRUN'] || 'irun'} #{rtl_top} #{output_directory}/origen.v #{output_directory}/*.c -ccargs \"-std=c99\" -top origen -elaborate -snapshot origen -access +rw -timescale 1ns/1ns -incdir #{Pathname.new(rtl_top).dirname}"
|
140
|
+
puts
|
141
|
+
puts 'Copy the following directory (produced by irun) to simulation/<target>/cadence/. within your Origen application:'
|
142
|
+
puts
|
143
|
+
puts ' INCA_libs'
|
144
|
+
puts
|
145
|
+
puts '-----------------------------------------------------------'
|
146
|
+
puts 'Synopsys VCS'
|
147
|
+
puts '-----------------------------------------------------------'
|
148
|
+
puts
|
149
|
+
puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
|
150
|
+
puts
|
151
|
+
puts " #{output_directory}/origen.v \\"
|
152
|
+
puts " #{output_directory}/brdige.c \\"
|
153
|
+
puts " #{output_directory}/client.c \\"
|
154
|
+
puts ' -CFLAGS "-std=c99" \\'
|
155
|
+
puts ' +vpi \\'
|
156
|
+
puts " -use_vpiobj #{output_directory}/origen.c \\"
|
157
|
+
puts ' +define+ORIGEN_VPD=1 \\'
|
158
|
+
puts ' -debug_access+all \\'
|
159
|
+
puts ' -PP \\'
|
160
|
+
puts ' -timescale=1ns/1ns'
|
161
|
+
puts
|
162
|
+
puts 'Here is an example which may work for the file you just parsed (add additional -incdir options at the end if required):'
|
163
|
+
puts
|
164
|
+
puts " #{ENV['ORIGEN_SIM_VCS'] || 'vcs'} #{rtl_top} #{output_directory}/origen.v #{output_directory}/bridge.c #{output_directory}/client.c -CFLAGS \"-std=c99\" +vpi -use_vpiobj #{output_directory}/origen.c -timescale=1ns/1ns +define+ORIGEN_VPD=1 +incdir+#{Pathname.new(rtl_top).dirname} -debug_access+all -PP"
|
165
|
+
puts
|
166
|
+
puts 'Copy the following files (produced by vcs) to simulation/<target>/synopsys/. within your Origen application:'
|
167
|
+
puts
|
168
|
+
puts ' simv'
|
169
|
+
puts ' simv.daidir'
|
170
|
+
puts
|
171
|
+
puts '-----------------------------------------------------------'
|
172
|
+
puts 'Icarus Verilog'
|
173
|
+
puts '-----------------------------------------------------------'
|
174
|
+
puts
|
175
|
+
puts 'Compile the VPI extension using the following command:'
|
176
|
+
puts
|
177
|
+
puts " cd #{output_directory} && #{ENV['ORIGEN_SIM_IVERILOG_VPI'] || 'iverilog-vpi'} *.c --name=origen && cd #{Pathname.pwd}"
|
178
|
+
puts
|
179
|
+
puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
|
180
|
+
puts
|
181
|
+
puts " #{output_directory}/origen.v \\"
|
182
|
+
puts ' -o origen.vvp \\'
|
183
|
+
puts ' -DORIGEN_VCD'
|
184
|
+
puts
|
185
|
+
puts 'Here is an example which may work for the file you just parsed (add additional source dirs with more -I options at the end if required):'
|
186
|
+
puts
|
187
|
+
puts " #{ENV['ORIGEN_SIM_IVERILOG'] || 'iverilog'} #{rtl_top} #{output_directory}/origen.v -o origen.vvp -DORIGEN_VCD -I #{Pathname.new(rtl_top).dirname}"
|
188
|
+
puts
|
189
|
+
puts 'Copy the following files (produced by iverilog) to simulation/<target>/icarus/. within your Origen application:'
|
190
|
+
puts
|
191
|
+
puts " #{output_directory}/origen.vpi"
|
192
|
+
puts ' origen.vvp'
|
193
|
+
puts
|
194
|
+
puts
|
195
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'thread'
|
2
|
+
module OrigenSim
|
3
|
+
class Heartbeat < Thread
|
4
|
+
attr_reader :socket
|
5
|
+
|
6
|
+
def initialize(socket)
|
7
|
+
@socket = socket
|
8
|
+
@continue = true
|
9
|
+
super do
|
10
|
+
while @continue
|
11
|
+
socket.write("OK\n")
|
12
|
+
sleep 5
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def stop
|
18
|
+
@continue = false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'origen/application/runner'
|
2
|
+
module Origen
|
3
|
+
class Application
|
4
|
+
class Runner
|
5
|
+
# When multiple patterns are requested via the command line with the LSF option,
|
6
|
+
# Origen will split it into separate jobs for each pattern. However, if the --flow
|
7
|
+
# option is also supplied in that case, then the user will want all the patterns to
|
8
|
+
# execute as a single job on the LSF, this hack to Origen makes that happen.
|
9
|
+
alias_method :orig_expand_lists_and_directories, :expand_lists_and_directories
|
10
|
+
def expand_lists_and_directories(files, options = {})
|
11
|
+
if (options[:lsf] && OrigenSim.flow) && !Origen.running_remotely?
|
12
|
+
Array(Array(files).join(' '))
|
13
|
+
else
|
14
|
+
orig_expand_lists_and_directories(files, options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'io/wait'
|
3
|
+
require 'origen_sim/heartbeat'
|
4
|
+
module OrigenSim
|
5
|
+
# Responsible for managing each individual simulation that is run in an
|
6
|
+
# Origen thread e.g. If multiple patterns are run in separate simulations, then one
|
7
|
+
# instance of this class will exist for each one.
|
8
|
+
#
|
9
|
+
# It is primarily responsible for all communications with the simulation and capturing
|
10
|
+
# log output and errors.
|
11
|
+
class Simulation
|
12
|
+
attr_reader :view_wave_command, :id
|
13
|
+
|
14
|
+
attr_accessor :logged_errors, :error_count, :failed_to_start, :completed_cleanly
|
15
|
+
attr_accessor :pid, :stderr_logged_errors
|
16
|
+
# Returns the communication socket used for sending commands to the Origen VPI running
|
17
|
+
# in the simulation process
|
18
|
+
attr_reader :socket
|
19
|
+
|
20
|
+
def initialize(id, view_wave_command)
|
21
|
+
@id = id
|
22
|
+
@view_wave_command = view_wave_command
|
23
|
+
@completed_cleanly = false
|
24
|
+
@failed_to_start = false
|
25
|
+
@logged_errors = false
|
26
|
+
@stderr_logged_errors = false
|
27
|
+
@error_count = 0
|
28
|
+
@socket_ids = {}
|
29
|
+
|
30
|
+
@server = UNIXServer.new(socket_id) # Socket used to send Origen -> Verilog commands
|
31
|
+
@server_stdout = UNIXServer.new(socket_id(:stdout))
|
32
|
+
@server_stderr = UNIXServer.new(socket_id(:stderr))
|
33
|
+
@server_heartbeat = UNIXServer.new(socket_id(:heartbeat))
|
34
|
+
end
|
35
|
+
|
36
|
+
def failed?(in_progress = false)
|
37
|
+
failed = stderr_logged_errors || logged_errors || failed_to_start || error_count > 0
|
38
|
+
if in_progress
|
39
|
+
failed
|
40
|
+
else
|
41
|
+
failed || !completed_cleanly
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def log_results(in_progress = false)
|
46
|
+
if failed?(in_progress)
|
47
|
+
if failed_to_start
|
48
|
+
Origen.log.error 'The simulation failed to start!'
|
49
|
+
else
|
50
|
+
if in_progress
|
51
|
+
Origen.log.error "The simulation has #{error_count} error#{error_count > 1 ? 's' : ''}!" if error_count > 0
|
52
|
+
else
|
53
|
+
Origen.log.error "The simulation failed with #{error_count} errors!" if error_count > 0
|
54
|
+
end
|
55
|
+
Origen.log.error 'The simulation log reported errors!' if logged_errors
|
56
|
+
Origen.log.error 'The simulation stderr reported errors!' if stderr_logged_errors
|
57
|
+
Origen.log.error 'The simulation exited early!' unless completed_cleanly || in_progress
|
58
|
+
end
|
59
|
+
else
|
60
|
+
if in_progress
|
61
|
+
Origen.log.success 'The simulation is passing!'
|
62
|
+
else
|
63
|
+
Origen.log.success 'The simulation passed!'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Provide a heartbeat to let the parallel Ruby process in charge of the simulator
|
69
|
+
# know that the master Origen process is still alive. If the Origen process crashes and leaves
|
70
|
+
# the simulator running, the child process will automatically reap it after a couple of missed
|
71
|
+
# heartbeats.
|
72
|
+
def start_heartbeat
|
73
|
+
@heartbeat = @server_heartbeat.accept
|
74
|
+
@pid = @heartbeat.gets.chomp.to_i
|
75
|
+
@heartbeat_thread = Heartbeat.new(@heartbeat)
|
76
|
+
end
|
77
|
+
|
78
|
+
def stop_heartbeat
|
79
|
+
@heartbeat_thread.stop
|
80
|
+
end
|
81
|
+
|
82
|
+
# Open the communication channels with the simulator
|
83
|
+
def open
|
84
|
+
start_heartbeat
|
85
|
+
@stdout = @server_stdout.accept
|
86
|
+
@stderr = @server_stderr.accept
|
87
|
+
@socket = @server.accept
|
88
|
+
@opened = true
|
89
|
+
end
|
90
|
+
|
91
|
+
# Close all communication channels with the simulator
|
92
|
+
def close
|
93
|
+
return unless @opened
|
94
|
+
stop_heartbeat
|
95
|
+
@heartbeat.close
|
96
|
+
@socket.close
|
97
|
+
@stderr.close
|
98
|
+
@stdout.close
|
99
|
+
File.unlink(socket_id(:heartbeat)) if File.exist?(socket_id(:heartbeat))
|
100
|
+
File.unlink(socket_id) if File.exist?(socket_id)
|
101
|
+
File.unlink(socket_id(:stderr)) if File.exist?(socket_id(:stderr))
|
102
|
+
File.unlink(socket_id(:stdout)) if File.exist?(socket_id(:stdout))
|
103
|
+
end
|
104
|
+
|
105
|
+
def read_sim_output
|
106
|
+
while @stdout.ready?
|
107
|
+
line = @stdout.gets.chomp
|
108
|
+
if OrigenSim.error_strings.any? { |s| line =~ /#{s}/ } &&
|
109
|
+
!OrigenSim.error_string_exceptions.any? { |s| line =~ /#{s}/ }
|
110
|
+
@logged_errors = true
|
111
|
+
Origen.log.error "(STDOUT): #{line}"
|
112
|
+
else
|
113
|
+
if OrigenSim.verbose? ||
|
114
|
+
OrigenSim.log_strings.any? { |s| line =~ /#{s}/ }
|
115
|
+
Origen.log.info line
|
116
|
+
else
|
117
|
+
Origen.log.debug line
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
while @stderr.ready?
|
122
|
+
line = @stderr.gets.chomp
|
123
|
+
if OrigenSim.fail_on_stderr && !line.empty? &&
|
124
|
+
!OrigenSim.stderr_string_exceptions.any? { |s| line =~ /#{s}/ }
|
125
|
+
# We're failing on stderr, so print its results and log as errors if its not an exception.
|
126
|
+
@stderr_logged_errors = true
|
127
|
+
Origen.log.error "(STDERR): #{line}"
|
128
|
+
elsif OrigenSim.verbose?
|
129
|
+
# We're not failing on stderr, or the string in stderr is an exception.
|
130
|
+
# Print the string as regular output if verbose is set, otherwise just ignore.
|
131
|
+
Origen.log.info line
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Returns true if the simulation is running
|
137
|
+
def running?
|
138
|
+
return false unless pid
|
139
|
+
begin
|
140
|
+
Process.getpgid(pid)
|
141
|
+
true
|
142
|
+
rescue Errno::ESRCH
|
143
|
+
false
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def socket_id(type = nil)
|
148
|
+
@socket_ids[type] ||= "/tmp/#{socket_number}#{type}.sock"
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
def socket_number
|
154
|
+
@socket_number ||= (Process.pid.to_s + Time.now.to_f.to_s).sub('.', '')
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
data/lib/origen_sim/simulator.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
require 'io/wait'
|
1
|
+
require 'origen_sim/simulation'
|
3
2
|
module OrigenSim
|
4
3
|
# Responsible for managing and communicating with the simulator
|
5
4
|
# process, a single instance of this class is instantiated as
|
@@ -9,13 +8,17 @@ module OrigenSim
|
|
9
8
|
|
10
9
|
VENDORS = [:icarus, :cadence, :synopsys, :generic]
|
11
10
|
|
12
|
-
attr_reader :
|
11
|
+
attr_reader :configuration
|
13
12
|
alias_method :config, :configuration
|
14
|
-
#
|
15
|
-
attr_reader :
|
13
|
+
# The instance of OrigenSim::Simulation for the current simulation
|
14
|
+
attr_reader :simulation
|
15
|
+
# Returns an array containing all instances of OrigenSim::Simulation that were created
|
16
|
+
# in the order that they were created
|
17
|
+
attr_reader :simulations
|
16
18
|
|
17
19
|
def initialize
|
18
|
-
@
|
20
|
+
@simulations = []
|
21
|
+
@simulation_open = false
|
19
22
|
end
|
20
23
|
|
21
24
|
# When set to true the simulator will log all messages it receives, note that
|
@@ -140,7 +143,7 @@ module OrigenSim
|
|
140
143
|
end
|
141
144
|
end
|
142
145
|
|
143
|
-
def wave_dir
|
146
|
+
def wave_dir(subdir = nil)
|
144
147
|
@wave_dir ||= begin
|
145
148
|
d = "#{Origen.root}/waves/#{id}"
|
146
149
|
FileUtils.mkdir_p(d)
|
@@ -198,17 +201,17 @@ module OrigenSim
|
|
198
201
|
cmd += " -M#{compiled_dir} -morigen #{compiled_dir}/origen.vvp +socket+#{socket_id}"
|
199
202
|
|
200
203
|
when :cadence
|
201
|
-
input_file = "#{tmp_dir}/#{
|
204
|
+
input_file = "#{tmp_dir}/#{wave_file_basename}.tcl"
|
202
205
|
if !File.exist?(input_file) || config_changed?
|
203
206
|
Origen.app.runner.launch action: :compile,
|
204
207
|
files: "#{Origen.root!}/templates/probe.tcl.erb",
|
205
208
|
output: tmp_dir,
|
206
209
|
check_for_changes: false,
|
207
210
|
quiet: true,
|
208
|
-
options: { dir: wave_dir, force: config[:force], setup: config[:setup], depth: :all },
|
209
|
-
output_file_name: "#{
|
211
|
+
options: { dir: wave_dir, wave_file: wave_file_basename, force: config[:force], setup: config[:setup], depth: :all },
|
212
|
+
output_file_name: "#{wave_file_basename}.tcl"
|
210
213
|
end
|
211
|
-
input_file_fast = "#{tmp_dir}/#{
|
214
|
+
input_file_fast = "#{tmp_dir}/#{wave_file_basename}_fast.tcl"
|
212
215
|
if !File.exist?(input_file_fast) || config_changed?
|
213
216
|
fast_probe_depth = config[:fast_probe_depth] || 1
|
214
217
|
Origen.app.runner.launch action: :compile,
|
@@ -216,8 +219,8 @@ module OrigenSim
|
|
216
219
|
output: tmp_dir,
|
217
220
|
check_for_changes: false,
|
218
221
|
quiet: true,
|
219
|
-
options: { dir: wave_dir, force: config[:force], setup: config[:setup], depth: fast_probe_depth },
|
220
|
-
output_file_name: "#{
|
222
|
+
options: { dir: wave_dir, wave_file: wave_file_basename, force: config[:force], setup: config[:setup], depth: fast_probe_depth },
|
223
|
+
output_file_name: "#{wave_file_basename}_fast.tcl"
|
221
224
|
end
|
222
225
|
save_config_signature
|
223
226
|
wave_dir # Ensure this exists since it won't be referenced above if the input file is already generated
|
@@ -228,7 +231,7 @@ module OrigenSim
|
|
228
231
|
cmd += " -nclibdirpath #{compiled_dir}"
|
229
232
|
|
230
233
|
when :synopsys
|
231
|
-
cmd = "#{compiled_dir}/simv +socket+#{socket_id} -vpd_file
|
234
|
+
cmd = "#{compiled_dir}/simv +socket+#{socket_id} -vpd_file #{wave_file_basename}.vpd"
|
232
235
|
|
233
236
|
when :generic
|
234
237
|
# Generic tester requires that a generic_run_command option/block be provided.
|
@@ -269,6 +272,18 @@ module OrigenSim
|
|
269
272
|
cmd
|
270
273
|
end
|
271
274
|
|
275
|
+
def wave_file_basename
|
276
|
+
if OrigenSim.flow
|
277
|
+
OrigenSim.flow.to_s
|
278
|
+
else
|
279
|
+
if Origen.app.current_job
|
280
|
+
@last_wafe_file_basename = Pathname.new(Origen.app.current_job.output_file).basename('.*').to_s
|
281
|
+
else
|
282
|
+
@last_wafe_file_basename
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
272
287
|
def view_wave_command
|
273
288
|
cmd = nil
|
274
289
|
case config[:vendor]
|
@@ -277,7 +292,7 @@ module OrigenSim
|
|
277
292
|
cmd = "cd #{edir} && "
|
278
293
|
cmd += configuration[:gtkwave] || 'gtkwave'
|
279
294
|
dir = Pathname.new(wave_dir).relative_path_from(edir.expand_path)
|
280
|
-
cmd += " #{dir}/
|
295
|
+
cmd += " #{dir}/#{wave_file_basename}/dump.vcd "
|
281
296
|
f = Pathname.new(wave_config_file).relative_path_from(edir.expand_path)
|
282
297
|
cmd += " --save #{f} &"
|
283
298
|
|
@@ -286,7 +301,7 @@ module OrigenSim
|
|
286
301
|
cmd = "cd #{edir} && "
|
287
302
|
cmd += configuration[:simvision] || 'simvision'
|
288
303
|
dir = Pathname.new(wave_dir).relative_path_from(edir.expand_path)
|
289
|
-
cmd += " #{dir}/#{
|
304
|
+
cmd += " #{dir}/#{wave_file_basename}/#{wave_file_basename}.dsn #{dir}/#{wave_file_basename}/#{wave_file_basename}.trn"
|
290
305
|
f = Pathname.new(wave_config_file).relative_path_from(edir.expand_path)
|
291
306
|
cmd += " -input #{f} &"
|
292
307
|
|
@@ -295,7 +310,7 @@ module OrigenSim
|
|
295
310
|
cmd = "cd #{edir} && "
|
296
311
|
cmd += configuration[:dve] || 'dve'
|
297
312
|
dir = Pathname.new(wave_dir).relative_path_from(edir.expand_path)
|
298
|
-
cmd += " -vpd #{dir}
|
313
|
+
cmd += " -vpd #{dir}/#{wave_file_basename}.vpd"
|
299
314
|
f = Pathname.new(wave_config_file).relative_path_from(edir.expand_path)
|
300
315
|
cmd += " -session #{f}"
|
301
316
|
cmd += ' &'
|
@@ -320,31 +335,29 @@ module OrigenSim
|
|
320
335
|
|
321
336
|
def run_dir
|
322
337
|
case config[:vendor]
|
323
|
-
when :icarus
|
338
|
+
when :icarus
|
339
|
+
d = File.join(wave_dir, wave_file_basename)
|
340
|
+
FileUtils.mkdir_p(d)
|
341
|
+
d
|
342
|
+
when :synopsys
|
324
343
|
wave_dir
|
325
344
|
else
|
326
345
|
tmp_dir
|
327
346
|
end
|
328
347
|
end
|
329
348
|
|
349
|
+
def simulation_open?
|
350
|
+
@simulation_open
|
351
|
+
end
|
352
|
+
|
330
353
|
# Starts up the simulator process
|
331
354
|
def start
|
355
|
+
@simulation_open = true
|
356
|
+
@simulation = Simulation.new(wave_file_basename, view_wave_command)
|
357
|
+
simulations << @simulation
|
358
|
+
|
332
359
|
fetch_simulation_objects
|
333
360
|
|
334
|
-
# Socket used for Origen -> Verilog commands
|
335
|
-
server = UNIXServer.new(socket_id)
|
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)
|
348
361
|
cmd = run_cmd + ' & echo \$!'
|
349
362
|
|
350
363
|
launch_simulator = %(
|
@@ -355,9 +368,19 @@ module OrigenSim
|
|
355
368
|
|
356
369
|
pid = nil
|
357
370
|
|
358
|
-
|
359
|
-
|
360
|
-
|
371
|
+
def kill_simulation(pid)
|
372
|
+
begin
|
373
|
+
# If the process already finished, then we will see an Errno exception.
|
374
|
+
# It does not harm anything, but looks ugly, so catch it here and ignore.
|
375
|
+
Process.kill('KILL', pid)
|
376
|
+
rescue Errno::ESRCH => e
|
377
|
+
end
|
378
|
+
exit!
|
379
|
+
end
|
380
|
+
|
381
|
+
stdout_socket = UNIXSocket.new('#{simulation.socket_id(:stdout)}')
|
382
|
+
stderr_socket = UNIXSocket.new('#{simulation.socket_id(:stderr)}')
|
383
|
+
heartbeat = UNIXSocket.new('#{simulation.socket_id(:heartbeat)}')
|
361
384
|
|
362
385
|
begin
|
363
386
|
|
@@ -372,6 +395,14 @@ module OrigenSim
|
|
372
395
|
missed_heartbeats = 0
|
373
396
|
loop do
|
374
397
|
sleep 5
|
398
|
+
|
399
|
+
# If the socket read hangs, count that as a reason to shutdown
|
400
|
+
socket_read = false
|
401
|
+
Thread.new do
|
402
|
+
sleep 1
|
403
|
+
kill_simulation(pid) unless socket_read
|
404
|
+
end
|
405
|
+
|
375
406
|
if heartbeat.ready?
|
376
407
|
while heartbeat.ready? do
|
377
408
|
heartbeat.gets
|
@@ -380,9 +411,9 @@ module OrigenSim
|
|
380
411
|
else
|
381
412
|
missed_heartbeats += 1
|
382
413
|
end
|
414
|
+
socket_read = true
|
383
415
|
if missed_heartbeats > 1
|
384
|
-
|
385
|
-
exit!(1)
|
416
|
+
kill_simulation(pid)
|
386
417
|
end
|
387
418
|
end
|
388
419
|
end
|
@@ -404,14 +435,7 @@ module OrigenSim
|
|
404
435
|
|
405
436
|
ensure
|
406
437
|
# Make sure this process never finishes and leaves the simulator running
|
407
|
-
|
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
|
414
|
-
end
|
438
|
+
kill_simulation(pid) if pid
|
415
439
|
end
|
416
440
|
)
|
417
441
|
|
@@ -419,34 +443,19 @@ module OrigenSim
|
|
419
443
|
Process.detach(simulator_parent_process)
|
420
444
|
|
421
445
|
timeout_connection(config[:startup_timeout] || 60) do
|
422
|
-
|
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
|
446
|
+
simulation.open # This will block until the simulation process responds
|
432
447
|
|
433
|
-
@
|
434
|
-
@stderr = server_stderr.accept
|
435
|
-
@socket = server.accept
|
436
|
-
@connection_established = true
|
448
|
+
@connection_established = true # Cancels timeout_connection
|
437
449
|
if @connection_timed_out
|
438
|
-
|
439
|
-
|
440
|
-
@failed = true
|
441
|
-
exit
|
450
|
+
simulation.failed_to_start = true
|
451
|
+
exit # Assume it is not worth trying another pattern in this case, some kind of environment/config issue
|
442
452
|
end
|
443
453
|
end
|
444
454
|
data = get
|
445
455
|
unless data.strip == 'READY!'
|
446
|
-
|
447
|
-
|
456
|
+
simulation.failed_to_start = true
|
457
|
+
exit # Assume it is not worth trying another pattern in this case, some kind of environment/config issue
|
448
458
|
end
|
449
|
-
@enabled = true
|
450
459
|
# Tick the simulation on, this seems to be required since any VPI puts operations before
|
451
460
|
# the simulation has started are not applied.
|
452
461
|
# Note that this is not setting a tester timeset, so the application will still have to
|
@@ -456,64 +465,64 @@ module OrigenSim
|
|
456
465
|
Origen.listeners_for(:simulation_startup).each(&:simulation_startup)
|
457
466
|
end
|
458
467
|
|
459
|
-
# Returns true if the simulator process is running
|
460
|
-
def running?
|
461
|
-
return false unless pid
|
462
|
-
begin
|
463
|
-
Process.getpgid(pid)
|
464
|
-
true
|
465
|
-
rescue Errno::ESRCH
|
466
|
-
false
|
467
|
-
end
|
468
|
-
end
|
469
|
-
|
470
468
|
# Send the given message string to the simulator
|
471
469
|
def put(msg)
|
472
|
-
socket.write(msg + "\n")
|
470
|
+
simulation.socket.write(msg + "\n")
|
473
471
|
end
|
474
472
|
|
475
473
|
# Get a message from the simulator, will block until one
|
476
474
|
# is received
|
477
475
|
def get
|
478
|
-
socket.readline
|
476
|
+
simulation.socket.readline
|
479
477
|
end
|
480
478
|
|
481
|
-
#
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
479
|
+
# At the start of a test program flow generation/simulation
|
480
|
+
def on_flow_start(options)
|
481
|
+
if simulation_tester? && options[:top_level]
|
482
|
+
OrigenSim.flow = Origen.interface.flow.name
|
483
|
+
start
|
484
|
+
@pattern_count = 0
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
# At the end of a test program flow generation/simulation
|
489
|
+
def on_flow_end(options)
|
490
|
+
if simulation_tester? && options[:top_level]
|
491
|
+
stop
|
492
|
+
end
|
487
493
|
end
|
488
494
|
|
489
495
|
# Called before every pattern is generated, but we only use it the
|
490
496
|
# first time it is called to kick off the simulator process if the
|
491
497
|
# current tester is an OrigenSim::Tester
|
492
498
|
def before_pattern(name)
|
493
|
-
@simulation_completed_cleanly = false
|
494
499
|
if simulation_tester?
|
495
|
-
|
496
|
-
# When running
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
500
|
+
if OrigenSim.flow || !simulation
|
501
|
+
# When running patterns back-to-back, only want to launch the simulator the first time
|
502
|
+
start unless simulation
|
503
|
+
else
|
504
|
+
stop
|
505
|
+
start
|
501
506
|
end
|
502
507
|
# Set the current pattern name in the simulation
|
503
508
|
put("a^#{name.sub(/\..*/, '')}")
|
504
509
|
@pattern_count ||= 0
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
else
|
510
|
-
Origen.log.success 'There are no simulation errors yet!'
|
511
|
-
end
|
510
|
+
# If running a flow, give the user some feedback about pass/fail status after
|
511
|
+
# each individual pattern has completed
|
512
|
+
if @pattern_count > 0 && OrigenSim.flow
|
513
|
+
simulation.log_results(true)
|
512
514
|
end
|
513
515
|
@pattern_count += 1
|
514
516
|
end
|
515
517
|
end
|
516
518
|
|
519
|
+
# This will be called at the end of every pattern, make
|
520
|
+
# sure the simulator is not running behind before potentially
|
521
|
+
# moving onto another pattern
|
522
|
+
def pattern_generated(path)
|
523
|
+
sync_up if simulation_tester?
|
524
|
+
end
|
525
|
+
|
517
526
|
def write_comment(comment)
|
518
527
|
# Not sure what the limiting factor here is, the comment memory in the test bench should
|
519
528
|
# be able to handle 1024 / 8 length strings, but any bigger than this hangs the simulation
|
@@ -590,7 +599,7 @@ module OrigenSim
|
|
590
599
|
|
591
600
|
def cycle(number_of_cycles)
|
592
601
|
put("3^#{number_of_cycles}")
|
593
|
-
read_sim_output
|
602
|
+
simulation.read_sim_output
|
594
603
|
end
|
595
604
|
|
596
605
|
# Blocks the Origen process until the simulator indicates that it has
|
@@ -601,37 +610,12 @@ module OrigenSim
|
|
601
610
|
unless data.strip == 'OK!'
|
602
611
|
fail 'Origen and the simulator are out of sync!'
|
603
612
|
end
|
604
|
-
read_sim_output
|
613
|
+
simulation.read_sim_output
|
605
614
|
end
|
606
615
|
|
607
|
-
def
|
608
|
-
|
609
|
-
|
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
|
616
|
+
def error(message)
|
617
|
+
simulation.logged_errors = true
|
618
|
+
Origen.log.error message
|
635
619
|
end
|
636
620
|
|
637
621
|
# Returns the current simulation error count
|
@@ -732,62 +716,71 @@ module OrigenSim
|
|
732
716
|
|
733
717
|
# Stop the simulator
|
734
718
|
def stop
|
719
|
+
@simulation_open = false
|
720
|
+
simulation.read_sim_output
|
721
|
+
simulation.error_count = error_count
|
735
722
|
Origen.listeners_for(:simulation_shutdown).each(&:simulation_shutdown)
|
736
723
|
ended = Time.now
|
737
724
|
end_simulation
|
738
725
|
# Give the simulator time to shut down
|
739
|
-
sleep 0.1 while running?
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
heartbeat.close if heartbeat
|
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))
|
726
|
+
sleep 0.1 while simulation.running?
|
727
|
+
simulation.close
|
728
|
+
simulation.completed_cleanly = true
|
729
|
+
simulation.log_results unless Origen.current_command == 'interactive'
|
748
730
|
end
|
749
731
|
|
750
732
|
def on_origen_shutdown
|
751
|
-
|
733
|
+
unless simulations.empty?
|
734
|
+
failed = false
|
735
|
+
# Stop the current simulation, this is done with the rescue wrapper so that the rest
|
736
|
+
# of the shutdown continues if we got in here via a CTRL-C, in which case the simulator
|
737
|
+
# is probably already dead
|
738
|
+
begin
|
739
|
+
stop if simulation_open?
|
740
|
+
rescue
|
741
|
+
simulation.completed_cleanly = false
|
742
|
+
end
|
752
743
|
unless @interactive_mode
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
Origen.log.error "
|
759
|
-
|
760
|
-
Origen.log.error 'The simulation stderr reported errors!' if @stderr_logged_errors
|
761
|
-
elsif !@simulation_completed_cleanly
|
762
|
-
@failed = true
|
763
|
-
Origen.log.error 'The simulation exited early!'
|
744
|
+
if simulations.size == 1
|
745
|
+
failed = simulation.failed?
|
746
|
+
else
|
747
|
+
failed_simulation_count = simulations.count(&:failed?)
|
748
|
+
if failed_simulation_count > 0
|
749
|
+
Origen.log.error "#{failed_simulation_count} of #{simulations.size} simulations failed!"
|
750
|
+
failed = true
|
764
751
|
end
|
765
752
|
end
|
766
|
-
end
|
767
|
-
stop
|
768
|
-
unless @interactive_mode
|
769
753
|
if failed
|
770
754
|
Origen.app.stats.report_fail
|
771
755
|
else
|
772
756
|
Origen.app.stats.report_pass
|
773
757
|
end
|
774
758
|
end
|
775
|
-
|
776
|
-
|
759
|
+
puts
|
760
|
+
if simulations.size == 1
|
777
761
|
puts 'To view the simulation run the following command:'
|
778
762
|
puts
|
779
|
-
puts " #{view_wave_command}"
|
763
|
+
puts " #{simulation.view_wave_command}"
|
764
|
+
else
|
765
|
+
puts 'To view the simulations run the following commands:'
|
780
766
|
puts
|
767
|
+
simulations.each do |simulation|
|
768
|
+
if simulation.failed?
|
769
|
+
puts " #{simulation.view_wave_command}".red
|
770
|
+
else
|
771
|
+
puts " #{simulation.view_wave_command}"
|
772
|
+
end
|
773
|
+
end
|
774
|
+
end
|
775
|
+
puts
|
776
|
+
unless @interactive_mode
|
777
|
+
failed ? exit(1) : exit(0)
|
781
778
|
end
|
782
779
|
end
|
783
780
|
end
|
784
781
|
|
785
|
-
def socket_id
|
786
|
-
|
787
|
-
end
|
788
|
-
|
789
|
-
def socket_number
|
790
|
-
@socket_number ||= (Process.pid.to_s + Time.now.to_f.to_s).sub('.', '')
|
782
|
+
def socket_id
|
783
|
+
simulation.socket_id
|
791
784
|
end
|
792
785
|
|
793
786
|
def simulation_tester?
|
@@ -796,6 +789,7 @@ module OrigenSim
|
|
796
789
|
|
797
790
|
def timeout_connection(wait_in_s)
|
798
791
|
@connection_timed_out = false
|
792
|
+
@connection_established = false
|
799
793
|
t = Thread.new do
|
800
794
|
sleep wait_in_s
|
801
795
|
# If the Verilog process has not established a connection yet, then make one to
|
data/lib/origen_sim.rb
CHANGED
@@ -4,6 +4,7 @@ require 'origen_testers'
|
|
4
4
|
require 'origen_sim/origen_testers/api'
|
5
5
|
require 'origen_sim/origen/pins/pin'
|
6
6
|
require 'origen_sim/origen/top_level'
|
7
|
+
require 'origen_sim/origen/application/runner'
|
7
8
|
module OrigenSim
|
8
9
|
# THIS FILE SHOULD ONLY BE USED TO LOAD RUNTIME DEPENDENCIES
|
9
10
|
# If this plugin has any development dependencies (e.g. dummy DUT or other models that are only used
|
@@ -46,7 +47,15 @@ module OrigenSim
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def self.verbose?
|
49
|
-
!!(@verbose || Origen.debugger_enabled?)
|
50
|
+
!!(@verbose || Origen.debugger_enabled? || Origen.running_remotely?)
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.flow=(val)
|
54
|
+
@flow = val
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.flow
|
58
|
+
@flow
|
50
59
|
end
|
51
60
|
|
52
61
|
def self.error_strings
|
@@ -100,5 +109,9 @@ module OrigenSim
|
|
100
109
|
def self.fail_on_stderr
|
101
110
|
defined?(@fail_on_stderr) ? @fail_on_stderr : true
|
102
111
|
end
|
112
|
+
|
113
|
+
def self.error(message)
|
114
|
+
simulator.error(message)
|
115
|
+
end
|
103
116
|
end
|
104
117
|
OrigenSim.__instantiate_simulator__
|
data/pattern/test.rb
CHANGED
@@ -45,12 +45,12 @@ Pattern.create do
|
|
45
45
|
|
46
46
|
if tester.sim?
|
47
47
|
sim = tester.simulator
|
48
|
-
capture_value = sim.peek("origen.pins.tdo.memory").to_i
|
48
|
+
capture_value = sim.peek("origen.pins.tdo.memory").to_i[31..0]
|
49
49
|
unless capture_value == 0x11662244 # 0x2244_6688 reversed
|
50
50
|
if capture_value
|
51
|
-
|
51
|
+
OrigenSim.error "Captured #{capture_value.to_hex} instead of 0x11662244!"
|
52
52
|
else
|
53
|
-
|
53
|
+
OrigenSim.error "Nothing captured instead of 0x11662244!"
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
@@ -58,7 +58,7 @@ Pattern.create do
|
|
58
58
|
dut.cmd.write(0) # Make Origen forget the actual value
|
59
59
|
dut.cmd.sync
|
60
60
|
unless dut.cmd.data == 0x2244_6688
|
61
|
-
|
61
|
+
OrigenSim.error "CMD register did not sync from simulation"
|
62
62
|
end
|
63
63
|
|
64
64
|
ss "Test sync of a register via a parallel interface"
|
@@ -68,7 +68,7 @@ Pattern.create do
|
|
68
68
|
dut.pins(:dout).dont_care
|
69
69
|
dut.parallel_read.sync
|
70
70
|
unless dut.parallel_read.data == 0x7707_7077
|
71
|
-
|
71
|
+
OrigenSim.error "PARALLEL_READ register did not sync from simulation"
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
data/pattern/test2.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pattern/test.rb
|
data/program/p1.rb
CHANGED
data/program/p2.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
program/p1.rb
|
data/templates/probe.tcl.erb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
database -open waves -into <%= options[:dir] %> -default -event
|
1
|
+
database -open waves -into <%= options[:dir] %>/<%= options[:wave_file] %> -default -event
|
2
2
|
probe -create -shm origen -depth <%= options[:depth] %> -database waves
|
3
3
|
#probe -create -assertions -transaction origen -depth all -database waves
|
4
4
|
|
@@ -157,7 +157,7 @@ module origen;
|
|
157
157
|
//$display("********************************");
|
158
158
|
//$display("Creating origen.vcd...");
|
159
159
|
//$display("********************************");
|
160
|
-
|
160
|
+
//$dumpfile("origen.vcd");
|
161
161
|
$dumpvars(0,origen);
|
162
162
|
end
|
163
163
|
`endif
|
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.10.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-06-
|
11
|
+
date: 2018-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: origen
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.
|
47
|
+
version: '0.4'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
54
|
+
version: '0.4'
|
55
55
|
description:
|
56
56
|
email:
|
57
57
|
- stephen.f.mcginty@gmail.com
|
@@ -81,15 +81,20 @@ files:
|
|
81
81
|
- lib/origen_sim/commands/pack.rb
|
82
82
|
- lib/origen_sim/flow.rb
|
83
83
|
- lib/origen_sim/generator.rb
|
84
|
+
- lib/origen_sim/heartbeat.rb
|
85
|
+
- lib/origen_sim/origen/application/runner.rb
|
84
86
|
- lib/origen_sim/origen/pins/pin.rb
|
85
87
|
- lib/origen_sim/origen/top_level.rb
|
86
88
|
- lib/origen_sim/origen_testers/api.rb
|
89
|
+
- lib/origen_sim/simulation.rb
|
87
90
|
- lib/origen_sim/simulator.rb
|
88
91
|
- lib/origen_sim/tester.rb
|
89
92
|
- lib/origen_sim_dev/dut.rb
|
90
93
|
- lib/tasks/origen_sim.rake
|
91
94
|
- pattern/test.rb
|
95
|
+
- pattern/test2.rb
|
92
96
|
- program/p1.rb
|
97
|
+
- program/p2.rb
|
93
98
|
- templates/empty.gtkw
|
94
99
|
- templates/empty.svcf
|
95
100
|
- templates/empty.tcl
|
@@ -118,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
123
|
version: 1.8.11
|
119
124
|
requirements: []
|
120
125
|
rubyforge_project:
|
121
|
-
rubygems_version: 2.6.
|
126
|
+
rubygems_version: 2.6.14.1
|
122
127
|
signing_key:
|
123
128
|
specification_version: 4
|
124
129
|
summary: Plugin that provides a testbench environment to simulate Origen test patterns
|