origen_sim 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d43e76c0e9a55fc9cdbcc5ba241ab8e76386aff85d711aef54e7c68293c5f8f
4
- data.tar.gz: 8f6582388d383142beebaf1c313936b78b6f495f0b2403193df02f8ae51f25f0
3
+ metadata.gz: a37dd737642a62e60b4cc98f47928b659004f3b89e771aa9efabfd2610622080
4
+ data.tar.gz: 74309fc46e200d299e8704e4599fdd3553abd1cb380ec56a9c7d926f1a7728f7
5
5
  SHA512:
6
- metadata.gz: dfa8d2b63ba5af0b216bda43900b24db81735a11a49f604053b34771c55d42a99d3e6a0f190f6f24815542bee91d1f281c423ba5fcadd01ea5d6e4406ba913d6
7
- data.tar.gz: 8a968093af5c18778e2835115f02c46ec3f638b1a5049124c9fe339dbe9007eb4f8a80aac3146a0e377aee0bcb920f147c54bf092b2721ccefd587614fee0fb6
6
+ metadata.gz: e94281aa75824657de8e4df717201db48d8b8fc02669b84b78e34f271533a119e88b6881a28d41ce6ecb5e2d12192d78d042764d6efabb2548e8c3fec7069080
7
+ data.tar.gz: 0404e46a47d0d02d5933ed238fc84b6660f3cbae5f70d7c632c4ca2cb87c8ada52b8a2b382becf4e59b2c276a423890b569de6a227b6d31f329eee26ca66711f
@@ -52,7 +52,8 @@ class OrigenSimApplication < Origen::Application
52
52
  dir: "example_rtl",
53
53
  rc_url: 'https://github.com/Origen-SDK/example_rtl.git',
54
54
  version: "master",
55
- development: true
55
+ development: true,
56
+ #path: "/home/stephen/Code/github/example_rtl"
56
57
  }
57
58
  ]
58
59
 
@@ -36,6 +36,10 @@ when "sim:unpack"
36
36
  OrigenSim::Commands::Pack.unpack
37
37
  exit 0
38
38
 
39
+ when "sim:run"
40
+ OrigenSim.run_source(ARGV[0])
41
+ exit 0
42
+
39
43
  #when "sim:list"
40
44
  # require "#{Origen.root!}/lib/origen_sim/commands/pack"
41
45
  # OrigenSim::Commands::Pack.list
data/config/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module OrigenSim
2
2
  MAJOR = 0
3
- MINOR = 14
3
+ MINOR = 15
4
4
  BUGFIX = 0
5
5
  DEV = nil
6
6
 
@@ -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', defines: [] }
6
+ options = { incl_files: [], source_dirs: [], testbench_name: 'origen', defines: [], user_details: {}, initial_pin_states: {}, verilog_top_output_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 || []
@@ -22,9 +22,43 @@ 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('--sv', 'Generate a .sv file instead of a .v file.') { |t| options[:sv] = t }
26
+ opts.on('--verilog_top_output_name NAME', 'Renames the output filename from origen.v to NAME.v') do |name|
27
+ options[:verilog_top_output_name] = name
28
+ end
25
29
  opts.on('--define MACRO', 'Specify a compiler define') do |macro|
26
30
  options[:defines] << macro
27
31
  end
32
+ opts.on('--init_pin_state PIN_AND_STATE', 'Specify how the pins should be initialized.') do |pin_and_state|
33
+ name, state = pin_and_state.split(':')
34
+
35
+ # Make sure that we recognize the pin state option before building.
36
+ unless OrigenSim::INIT_PIN_STATE_MAPPING.include?(state)
37
+ fail "Provide state '#{state}' to --init_pin_state pin_and_state not recognized!"
38
+ end
39
+ (options[:initial_pin_states])[name.to_sym] = OrigenSim::INIT_PIN_STATE_MAPPING[state]
40
+ end
41
+ opts.on('--include FILE' 'Specify files to include in the top verilog file.') { |f| options[:incl_files] << f }
42
+
43
+ # Specifying snapshot details
44
+ opts.on('--device_name NAME', '(Snapshot Detail) Specify a device name') { |n| options[:device_name] = n }
45
+ opts.on('--testbench_version VER', '(Snapshot Detail) Specify a version of the testbench this snapshot was built from') { |v| options[:testbench_version] = v }
46
+ opts.on('--revision REV', '(Snapshot Detail) Specify a revision of the snapshot') { |r| options[:revision] = r }
47
+ opts.on('--revision_note REV_NOTE', '(Snapshot Detail) Specify a brief note on this revision of the snapshot') { |n| options[:revision_note] = n }
48
+ opts.on('--author AUTHOR', '(Snapshot Detail) Specify the author of the snapshot (default is just Origen.current_user)') { |a| options[:author] = a }
49
+
50
+ # User-defined snapshot details
51
+ opts.on('--USER_DETAIL NAME_AND_VALUE', 'Specify custom user-defined details to build into the snapshot details. Format as NAME:VALUE, e.g.: \'--USER_DETAIL BUILD_TYPE:RTL\'') do |name_and_value|
52
+ name, value = name_and_value.split(':')
53
+
54
+ unless name.upcase == name
55
+ Origen.log.warning "Non-capitalized user detail '#{name}' was given!"
56
+ Origen.log.warning 'OrigenSim forces the Verilog practice that parameters should be capitalized.'
57
+ Origen.log.warning "The parameter '#{name.upcase}' will be used instead"
58
+ name.upcase!
59
+ end
60
+ (options[:user_details])[name] = value
61
+ end
28
62
  opts.on('-d', '--debugger', 'Enable the debugger') { options[:debugger] = true }
29
63
  app_options.each do |app_option|
30
64
  opts.on(*app_option) {}
@@ -82,19 +116,37 @@ rtl_top_module = mod.name
82
116
 
83
117
  mod.to_top_level # Creates dut
84
118
 
119
+ # Update the pins with any setings from the command line
120
+ options[:initial_pin_states].each do |pin, state|
121
+ dut.pins(pin).meta[:origen_sim_init_pin_state] = state
122
+ end
123
+
85
124
  if $_testing_build_return_dut_
86
125
  dut
87
126
 
88
127
  else
89
128
 
90
129
  output_directory = options[:output] || Origen.config.output_directory
130
+ output_name = options[:sv] ? "#{options[:verilog_top_output_name]}.sv" : "#{options[:verilog_top_output_name]}.v"
91
131
 
92
132
  Origen.app.runner.launch action: :compile,
93
133
  files: "#{Origen.root!}/templates/rtl_v/origen.v.erb",
134
+ output_file_name: output_name,
94
135
  output: output_directory,
95
136
  check_for_changes: false,
96
137
  quiet: true,
97
- options: { vendor: :cadence, top: dut.name, incl: options[:incl_files] }
138
+ preserve_target: true,
139
+ options: {
140
+ vendor: :cadence,
141
+ top: dut.name,
142
+ incl: options[:incl_files],
143
+ device_name: options[:device_name],
144
+ revision: options[:revision],
145
+ revision_note: options[:revision_note],
146
+ parent_tb_version: options[:testbench_version],
147
+ user_details: options[:user_details],
148
+ author: options[:author]
149
+ }
98
150
 
99
151
  Origen.app.runner.launch action: :compile,
100
152
  files: "#{Origen.root!}/ext",
@@ -113,7 +165,7 @@ else
113
165
  puts
114
166
  puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
115
167
  puts
116
- puts " #{output_directory}/origen.v \\"
168
+ puts " #{output_directory}/#{output_name} \\"
117
169
  puts " #{output_directory}/*.c \\"
118
170
  puts ' -ccargs "-std=c99" \\'
119
171
  puts ' -top origen \\'
@@ -124,7 +176,7 @@ else
124
176
  puts
125
177
  puts 'Here is an example which may work for the file you just parsed (add additional -incdir options at the end if required):'
126
178
  puts
127
- 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}"
179
+ puts " #{ENV['ORIGEN_SIM_IRUN'] || 'irun'} #{rtl_top} #{output_directory}/#{output_name} #{output_directory}/*.c -ccargs \"-std=c99\" -top origen -elaborate -snapshot origen -access +rw -timescale 1ns/1ns -incdir #{Pathname.new(rtl_top).dirname}"
128
180
  puts
