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