origen_sim 0.15.0 → 0.16.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 +1 -1
- data/config/shared_commands.rb +13 -4
- data/config/version.rb +1 -1
- data/ext/bridge.c +521 -272
- data/ext/bridge.h +2 -0
- data/ext/defines.h.erb +8 -0
- data/ext/origen.c +2 -0
- data/lib/origen_sim.rb +21 -1
- data/lib/origen_sim/origen/pins/pin.rb +7 -2
- data/lib/origen_sim/origen_testers/api.rb +11 -2
- data/lib/origen_sim/simulation.rb +34 -4
- data/lib/origen_sim/simulator.rb +227 -19
- data/lib/origen_sim/stderr_reader.rb +9 -3
- data/lib/origen_sim/stdout_reader.rb +35 -12
- data/lib/origen_sim/tester.rb +209 -29
- data/lib/origen_sim_dev/dut.rb +31 -29
- data/pattern/test.rb +2 -0
- data/templates/origen_guides/simulation/debugging.md.erb +123 -6
- data/templates/origen_guides/simulation/environment.md.erb +3 -6
- data/templates/origen_guides/simulation/log.md.erb +1 -1
- data/templates/origen_guides/simulation/patterns.md.erb +35 -0
- data/templates/rtl_v/origen.v.erb +14 -49
- metadata +5 -5
data/pattern/test.rb
CHANGED
@@ -35,6 +35,7 @@ Pattern.create do
|
|
35
35
|
|
36
36
|
ss "Now try and read and write a register"
|
37
37
|
dut.cmd.write!(0x1234_5678)
|
38
|
+
tester.marker = 1
|
38
39
|
dut.cmd.read!(0x1234_5678)
|
39
40
|
|
40
41
|
if tester.sim?
|
@@ -44,6 +45,7 @@ Pattern.create do
|
|
44
45
|
|
45
46
|
ss "Test storing a register"
|
46
47
|
dut.cmd.write!(0x2244_6688)
|
48
|
+
Origen.log.info "Should be within 'Test storing a register'"
|
47
49
|
dut.cmd.store!
|
48
50
|
|
49
51
|
if tester.sim?
|
@@ -1,15 +1,132 @@
|
|
1
1
|
% render "layouts/guides.html" do
|
2
2
|
|
3
|
+
This guide describes some features that are useful for debugging a failing simulation
|
4
|
+
or when running
|
5
|
+
[an interactive ad-hoc simulation from the console.](<%= path "guides/simulation/app/#Starting_the_Simulator_in_an_Interactive_Session" %>)
|
6
|
+
|
7
|
+
#### Identifying Points in Time
|
8
|
+
|
9
|
+
All [major step comments](<%= path "guides/pattern/documenting/#Documenting_Major_Steps" %>) in pattern
|
10
|
+
source code will be simulation time-stamped and output to the console as shown below:
|
11
|
+
|
12
|
+
~~~ruby
|
13
|
+
ss "Test basic 2-pin match loop"
|
14
|
+
|
15
|
+
# ...
|
16
|
+
|
17
|
+
ss "Test a block match loop"
|
18
|
+
|
19
|
+
# ...
|
20
|
+
~~~
|
21
|
+
|
22
|
+
The above will produce this output where the simulation time when each operation occurs is given in ns:
|
23
|
+
|
24
|
+
~~~text
|
25
|
+
[INFO] 6.710[0.000] || 991700 ns: ===========================================================
|
26
|
+
[INFO] 6.710[0.001] || 991700 ns: Test basic 2-pin match loop
|
27
|
+
[INFO] 6.711[0.001] || 991700 ns: ===========================================================
|
28
|
+
[INFO] 6.711[0.001] || 1207500 ns: ===========================================================
|
29
|
+
[INFO] 6.712[0.000] || 1207500 ns: Test a block match loop
|
30
|
+
[INFO] 6.712[0.000] || 1207500 ns: ===========================================================
|
31
|
+
~~~
|
32
|
+
|
33
|
+
All [log output](<%= path "guides/misc/logger" %>) created by application code will also be simulation
|
34
|
+
time-stamped and synchronized to simulator progress:
|
35
|
+
|
36
|
+
~~~ruby
|
37
|
+
Origen.log.info "Something important is happening!"
|
38
|
+
~~~
|
39
|
+
|
40
|
+
~~~text
|
41
|
+
[INFO] 6.712[0.000] || 24210200 ns: Something important is happening!
|
42
|
+
~~~
|
43
|
+
|
44
|
+
|
45
|
+
**Note that applications should avoid the use of `puts` to output debug or status information to the console
|
46
|
+
because that will occur immediately and will not be time-stamped or synchronized with the simulator.**
|
47
|
+
|
48
|
+
Additionally, the Origen testbench contains a register that can be used to mark events like this:
|
49
|
+
|
50
|
+
~~~ruby
|
51
|
+
tester.marker = 0x1234
|
52
|
+
~~~
|
53
|
+
|
54
|
+
You can then view signal `origen.debug.marker` in a wave viewer and search for the appropriate value to
|
55
|
+
locate the specific point in time when the mark was applied.
|
56
|
+
|
57
|
+
When generating for non-simulation tester targets that statement will do nothing and it can be
|
58
|
+
safely left in production code.
|
59
|
+
|
60
|
+
|
61
|
+
#### Failed Register Reads
|
62
|
+
|
63
|
+
The following information is logged whenever a pin mis-compare occurs within a register read transaction:
|
64
|
+
|
65
|
+
* The path (name) of the register
|
66
|
+
* Expected data
|
67
|
+
* Received (actual) data - requires support from the physical driver, see below
|
68
|
+
* Application stack trace to identify where in the application code the read originated
|
69
|
+
|
70
|
+
Here is an example:
|
71
|
+
|
72
|
+
~~~ruby
|
73
|
+
ss "Now try and read and write a register"
|
74
|
+
dut.cmd.write!(0x1234_5678)
|
75
|
+
dut.cmd.read!(0x1234_5078) # Note that we just wrote ..567.. but are now expecting ..507..
|
76
|
+
~~~
|
77
|
+
|
78
|
+
~~~text
|
79
|
+
[INFO] 4.098[0.000] || 86500 ns: ======================================================================
|
80
|
+
[INFO] 4.098[0.001] || 86500 ns: Now try and read and write a register
|
81
|
+
[INFO] 4.099[0.001] || 86500 ns: ======================================================================
|
82
|
+
[ERROR] 4.100[0.001] || 117400 ns: Miscompare on pin tdo, expected 0 received 1
|
83
|
+
[ERROR] 4.101[0.001] || 117600 ns: Miscompare on pin tdo, expected 0 received 1
|
84
|
+
[ERROR] 4.102[0.001] || 129100 ns: Errors occurred reading register cmd:
|
85
|
+
[ERROR] 4.102[0.001] || 129100 ns: cmd.d: expected 12345078 received 12345678
|
86
|
+
[ERROR] 4.103[0.001] || 129100 ns:
|
87
|
+
[ERROR] 4.104[0.001] || 129100 ns: /home/stephen/Code/github/origen_sim/pattern/test.rb:39:in `block in <top (required)>'
|
88
|
+
[ERROR] 4.110[0.006] || 129100 ns: /home/stephen/Code/github/origen_sim/pattern/test.rb:1:in `<top (required)>'
|
89
|
+
~~~
|
90
|
+
|
91
|
+
The received data resolution does depend on the physical protocol driver supplying meta-data when
|
92
|
+
creating pin assertions (reads) that correspond to register bits, like this:
|
93
|
+
|
94
|
+
~~~ruby
|
95
|
+
pin(:tdo).assert(bit.data, meta: { position: bit.position })
|
96
|
+
~~~
|
97
|
+
|
98
|
+
For reference, here is the update that was made to the JTAG driver to support this feature -
|
99
|
+
[OrigenJTAG - Add meta data for OrigenSim](https://github.com/Origen-SDK/origen_jtag/pull/10/files)
|
100
|
+
|
101
|
+
If the driver has not provided this then a warning will be output and no received data will be given.
|
102
|
+
|
103
|
+
This feature will automatically be enabled for any reads launched via the register object itself, e.g.
|
104
|
+
`my_reg.read!`, but not for reads launched by calling the `read_register` method manually,
|
105
|
+
e.g. `dut.read_register(my_reg)`.
|
106
|
+
|
107
|
+
If your application has a tendency to do the latter, then the following modification can be made to your
|
108
|
+
`read_register` method to make OrigenSim aware of such transactions:
|
109
|
+
|
110
|
+
~~~ruby
|
111
|
+
def read_register(reg_or_value, options = {})
|
112
|
+
# Make OrigenSim aware of all transactions to enable failed transaction reporting
|
113
|
+
tester.read_register(reg_or_value, options) do
|
114
|
+
|
115
|
+
# Existing implementation here
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
~~~
|
120
|
+
|
121
|
+
This feature will also work in the case of the read object being a value rather than a register object.
|
122
|
+
|
123
|
+
|
124
|
+
#### Interactive Debugging
|
125
|
+
|
3
126
|
The execution of an Origen simulation is fully controlled by Origen/Ruby, this means that if you
|
4
127
|
insert a regular Ruby debugger breakpoint into your application code then you can step through the
|
5
128
|
simulation in real time.
|
6
129
|
|
7
|
-
This guide describes some features that are useful for interacting with the DUT from a simulation
|
8
|
-
breakpoint, or when running
|
9
|
-
[an interactive ad-hoc simulation from the console.](<%= path "guides/simulation/app/#Starting_the_Simulator_in_an_Interactive_Session" %>)
|
10
|
-
|
11
|
-
#### Syncing & Flushing
|
12
|
-
|
13
130
|
When a simulation is running most of the communication is one-way, Origen tells the simulator what to do,
|
14
131
|
and for performance reasons there is no handshake between Origen and the simulator at every instruction. Instead,
|
15
132
|
Origen fires off instructions into a buffer, the simulator executes them as fast as it can, and then Origen
|
@@ -37,12 +37,9 @@ OrigenSim.cadence do |sim|
|
|
37
37
|
# simulation will be abandoned and considered failed. If a particular simulation is known to be slow to start,
|
38
38
|
# the timeout can be extended as shown in this example (5 minutes):
|
39
39
|
sim.startup_timeout 5 * 60
|
40
|
-
#
|
41
|
-
#
|
42
|
-
|
43
|
-
# will be multiplied with all time advancements defined by Origen. This can be any value like 0.01, 0.1, 10,
|
44
|
-
# 100, 1000, etc. to make the cycle period seen in simulation bigger or smaller.
|
45
|
-
sim.time_factor 100
|
40
|
+
# Abort the simulation when this number of errors is reached (defaults to 100).
|
41
|
+
# This can also be overridden at runtime via the --max_errors switch.
|
42
|
+
sim.max_errors = 50
|
46
43
|
end
|
47
44
|
~~~
|
48
45
|
|
@@ -7,7 +7,7 @@ By default, OrigenSim will automatically suppress all simulator log output excep
|
|
7
7
|
contain the text _WARNING_ or _ERROR_ (case insensitive); both of these will be logged to the console and any occurrences of
|
8
8
|
the latter will also make the result of the simulation be classed as a FAIL.
|
9
9
|
|
10
|
-
All log output can be shown in the console by running with the `-
|
10
|
+
All log output can be shown in the console by running with the `-verbose` switch, and the log files will
|
11
11
|
always contain everything that was output by the simulator.
|
12
12
|
|
13
13
|
OrigenSim will also consider any output from the simulator to STDERR as a sign that something has gone wrong
|
@@ -148,6 +148,41 @@ at the point during the cycle where it will be read by the pattern.
|
|
148
148
|
However, if this were to be a problem in a particular application, you would see it fail when re-playing the
|
149
149
|
captured data in simulation.
|
150
150
|
|
151
|
+
#### Configuring the Capture Storage Location
|
152
|
+
|
153
|
+
By default, both `sim_delay` and `sim_capture` will save their captured data to
|
154
|
+
Org files (Origen native pattern format) using the following file naming rule:
|
155
|
+
`Origen.root/pattern/org/<target name>/<capture ID>.org`.
|
156
|
+
|
157
|
+
If your application is a top-level application then the default setting should work fine unless you wish
|
158
|
+
to share/re-use captured data between multiple targets.
|
159
|
+
|
160
|
+
Another reason to change from the default would be if data is captured at plugin-level and this needs
|
161
|
+
to be referenced later when running within a top-level application.
|
162
|
+
There are potentially two issues in that case:
|
163
|
+
|
164
|
+
* `Origen.root` will point to the top-level application's root instead of the plugin's
|
165
|
+
* The target name used at the top-level could be different from the one that was used within the plugin to capture
|
166
|
+
the data
|
167
|
+
|
168
|
+
In such cases, the default capture directory can be changed by setting the `OrigenSim.capture_dir` attribute.
|
169
|
+
This can be set anytime before the first call is made to `sim_delay` or `sim_capture`.
|
170
|
+
|
171
|
+
For example, a plugin that needs its captured data to work later as part of a top-level application,
|
172
|
+
could set the capture directory in a [startup callback](<%= path "guides/misc/callbacks/#startup(options)" %>),
|
173
|
+
like this:
|
174
|
+
|
175
|
+
~~~ruby
|
176
|
+
def startup(options)
|
177
|
+
# Only modify this if we are the current app or plugin
|
178
|
+
if Origen.app!.current? || Origen.app!.current_plugin?
|
179
|
+
# Use a directory within our root and named after the current IP block, rather than the target
|
180
|
+
OrigenSim.capture_dir = Origen.root!.join('pattern', 'org', dut.myip.name)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
~~~
|
184
|
+
|
185
|
+
|
151
186
|
#### Creating Simulation-Only Assertions
|
152
187
|
|
153
188
|
Users are of course encouraged to write patterns that test the DUT via its pin interface since such
|
@@ -17,15 +17,14 @@
|
|
17
17
|
// 1 - Initialize drive and assign to 1
|
18
18
|
// 2 - Don't initialize drive and assign to Z (default)
|
19
19
|
// -1 - Don't initialize drive or assign. Pin will be left unknown
|
20
|
-
module pin_driver(
|
20
|
+
module pin_driver(pin, sync);
|
21
21
|
parameter init_drive = 2; // Which means don't drive initially, set to 0 or 1 to drive
|
22
22
|
parameter pin_name = "undefined_name";
|
23
23
|
|
24
|
-
output reg error;
|
25
24
|
inout pin;
|
26
25
|
input sync;
|
27
|
-
input match_loop;
|
28
26
|
|
27
|
+
reg error;
|
29
28
|
reg [1:0] data = 0;
|
30
29
|
reg [1:0] force_data = 0;
|
31
30
|
reg compare = 0;
|
@@ -52,9 +51,8 @@ module pin_driver(error, pin, sync, match_loop);
|
|
52
51
|
|
53
52
|
// pin compare failure logger
|
54
53
|
always @(posedge error) begin
|
55
|
-
|
56
|
-
|
57
|
-
end
|
54
|
+
//$display("!4![%t] Miscompare on pin %s, expected %d received %d", $time, pin_name, data[0], pin);
|
55
|
+
$bridge_on_miscompare(pin_name, data[0], pin);
|
58
56
|
end
|
59
57
|
|
60
58
|
// SMcG - needs more work, causes non-genuine fails in OrigenSim test case
|
@@ -77,7 +75,7 @@ module pin_driver(error, pin, sync, match_loop);
|
|
77
75
|
|
78
76
|
initial begin
|
79
77
|
// Set the timescale to ns (-9) with 0 decimal place precision, 20 chars
|
80
|
-
|
78
|
+
//$timeformat(-9, 0, "", 20);
|
81
79
|
if (init_drive == 1) begin
|
82
80
|
drive = 1;
|
83
81
|
data[0] = 1;
|
@@ -89,39 +87,16 @@ module pin_driver(error, pin, sync, match_loop);
|
|
89
87
|
|
90
88
|
endmodule
|
91
89
|
|
92
|
-
module pin_drivers(
|
90
|
+
module pin_drivers(<%= dut.rtl_pins.map { |n, p, o| "#{p.id}_o" }.join(', ') %>);
|
93
91
|
|
94
92
|
% dut.rtl_pins.each do |name, pin, options|
|
95
93
|
output <%= pin.id %>_o;
|
96
94
|
% end
|
97
95
|
|
98
|
-
% dut.rtl_pins.each do |name, pin, options|
|
99
|
-
wire <%= pin.id %>_err;
|
100
|
-
% end
|
101
|
-
|
102
|
-
output reg [31:0] errors = 0;
|
103
96
|
reg sync = 0;
|
104
|
-
reg [31:0] match_errors = 0;
|
105
|
-
reg match_loop = 0;
|
106
|
-
|
107
|
-
always @(
|
108
|
-
|
109
|
-
% dut.rtl_pins.each_with_index do |(name, pin, options), i|
|
110
|
-
% if i == 0
|
111
|
-
posedge <%= pin.id %>_err
|
112
|
-
% else
|
113
|
-
or posedge <%= pin.id %>_err
|
114
|
-
% end
|
115
|
-
% end
|
116
|
-
) begin
|
117
|
-
if (match_loop == 1)
|
118
|
-
match_errors[31:0] = match_errors[31:0] + 1;
|
119
|
-
else
|
120
|
-
errors[31:0] = errors[31:0] + 1;
|
121
|
-
end
|
122
97
|
|
123
98
|
% dut.rtl_pins.each do |name, pin, options|
|
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), .
|
99
|
+
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), .sync(sync));
|
125
100
|
% end
|
126
101
|
|
127
102
|
|
@@ -157,8 +132,10 @@ module snapshot_details;
|
|
157
132
|
|
158
133
|
endmodule
|
159
134
|
|
160
|
-
module debug
|
161
|
-
|
135
|
+
module debug;
|
136
|
+
reg [31:0] errors = 0;
|
137
|
+
reg [15:0] marker = 0;
|
138
|
+
reg [31:0] match_errors = 0;
|
162
139
|
|
163
140
|
reg [1023:0] pattern = 0;
|
164
141
|
% OrigenSim::NUMBER_OF_COMMENT_LINES.times do |i|
|
@@ -179,13 +156,10 @@ module origen;
|
|
179
156
|
wire <%= pin.id %>;
|
180
157
|
% end
|
181
158
|
|
182
|
-
wire [31:0] errors;
|
183
|
-
|
184
159
|
pin_drivers pins (
|
185
160
|
% dut.rtl_pins.each_with_index do |(name, pin, options), i|
|
186
|
-
|
161
|
+
.<%= pin.id %>_o(<%= pin.id %>)<%= i == dut.rtl_pins.size - 1 ? '' : ',' %>
|
187
162
|
% end
|
188
|
-
.errors(errors)
|
189
163
|
);
|
190
164
|
|
191
165
|
// Instantiate the DUT
|
@@ -205,7 +179,7 @@ module origen;
|
|
205
179
|
% pin.primary_group.each_with_index do |pin, i|
|
206
180
|
<%= pin.id %><%= i == (pin.primary_group.size - 1) ? '' : ',' %>
|
207
181
|
% end
|
208
|
-
})<%= i ==
|
182
|
+
})<%= (i + pin.primary_group.size) == dut.rtl_pins.size ? '' : ',' %>
|
209
183
|
% seen_groups << pin.primary_group
|
210
184
|
% end
|
211
185
|
% else
|
@@ -214,17 +188,11 @@ module origen;
|
|
214
188
|
% end
|
215
189
|
);
|
216
190
|
|
217
|
-
debug debug (
|
218
|
-
.errors(errors)
|
219
|
-
);
|
191
|
+
debug debug ();
|
220
192
|
|
221
193
|
`ifdef ORIGEN_VCD
|
222
194
|
initial
|
223
195
|
begin
|
224
|
-
//$display("********************************");
|
225
|
-
//$display("Creating origen.vcd...");
|
226
|
-
//$display("********************************");
|
227
|
-
//$dumpfile("origen.vcd");
|
228
196
|
$dumpvars(0,origen);
|
229
197
|
end
|
230
198
|
`endif
|
@@ -248,9 +216,6 @@ module origen;
|
|
248
216
|
|
249
217
|
|
250
218
|
always @(posedge finish) begin
|
251
|
-
//$display("********************************");
|
252
|
-
//$display("Finishing simulation...");
|
253
|
-
//$display("********************************");
|
254
219
|
$finish(2);
|
255
220
|
end
|
256
221
|
|
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.16.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: 2019-
|
11
|
+
date: 2019-03-18 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.
|
19
|
+
version: 0.43.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.
|
26
|
+
version: 0.43.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: origen_testers
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -143,7 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
143
|
version: 1.8.11
|
144
144
|
requirements: []
|
145
145
|
rubyforge_project:
|
146
|
-
rubygems_version: 2.7.
|
146
|
+
rubygems_version: 2.7.6
|
147
147
|
signing_key:
|
148
148
|
specification_version: 4
|
149
149
|
summary: Plugin that provides a testbench environment to simulate Origen test patterns
|