129
181
  puts 'Copy the following directory (produced by irun) to simulation/<target>/cadence/. within your Origen application:'
130
182
  puts
@@ -136,7 +188,7 @@ else
136
188
  puts
137
189
  puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
138
190
  puts
139
- puts " #{output_directory}/origen.v \\"
191
+ puts " #{output_directory}/#{output_name} \\"
140
192
  puts " #{output_directory}/bridge.c \\"
141
193
  puts " #{output_directory}/client.c \\"
142
194
  puts ' -CFLAGS "-std=c99" \\'
@@ -149,7 +201,7 @@ else
149
201
  puts
150
202
  puts 'Here is an example which may work for the file you just parsed (add additional -incdir options at the end if required):'
151
203
  puts
152
- puts " #{ENV['ORIGEN_SIM_VCS'] || 'vcs'} #{rtl_top} #{output_directory}/origen.v #{output_directory}/bridge.c #{output_directory}/client.c -CFLAGS \"-std=c99\" +vpi #{output_directory}/origen.c -timescale=1ns/1ns +define+ORIGEN_VPD=1 +incdir+#{Pathname.new(rtl_top).dirname} -debug_access+all -PP"
204
+ puts " #{ENV['ORIGEN_SIM_VCS'] || 'vcs'} #{rtl_top} #{output_directory}/#{output_name} #{output_directory}/bridge.c #{output_directory}/client.c -CFLAGS \"-std=c99\" +vpi #{output_directory}/origen.c -timescale=1ns/1ns +define+ORIGEN_VPD=1 +incdir+#{Pathname.new(rtl_top).dirname} -debug_access+all -PP"
153
205
  puts
154
206
  puts 'Copy the following files (produced by vcs) to simulation/<target>/synopsys/. within your Origen application:'
155
207
  puts
@@ -166,13 +218,13 @@ else
166
218
  puts
167
219
  puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
168
220
  puts
169
- puts " #{output_directory}/origen.v \\"
221
+ puts " #{output_directory}/#{output_name} \\"
170
222
  puts ' -o origen.vvp \\'
171
223
  puts ' -DORIGEN_VCD'
172
224
  puts
173
225
  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):'
174
226
  puts
175
- puts " #{ENV['ORIGEN_SIM_IVERILOG'] || 'iverilog'} #{rtl_top} #{output_directory}/origen.v -o origen.vvp -DORIGEN_VCD -I #{Pathname.new(rtl_top).dirname}"
227
+ puts " #{ENV['ORIGEN_SIM_IVERILOG'] || 'iverilog'} #{rtl_top} #{output_directory}/#{output_name} -o origen.vvp -DORIGEN_VCD -I #{Pathname.new(rtl_top).dirname}"
176
228
  puts
177
229
  puts 'Copy the following files (produced by iverilog) to simulation/<target>/icarus/. within your Origen application:'
178
230
  puts
@@ -185,8 +237,8 @@ else
185
237
  puts
186
238
  puts 'Add the following to your build script (AND REMOVE ANY OTHER TESTBENCH!):'
187
239
  puts
188
- puts " #{output_directory}/origen.v \\"
189
- puts " #{output_directory}/bridge.c \\"
240
+ puts " #{output_directory}/#{output_name} \\"
241
+ puts " #{output_directory}/brdige.c \\"
190
242
  puts " #{output_directory}/client.c \\"
191
243
  puts ' -CFLAGS "-std=c99" \\'
192
244
  puts ' +vpi \\'
@@ -202,7 +254,7 @@ else
202
254
  puts
203
255
  puts 'Here is an example which may work for the file you just parsed (add additional -incdir options at the end if required):'
204
256
  puts
205
- puts " #{ENV['ORIGEN_SIM_VCS'] || 'vcs'} #{rtl_top} #{output_directory}/origen.v #{output_directory}/bridge.c #{output_directory}/client.c -CFLAGS \"-std=c99\" +vpi #{output_directory}/origen.c +define+ORIGEN_FSDB=1 +incdir+#{Pathname.new(rtl_top).dirname} -debug_access+all +lint=all,noVCDE,noIWU,noVNGS,noCAWM-L,noPORTFRC,noZERO,noNS -PP -timescale=1ns/100ps -full64 -lca -kdb"
257
+ puts " #{ENV['ORIGEN_SIM_VCS'] || 'vcs'} #{rtl_top} #{output_directory}/#{output_name} #{output_directory}/bridge.c #{output_directory}/client.c -CFLAGS \"-std=c99\" +vpi #{output_directory}/origen.c +define+ORIGEN_FSDB=1 +incdir+#{Pathname.new(rtl_top).dirname} -debug_access+all +lint=all,noVCDE,noIWU,noVNGS,noCAWM-L,noPORTFRC,noZERO,noNS -PP -timescale=1ns/100ps -full64 -lca -kdb"
206
258
  puts
207
259
  puts 'Copy the following files (produced by vcs) to simulation/<target>/verdi/. within your Origen application:'
208
260
  puts
@@ -1,7 +1,7 @@
1
1
  require 'thread'
2
2
  module OrigenSim
3
3
  class Heartbeat < Thread
4
- attr_reader :socket
4
+ attr_reader :socket, :simulation
5
5
 
6
6
  # Can't use this with threads currently because Byebug pauses the sleep,
7
7
  # during a breakpoint, which means that the simulator is killed.
@@ -9,7 +9,8 @@ module OrigenSim
9
9
  # whenever this is set to false.
10
10
  THREADSAFE = false
11
11
 
12
- def initialize(socket)
12
+ def initialize(simulation, socket)
13
+ @simulation = simulation
13
14
  @socket = socket
14
15
  @continue = true
15
16
  super do
@@ -17,8 +18,12 @@ module OrigenSim
17
18
  begin
18
19
  socket.write("OK\n")
19
20
  rescue Errno::EPIPE => e
20
- Origen.log.error 'Communication with the simulation monitor has been lost!'
21
- sleep 2
21
+ exit 0 if simulation.ended
22
+ if simulation.monitor_running?
23
+ Origen.log.error 'Communication with the simulation monitor has been lost (though it seems to still be running)!'
24
+ else
25
+ Origen.log.error 'The simulation monitor has stopped unexpectedly!'
26
+ end
22
27
  exit 1
23
28
  end
24
29
  sleep 5
@@ -18,6 +18,10 @@ module OrigenSim
18
18
  # Returns the communication socket used for sending commands to the Origen VPI running
19
19
  # in the simulation process
20
20
  attr_reader :socket
21
+ # Returns false when the simulation is running and will be set to true once all instructions
22
+ # have been sent and executed by the simulator and immediately before the end_simulation
23
+ # instruction is sent to the simulator.
24
+ attr_accessor :ended
21
25
 
22
26
  def initialize(id, view_wave_command)
23
27
  @id = id
@@ -25,6 +29,7 @@ module OrigenSim
25
29
  @completed_cleanly = false
26
30
  @failed_to_start = false
27
31
  @logged_errors = false
32
+ @ended = false
28
33
  @error_count = 0
29
34
  @socket_ids = {}
30
35
 
@@ -85,6 +90,24 @@ module OrigenSim
85
90
  end
86
91
  end
87
92
 
93
+ def ended=(val)
94
+ # If running the heartbeat from a fork we need to communicate to it that the simulation has
95
+ # ended by writing to a file
96
+ if val == true && !Heartbeat::THREADSAFE
97
+ FileUtils.touch(ended_file)
98
+ else
99
+ @ended = val
100
+ end
101
+ end
102
+
103
+ def ended_file
104
+ @ended_file ||= begin
105
+ dir = Origen.root.join('tmp', 'origen_sim', 'ended')
106
+ FileUtils.mkdir_p(dir.to_s)
107
+ dir.join(socket_number).to_s
108
+ end
109
+ end
110
+
88
111
  # Provide a heartbeat to let the parallel Ruby process in charge of the simulator
89
112
  # know that the master Origen process is still alive. If the Origen process crashes and leaves
90
113
  # the simulator running, the child process will automatically reap it after a couple of missed
@@ -92,20 +115,25 @@ module OrigenSim
92
115
  def start_heartbeat
93
116
  @heartbeat = @server_heartbeat.accept
94
117
  if Heartbeat::THREADSAFE
95
- @heartbeat_thread = Heartbeat.new(@heartbeat)
118
+ @heartbeat_thread = Heartbeat.new(self, @heartbeat)
96
119
  else
120
+ ended_file # Cache this file name before forking
97
121
  @heartbeat_pid = fork do
98
122
  loop do
99
123
  begin
100
124
  @heartbeat.write("OK\n")
101
125
  rescue Errno::EPIPE => e
102
- if monitor_running?
103
- Origen.log.error 'Communication with the simulation monitor has been lost (though it seems to still be running)!'
126
+ if File.exist?(ended_file)
127
+ FileUtils.rm_f(ended_file)
128
+ exit 0
104
129
  else
105
- Origen.log.error 'The simulation monitor has stopped unexpectedly!'
130
+ if monitor_running?
131
+ Origen.log.error 'Communication with the simulation monitor has been lost (though it seems to still be running)!'
132
+ else
133
+ Origen.log.error 'The simulation monitor has stopped unexpectedly!'
134
+ end
135
+ exit 1
106
136
  end
107
- sleep 2 # To make sure that any log output from the simulator is captured before we pull the plug
108
- exit 1
109
137
  end
110
138
  sleep 5
111
139
  end
@@ -125,6 +153,7 @@ module OrigenSim
125
153
  rescue Errno::ECHILD
126
154
  # Heartbeat process has already stopped, so ignore this.
127
155
  end
156
+ FileUtils.rm_f(ended_file) if File.exist?(ended_file)
128
157
  end
129
158
  end
130
159
 
@@ -74,6 +74,10 @@ module OrigenSim
74
74
  alias_method :pop_method, :populate_method
75
75
 
76
76
  def populate
77
+ unless Dir.exist?(run_target.dirname)
78
+ FileUtils.mkdir_p(run_target.dirname)
79
+ end
80
+
77
81
  if populate_method == :symlink
78
82
  File.symlink(target, run_target)
79
83
  elsif populate_method == :copy
@@ -0,0 +1,59 @@
1
+ require 'origen_sim/simulator/user_details'
2
+
3
+ module OrigenSim
4
+ class Simulator
5
+ # The SnapshotDetails and UserDetails share a lot in common, with the
6
+ # SnapshotDetails containing a bit of extra stuff.
7
+ class SnapshotDetails < UserDetails
8
+ attr_reader :_user_details
9
+
10
+ def initialize(simulator:, cache: true)
11
+ # @fetch_error_message = "OrigenSim was unable to find net #{detail_names_net} in the snapshot! Unable to retrieve snapshot details!"
12
+ super(simulator: simulator, cache: cache)
13
+
14
+ @_user_details = UserDetails.new(simulator: simulator, cache: cache)
15
+ end
16
+
17
+ def detail_to_net(d)
18
+ "#{@simulator.testbench_top}.debug.snapshot_details.#{d}"
19
+ end
20
+
21
+ def _missing_detail_message(d)
22
+ "Detail '#{d}' is not an available snapshot detail name!"
23
+ end
24
+
25
+ ### The user details interface is the same as the snapshot_details ###
26
+ ### just on the snapshot_details itself ###
27
+
28
+ def user_details(d = nil)
29
+ if d
30
+ _user_details[d]
31
+ else
32
+ _user_details
33
+ end
34
+ end
35
+
36
+ def user_detail(d)
37
+ user_details(d)
38
+ end
39
+ end
40
+
41
+ ### Add the following methods to the simulator ###
42
+
43
+ def _snapshot_details
44
+ @_snapshot_details ||= SnapshotDetails.new(simulator: self, **@configuration[:snapshot_details_options])
45
+ end
46
+
47
+ def snapshot_details(d = nil)
48
+ if d
49
+ _snapshot_details[d]
50
+ else
51
+ _snapshot_details
52
+ end
53
+ end
54
+
55
+ def snapshot_detail(d)
56
+ snapshot_details(d)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,107 @@
1
+ module OrigenSim
2
+ class Simulator
3
+ class UserDetails
4
+ DETAIL_NAMES_NET = '_AVAILABLE_DETAILS_'
5
+
6
+ attr_reader :cache
7
+ attr_reader :details
8
+
9
+ def initialize(simulator:, cache: true)
10
+ @simulator = simulator
11
+ @fetch_error_message = "OrigenSim was unable to find net #{detail_names_net} in the snapshot! Unable to retrieve snapshot details!"
12
+ @details = fetch
13
+ @cache = cache
14
+ end
15
+
16
+ # This gets called for some reason when 'puts' is used for the object.
17
+ # Provide something here to avoid seeing the error message.
18
+ def to_ary
19
+ nil
20
+ end
21
+
22
+ def method_missing(method, *args, &block)
23
+ self[method]
24
+ end
25
+
26
+ def [](d)
27
+ _d = d.to_s.upcase
28
+ if cache
29
+ if details
30
+ if details.key?(_d)
31
+ details[_d]
32
+ else
33
+ Origen.log.error(_missing_detail_message(_d))
34
+ nil
35
+ end
36
+ else
37
+ # if detail fetching failed, but the user is still trying to query
38
+ # details, re-print the fetch error message
39
+ Origen.log.error(@fetch_error_message)
40
+ nil
41
+ end
42
+ else
43
+ details = fetch
44
+ if details
45
+ if details.key?(_d)
46
+ details[_d]
47
+ else
48
+ Origen.log.error(_missing_detail_message(_d))
49
+ nil
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def _missing_detail_message(d)
56
+ "Detail '#{d}' was not provided in this snapshot!"
57
+ end
58
+
59
+ # Fetches the details available in the snapshot.
60
+ # This is done at runtime to get the latest details list from the snapshot
61
+ # but can be cached for future use.
62
+ # @note This requires the details <code>origen.debug.AVAILABLE_DETAILS</code>
63
+ # to be defined. This should be a comma-separeted string of the available values.
64
+ # It will be assumed that each details will be defined in the snapshot.
65
+ def fetch
66
+ puts 'FETCHING!'.cyan
67
+ # Read the available details.
68
+ # names = str_peek("#{debug_module}.PARAMETER_NAMES").split(',')
69
+ names = @simulator.peek_str(detail_names_net)
70
+ if names.nil?
71
+ Origen.log.error(@fetch_error_message)
72
+
73
+ # Returning false indicates that the fetch failed.
74
+ false
75
+ elsif names.empty?
76
+ # Empty string was returned. No available details/no details given.
77
+ {}
78
+ else
79
+ # Fetch each detail value and return as a Hash
80
+ names.split(',').map do |n|
81
+ [n, @simulator.str_peek(detail_to_net(n))]
82
+ end.to_h
83
+ end
84
+ end
85
+
86
+ def available_details
87
+ if details
88
+ details.keys
89
+ else
90
+ details = fetch
91
+ @details = details if cache
92
+ if details
93
+ details.keys
94
+ end
95
+ end
96
+ end
97
+
98
+ def detail_to_net(d)
99
+ "#{@simulator.testbench_top}.debug.snapshot_details.user_details.#{d}"
100
+ end
101
+
102
+ def detail_names_net
103
+ detail_to_net(DETAIL_NAMES_NET)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -1,5 +1,6 @@
1
1
  require 'origen_sim/simulation'
2
- require 'origen_sim/artifacts'
2
+ require 'origen_sim/simulator/artifacts'
3
+ require 'origen_sim/simulator/snapshot_details'
3
4
 
4
5
  module OrigenSim
5
6
  # Responsible for managing and communicating with the simulator
@@ -117,7 +118,9 @@ module OrigenSim
117
118
  unless VENDORS.include?(options[:vendor])
118
119
  fail "Unknown vendor #{options[:vendor]}, valid values are: #{VENDORS.map { |v| ':' + v.to_s }.join(', ')}"
119
120
  end
120
- @configuration = options
121
+ @configuration = {
122
+ snapshot_details_options: {}
123
+ }.merge(options)
121
124
  @tmp_dir = nil
122
125
 
123
126
  # Temporary workaround for bug in componentable, which is making the container a class object, instead of an
@@ -171,7 +174,7 @@ module OrigenSim
171
174
  end
172
175
 
173
176
  def target_artifact_dir
174
- Pathname(@configuration[:target_artifact_dir] || "#{Origen.app.root}/simulation/#{Origen.target.name}/artifacts")
177
+ Pathname(@configuration[:target_artifact_dir] || "#{Origen.app.root}/simulation/#{id}/artifacts")
175
178
  end
176
179
 
177
180
  def artifact_run_dir
@@ -311,7 +314,7 @@ module OrigenSim
311
314
 
312
315
  when :synopsys
313
316
  if configuration[:verdi]
314
- cmd = "#{compiled_dir}/simv +socket+#{socket_id} +FSDB_ON +fsdbfile+#{Origen.root}/waves/#{Origen.target.name}/#{wave_file_basename}.fsdb +memcbk +vcsd"
317
+ cmd = "#{compiled_dir}/simv +socket+#{socket_id} +FSDB_ON +fsdbfile+#{Origen.root}/waves/#{id}/#{wave_file_basename}.fsdb +memcbk +vcsd"
315
318
  else
316
319
  cmd = "#{compiled_dir}/simv +socket+#{socket_id} -vpd_file #{wave_file_basename}.vpd"
317
320
  end
@@ -364,12 +367,12 @@ module OrigenSim
364
367
  OrigenSim.flow.to_s
365
368
  else
366
369
  if Origen.app.current_job
367
- @last_wafe_file_basename = Pathname.new(Origen.app.current_job.output_file).basename('.*').to_s
370
+ @last_wave_file_basename = Pathname.new(Origen.app.current_job.output_file).basename('.*').to_s
368
371
  else
369
372
  if Origen.interactive?
370
373
  'interactive'
371
374
  else
372
- @last_wafe_file_basename
375
+ @last_wave_file_basename || 'unnamed_pattern'
373
376
  end
374
377
  end
375
378
  end
@@ -407,7 +410,7 @@ module OrigenSim
407
410
  cmd = "cd #{edir} && "
408
411
  cmd += configuration[:verdi] || 'verdi'
409
412
  dir = Pathname.new(wave_dir).relative_path_from(edir.expand_path)
410
- cmd += " -ssz -dbdir #{Origen.root}/simulation/#{Origen.target.name}/synopsys/simv.daidir/ -ssf #{dir}/#{wave_file_basename}.fsdb"
413
+ cmd += " -ssz -dbdir #{Origen.root}/simulation/#{id}/synopsys/simv.daidir/ -ssf #{dir}/#{wave_file_basename}.fsdb"
411
414
  f = Pathname.new(wave_config_file).relative_path_from(edir.expand_path)
412
415
  cmd += " -sswr #{f}"
413
416
  cmd += ' &'
@@ -643,6 +646,7 @@ module OrigenSim
643
646
  @pattern_count += 1
644
647
  end
645
648
  end
649
+ alias_method :setup_simulation, :before_pattern
646
650
 
647
651
  # This will be called at the end of every pattern, make
648
652
  # sure the simulator is not running behind before potentially
@@ -653,6 +657,7 @@ module OrigenSim
653
657
  simulation.completed_cleanly = true unless @flow_running
654
658
  end
655
659
  end
660
+ alias_method :complete_simulation, :pattern_generated
656
661
 
657
662
  def write_comment(line, comment)
658
663
  return if line >= OrigenSim::NUMBER_OF_COMMENT_LINES
@@ -864,6 +869,8 @@ module OrigenSim
864
869
  @simulation_open = false
865
870
  simulation.error_count = error_count
866
871
  Origen.listeners_for(:simulation_shutdown).each(&:simulation_shutdown)
872
+ sync_up
873
+ simulation.ended = true
867
874
  end_simulation
868
875
  # Give the simulator time to shut down
869
876
  sleep 0.1 while simulation.running?
@@ -973,6 +980,23 @@ module OrigenSim
973
980
  peek("#{testbench_top}.pins.match_errors").to_i
974
981
  end
975
982
 
983
+ def peek_str(signal)
984
+ val = tester.simulator.peek(signal)
985
+ unless val.nil?
986
+ puts val
987
+ puts val.class
988
+ # All zeros seems to be what an empty string is returned from the VPI,
989
+ # Otherwise, break the string up into 8-bit chunks and decode the ASCII>
990
+ val = (val.to_s == 'b00000000' ? '' : val.to_s[1..-1].scan(/.{1,8}/).collect { |char| char.to_i(2).chr }.join)
991
+ end
992
+ val
993
+ # puts "Peaking #{signal}: #{a}: #{a.class}"
994
+ # tester.simulator.peek(signal).to_s[1..-1].scan(/.{1,8}/).collect { |char| char.to_i(2).chr }.join
995
+ end
996
+ alias_method :str_peek, :peek_str
997
+ alias_method :peek_string, :peek_str
998
+ alias_method :string_peek, :peek_str
999
+
976
1000
  private
977
1001
 
978
1002
  # Pre 0.8.0 the simulator represented the time in ns instead of ps
@@ -225,6 +225,10 @@ module OrigenSim
225
225
  flush if Origen.running_interactively? && dut_version > '0.12.1'
226
226
  end
227
227
 
228
+ # def method_missing(m, *args, &block)
229
+ # super
230
+ # end
231
+
228
232
  private
229
233
 
230
234
  def flush_comments
data/lib/origen_sim.rb CHANGED
@@ -19,6 +19,44 @@ module OrigenSim
19
19
  autoload :Tester, 'origen_sim/tester'
20
20
  autoload :Generator, 'origen_sim/generator'
21
21
 
22
+ # Include a mapping for various sematics.
23
+ INIT_PIN_STATE_MAPPING = {
24
+ # Drive Low Options
25
+ 'drive_lo' => 0,
26
+ 'drive-lo' => 0,
27
+ 'drive_low' => 0,
28
+ 'drive-low' => 0,
29
+ 'lo' => 0,
30
+ 'low' => 0,
31
+ '0' => 0,
32
+
33
+ # Drive High Options
34
+ 'drive_hi' => 1,
35
+ 'drive-hi' => 1,
36
+ 'drive_high' => 1,
37
+ 'drive-high' => 1,
38
+ 'hi' => 1,
39
+ 'high' => 1,
40
+ '1' => 1,
41
+
42
+ # High Impedance Options
43
+ 'z' => 2,
44
+ 'high_z' => 2,
45
+ 'high-z' => 2,
46
+ 'hi_z' => 2,
47
+ 'hi-z' => 2,
48
+ 'high_impedance' => 2,
49
+ 'high-impedance' => 2,
50
+ '2' => 2,
51
+
52
+ # Disable Options
53
+ '-1' => -1,
54
+ 'disable' => -1,
55
+ 'disabled' => -1,
56
+ 'no_action' => -1,
57
+ 'no-action' => -1
58
+ }
59
+
22
60
  def self.__instantiate_simulator__
23
61
  @simulator ||= Simulator.new
24
62
  end
@@ -145,5 +183,23 @@ module OrigenSim
145
183
  def self.error(message)
146
184
  simulator.error(message)
147
185
  end
186
+
187
+ def self.run(name, options = {}, &block)
188
+ # Load up the application and target
189
+ Origen.load_application
190
+ Origen.app.load_target!
191
+
192
+ # Start up the simulator and run whatever's in the target block.
193
+ # After the block completes, shutdown the simulator
194
+ tester.simulator.setup_simulation(name)
195
+ yield
196
+ tester.simulator.complete_simulation(name)
197
+ end
198
+
199
+ def self.run_source(source, options = {})
200
+ OrigenSim.run(source) do
201
+ OrigenTesters::Decompiler.decompile(source).execute
202
+ end
203
+ end
148
204
  end
149
205
  OrigenSim.__instantiate_simulator__
@@ -72,6 +72,9 @@ module OrigenSimDev
72
72
  reg.bits 6..4, :b5
73
73
  reg.bits 2..0, :b6
74
74
  end
75
+
76
+ sub_block :ip1, class_name: 'IP'
77
+ sub_block :ip2, class_name: 'IP'
75
78
  end
76
79
 
77
80
  def interactive_startup
@@ -98,12 +101,23 @@ module OrigenSimDev
98
101
  end
99
102
 
100
103
  def write_register(reg, options = {})
101
- jtag.write_ir(0x8, size: 4)
102
- dr.rg_enable.write(1)
103
- dr.rg_read.write(0)
104
- dr.rg_addr.write(reg.address)
105
- dr.rg_data.write(reg.data)
106
- jtag.write_dr(dr)
104
+ if reg.path =~ /ip(\d)/
105
+ ir_val = 0b0100 | Regexp.last_match(1).to_i
106
+ jtag.write_ir(ir_val, size: 4)
107
+ ip = reg.parent
108
+ ip.dr.bits(:write).write(1)
109
+ ip.dr.bits(:address).write(reg.address)
110
+ ip.dr.bits(:data).write(reg.data)
111
+ jtag.write_dr(ip.dr)
112
+ # Write to top-level reg
113
+ else
114
+ jtag.write_ir(0x8, size: 4)
115
+ dr.rg_enable.write(1)
116
+ dr.rg_read.write(0)
117
+ dr.rg_addr.write(reg.address)
118
+ dr.rg_data.write(reg.data)
119
+ jtag.write_dr(dr)
120
+ end
107
121
  end
108
122
 
109
123
  def read_register(reg, options = {})
@@ -119,14 +133,26 @@ module OrigenSimDev
119
133
  1.cycle
120
134
  dut.pins(:dout).dont_care
121
135
  else
122
- jtag.write_ir(0x8, size: 4)
123
- dr.rg_enable.write(1)
124
- dr.rg_read.write(1)
125
- dr.rg_addr.write(reg.address)
126
- jtag.write_dr(dr)
127
- dr.rg_enable.write(0)
128
- dr.rg_data.copy_all(reg)
129
- jtag.read_dr(dr)
136
+ if reg.path =~ /ip(\d)/
137
+ ir_val = 0b0100 | Regexp.last_match(1).to_i
138
+ jtag.write_ir(ir_val, size: 4)
139
+ ip = reg.parent
140
+ ip.dr.bits(:write).write(0)
141
+ ip.dr.bits(:address).write(reg.address)
142
+ ip.dr.bits(:data).write(0)
143
+ jtag.write_dr(ip.dr)
144
+ ip.dr.bits(:data).copy_all(reg)
145
+ jtag.read_dr(ip.dr)
146
+ else
147
+ jtag.write_ir(0x8, size: 4)
148
+ dr.rg_enable.write(1)
149
+ dr.rg_read.write(1)
150
+ dr.rg_addr.write(reg.address)
151
+ jtag.write_dr(dr)
152
+ dr.rg_enable.write(0)
153
+ dr.rg_data.copy_all(reg)
154
+ jtag.read_dr(dr)
155
+ end
130
156
  end
131
157
  end
132
158
  end
@@ -0,0 +1,53 @@
1
+ module OrigenSimDev
2
+ class IP
3
+ include Origen::Model
4
+
5
+ def initialize
6
+ # Virtual reg to implement the JTAG scan chain
7
+ add_reg :dr, 0x0, size: 49 do |reg|
8
+ reg.bit 48, :write
9
+ reg.bits 47..32, :address
10
+ reg.bits 31..0, :data
11
+ end
12
+
13
+ # User regs
14
+ add_reg :cmd, 0x0
15
+
16
+ reg :status, 0x4 do |reg|
17
+ reg.bit 2, :error, access: :w1c
18
+ reg.bit 1, :fail, access: :w1c
19
+ reg.bit 0, :busy
20
+ end
21
+
22
+ add_reg :data, 0x8
23
+ end
24
+
25
+ def communication_test
26
+ ss "Communication test with #{name}"
27
+ data.write!(0x1234)
28
+ data.read!
29
+ data.read!
30
+ data.write!(0x5555_AAAA)
31
+ data.read!
32
+ end
33
+
34
+ def execute_cmd(code)
35
+ ss "Execute command #{code}"
36
+ # Verify that no command is currently running
37
+ status.read!(0)
38
+
39
+ cmd.write!(code)
40
+ 10.cycles
41
+ # Verify that the command has started
42
+
43
+ status.busy.read!(1)
44
+
45
+ # Wait for the command to complete, a 'command' lasts for
46
+ # 1000 cycles times the command code
47
+ (code * 1000).cycles
48
+
49
+ # Verify that the command completed and passed
50
+ status.read!(0)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,9 @@
1
+ Pattern.create do
2
+
3
+ dut.ip1.communication_test
4
+
5
+ dut.ip1.execute_cmd(1)
6
+
7
+ dut.ip1.execute_cmd(50)
8
+
9
+ end
@@ -0,0 +1,8 @@
1
+ Pattern.create do
2
+
3
+ dut.ip2.communication_test
4
+
5
+ dut.ip2.execute_cmd(10)
6
+ dut.ip2.execute_cmd(10)
7
+ dut.ip2.execute_cmd(10)
8
+ end
@@ -11,6 +11,12 @@
11
11
  //
12
12
  // 0 - Force data 0
13
13
  // 1 - Force data 1
14
+ //
15
+ // Parameter init_drive
16
+ // 0 - Initialize drive and assign to 0
17
+ // 1 - Initialize drive and assign to 1
18
+ // 2 - Don't initialize drive and assign to Z (default)
19
+ // -1 - Don't initialize drive or assign. Pin will be left unknown
14
20
  module pin_driver(error, pin, sync, match_loop);
15
21
  parameter init_drive = 2; // Which means don't drive initially, set to 0 or 1 to drive
16
22
  parameter pin_name = "undefined_name";
@@ -33,7 +39,9 @@ module pin_driver(error, pin, sync, match_loop);
33
39
  wire drive_data = force_data[0] ? 0 : (force_data[1] ? 1 : data[0]);
34
40
  wire contention = drive ? (pin !== drive_data ? 1 : 0) : 0;
35
41
 
36
- assign pin = drive ? drive_data : 1'bz;
42
+ if (init_drive != -1) begin
43
+ assign pin = drive ? drive_data : 1'bz;
44
+ end
37
45
 
38
46
  // Debug signal to show the expected data in the waves
39
47
  wire expect_data = compare ? data[0] : 1'bz;
@@ -113,14 +121,43 @@ module pin_drivers(errors, <%= dut.rtl_pins.map { |n, p, o| "#{p.id}_o" }.join('
113
121
  end
114
122
 
115
123
  % dut.rtl_pins.each do |name, pin, options|
116
- pin_driver #(.init_drive(<%= pin.driving? ? "#{pin.value}" : '2' %>), .pin_name("<%= pin.id %>")) <%= pin.id %>(.pin(<%= pin.id %>_o), .error(<%= pin.id %>_err), .sync(sync), .match_loop(match_loop));
124
+ pin_driver #(<%= pin.meta[:origen_sim_init_pin_state].nil? ? '' : ".init_drive(#{pin.meta[:origen_sim_init_pin_state]}), "%>.pin_name("<%= pin.id %>")) <%= pin.id %>(.pin(<%= pin.id %>_o), .error(<%= pin.id %>_err), .sync(sync), .match_loop(match_loop));
117
125
  % end
118
126
 
127
+
119
128
  endmodule
120
129
 
130
+ // Placeholder for user notes. This will be an empty module if no notes were given
131
+ module user_details;
132
+ parameter _AVAILABLE_DETAILS_ = "<%= options[:user_details].empty? ? "" : options[:user_details].keys.join(',') %>";
133
+
134
+ % options[:user_details].each do |name, note|
135
+ parameter <%= name %> = "<%= note %>";
136
+ % end
137
+ endmodule
121
138
 
122
- module debug(errors);
123
139
 
140
+ // SnapshotDetails module. Just stores some traceability details into the snapshot
141
+ // that can be queried by OrigenSim or viewed in the waveform viewer.
142
+ module snapshot_details;
143
+ // Add a parameter that lists the available parameters. OrigenSim can use this known parameter to query any others that are
144
+ // added here.
145
+ parameter _AVAILABLE_DETAILS_ = "ORIGEN_SIM_VERSION,COMPILATION_TIME_STAMP,COMPILATION_PATH,DEVICE_NAME,REVISION,REVISION_NOTE,TESTBENCH_VERSION,AUTHOR";
146
+
147
+ parameter ORIGEN_SIM_VERSION = "<%= OrigenSim::VERSION %>";
148
+ parameter COMPILATION_TIME_STAMP = "<%= Time.now %>";
149
+ parameter COMPILATION_PATH = "<%= Dir.pwd %>";
150
+ parameter DEVICE_NAME = "<%= options[:device_name] || 'No --device_name specified' %>";
151
+ parameter REVISION = "<%= options[:revision] || 'No --revision specified' %>";
152
+ parameter REVISION_NOTE = "<%= options[:revision_note] || 'No --revision_note specified' %>";
153
+ parameter TESTBENCH_VERSION = "<%= options[:parent_tb_version] || 'No --testbench_version specified' %>";
154
+ parameter AUTHOR = "<%= options[:author] || Origen.current_user.username %>";
155
+
156
+ user_details user_details();
157
+
158
+ endmodule
159
+
160
+ module debug(errors);
124
161
  input [31:0] errors;
125
162
 
126
163
  reg [1023:0] pattern = 0;
@@ -130,6 +167,8 @@ module debug(errors);
130
167
 
131
168
  reg handshake;
132
169
 
170
+ snapshot_details snapshot_details();
171
+
133
172
  endmodule
134
173
 
135
174
  module origen;
@@ -157,14 +196,17 @@ module origen;
157
196
  % dut.ground_pins.each do |name, pin, options|
158
197
  .<%= pin.id %>(<%= pin.id %>),
159
198
  % end
199
+ % # Keep track of the primary groups seen.
200
+ % seen_groups = []
160
201
  % dut.rtl_pins.each_with_index do |(name, pin, options), i|
161
202
  % if options[:group]
162
- % if pin.group_index == 0
203
+ % unless seen_groups.include?(pin.primary_group)
163
204
  .<%= pin.primary_group.id %>({
164
205
  % pin.primary_group.each_with_index do |pin, i|
165
206
  <%= pin.id %><%= i == (pin.primary_group.size - 1) ? '' : ',' %>
166
207
  % end
167
208
  })<%= i == (dut.rtl_pins.size - 1) ? '' : ',' %>
209
+ % seen_groups << pin.primary_group
168
210
  % end
169
211
  % else
170
212
  .<%= pin.rtl_name %>(<%= pin.id %>)<%= i == (dut.rtl_pins.size - 1) ? '' : ',' %>
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.14.0
4
+ version: 0.15.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-27 00:00:00.000000000 Z
11
+ date: 2019-02-11 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.35.0
19
+ version: 0.41.0
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.35.0
26
+ version: 0.41.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: origen_testers
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 0.5.1
47
+ version: 0.5.2
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.5.1
54
+ version: 0.5.2
55
55
  description:
56
56
  email:
57
57
  - stephen.f.mcginty@gmail.com
@@ -75,7 +75,6 @@ files:
75
75
  - ext/origen.h
76
76
  - ext/vpi_user.h
77
77
  - lib/origen_sim.rb
78
- - lib/origen_sim/artifacts.rb
79
78
  - lib/origen_sim/commands/build.rb
80
79
  - lib/origen_sim/commands/ci.rb
81
80
  - lib/origen_sim/commands/co.rb
@@ -89,11 +88,17 @@ files:
89
88
  - lib/origen_sim/origen_testers/api.rb
90
89
  - lib/origen_sim/simulation.rb
91
90
  - lib/origen_sim/simulator.rb
91
+ - lib/origen_sim/simulator/artifacts.rb
92
+ - lib/origen_sim/simulator/snapshot_details.rb
93
+ - lib/origen_sim/simulator/user_details.rb
92
94
  - lib/origen_sim/stderr_reader.rb
93
95
  - lib/origen_sim/stdout_reader.rb
94
96
  - lib/origen_sim/tester.rb
95
97
  - lib/origen_sim_dev/dut.rb
98
+ - lib/origen_sim_dev/ip.rb
96
99
  - lib/tasks/origen_sim.rake
100
+ - pattern/ip1_test.rb
101
+ - pattern/ip2_test.rb
97
102
  - pattern/test.rb
98
103
  - pattern/test2.rb
99
104
  - program/p1.rb
@@ -138,7 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
143
  version: 1.8.11
139
144
  requirements: []
140
145
  rubyforge_project:
141
- rubygems_version: 2.7.6
146
+ rubygems_version: 2.7.7
142
147
  signing_key:
143
148
  specification_version: 4
144
149
  summary: Plugin that provides a testbench environment to simulate Origen test patterns