origen_sim 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +5 -5
  2. data/config/application.rb +17 -2
  3. data/config/shared_commands.rb +7 -0
  4. data/config/version.rb +1 -1
  5. data/ext/bridge.c +13 -3
  6. data/lib/origen_sim.rb +10 -0
  7. data/lib/origen_sim/artifacts.rb +101 -0
  8. data/lib/origen_sim/commands/build.rb +41 -9
  9. data/lib/origen_sim/heartbeat.rb +13 -1
  10. data/lib/origen_sim/origen_testers/api.rb +90 -7
  11. data/lib/origen_sim/simulation.rb +49 -4
  12. data/lib/origen_sim/simulator.rb +171 -19
  13. data/lib/origen_sim/stderr_reader.rb +19 -13
  14. data/lib/origen_sim/stdout_reader.rb +22 -16
  15. data/lib/origen_sim/tester.rb +110 -1
  16. data/lib/origen_sim_dev/dut.rb +5 -0
  17. data/pattern/test.rb +143 -0
  18. data/templates/empty.gtkw +19 -1
  19. data/templates/empty.rc +86 -0
  20. data/templates/empty.svcf +79 -9
  21. data/templates/empty.tcl +37 -9
  22. data/templates/origen_guides/simulation/app.md.erb +131 -0
  23. data/templates/origen_guides/simulation/artifacts.md.erb +115 -0
  24. data/templates/origen_guides/simulation/compiling.md.erb +190 -0
  25. data/templates/origen_guides/simulation/debugging.md.erb +135 -0
  26. data/templates/origen_guides/simulation/environment.md.erb +217 -0
  27. data/templates/origen_guides/simulation/flows.md.erb +69 -0
  28. data/templates/origen_guides/simulation/howitworks.md.erb +64 -0
  29. data/templates/origen_guides/simulation/introduction.md.erb +35 -0
  30. data/templates/origen_guides/simulation/log.md.erb +118 -0
  31. data/templates/origen_guides/simulation/patterns.md.erb +193 -0
  32. data/templates/probe.tcl.erb +3 -0
  33. data/templates/rtl_v/origen.v.erb +19 -3
  34. data/templates/web/layouts/_guides.html.erb +15 -0
  35. metadata +18 -5
@@ -0,0 +1,35 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ <img src="https://user-images.githubusercontent.com/158364/36662666-6b49d096-1adf-11e8-997e-889caba391b2.png" alt="origen_sim" style="
4
+ width: 100%;
5
+ ">
6
+
7
+ OrigenSim is a plugin that enables semiconductor test patterns (and flows) written in Origen/Ruby to be run
8
+ in a dynamic Verilog simulation, similar to what is commonly known as a _Virtual Test_ simulation in other workflows.
9
+
10
+ It provides a simulation tester driver (which can be used as a direct replacement for Origen's
11
+ conventional ATE tester drivers) which will
12
+ pass requests to drive or expect pin values onto a simulator instead of rendering them to an ASCII file. Since
13
+ the application-level Origen code is the same in both cases, it guarantees that what happens in the simulation
14
+ and in the final pattern are the same and that ultimately they will work first time on silicon.
15
+
16
+ For debugging, OrigenSim supports the injection of regular Ruby debugger breakpoints anywhere in the pattern
17
+ source code. This will halt the simulation at the given point in time, allowing it to be interactively
18
+ debugged at the Origen-source-code level.
19
+
20
+ Similarly, an Origen interactive session (`origen i`) can be launched with an OrigenSim driver,
21
+ allowing designers and test engineers to use Origen APIs to interactively manipulate a live simulation of their
22
+ DUT while viewing the response in real time in a wave viewer.
23
+
24
+ #### Adding OrigenSim To Your Application
25
+
26
+ To enable your application to use OrigenSim, simply add the plugin to your Gemfile:
27
+
28
+ ~~~ruby
29
+ gem "origen_sim"
30
+ ~~~
31
+
32
+ and then [create a simulation environment setup](<%= path "guides/simulation/environment" %>).
33
+
34
+
35
+ % end
@@ -0,0 +1,118 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ Log output from simulations is often very verbose, which can make it hard to distinguish between messages
4
+ that are important and those that can be safely ignored.
5
+
6
+ By default, OrigenSim will automatically suppress all simulator log output except for any lines that
7
+ contain the text _WARNING_ or _ERROR_ (case insensitive); both of these will be logged to the console and any occurrences of
8
+ the latter will also make the result of the simulation be classed as a FAIL.
9
+
10
+ All log output can be shown in the console by running with the `-d` or `--debug` switches, and the log files will
11
+ always contain everything that was output by the simulator.
12
+
13
+ OrigenSim will also consider any output from the simulator to STDERR as a sign that something has gone wrong
14
+ and this will also cause the simulation result to be classed as a FAIL.
15
+
16
+ If your simulation produces STDERR output which you don't care about (and which you don't want to make your
17
+ simulation FAIL), then you can configure OrigenSim to ignore all STDERR messages via:
18
+
19
+ ~~~ruby
20
+ OrigenSim.fail_on_stderr = false
21
+ ~~~
22
+
23
+ Alternatively, a safer solution is to declare which specific messages on STDERR should be ignored.
24
+ For example, say that in an early design build the ADC is not configured correctly and this results
25
+ in a message about this being output to STDERR.
26
+ However, since this problem does not affect the particular IP that we are testing we do
27
+ not want our simulations to FAIL because of it.
28
+
29
+ In such a case you can add strings to the `stderr_string_exceptions` array and any STDERR lines which contain
30
+ the given text will be ignored:
31
+
32
+ ~~~ruby
33
+ OrigenSim.stderr_string_exceptions << 'invalid adc config' # Case in-sensitive match
34
+ ~~~
35
+
36
+ **Note that in all of these cases the given text is considered to be case-insensitive when considering if
37
+ it matches a log line.**
38
+
39
+ If you need case-sensitivity (or more generally need more control of exactly what is considered to be a match), you can
40
+ supply a regular expression instead of a string for all of the cases discussed here:
41
+
42
+ ~~~ruby
43
+ OrigenSim.stderr_string_exceptions << /invalid adc config/ # Case sensitive match
44
+ ~~~
45
+
46
+ Similarly, if you find that the default of matching for _ERROR_ in STDOUT messages is being overly aggressive,
47
+ exceptions can be added in a similar way:
48
+
49
+ ~~~ruby
50
+ OrigenSim.error_string_exceptions << 'uninitialized value in ROM at'
51
+ ~~~
52
+
53
+ This means that a log line resembling <code>ERROR uninitialized value in ROM at 0x1000</code> will not fail the simulation,
54
+ but the line `ERROR uninitialized value in RAM at 0x2000` will fail.
55
+
56
+ On the other hand, if you find that simply matching for _ERROR_ is not catching some cases which you would
57
+ like to cause a FAIL, you can add additional strings to watch out for like this:
58
+
59
+ ~~~ruby
60
+ OrigenSim.error_strings << 'FAILED'
61
+ ~~~
62
+
63
+ If you want to remove 'ERROR' from the list of error strings (in there by default), you can assign a new array
64
+ instance:
65
+
66
+ ~~~ruby
67
+ OrigenSim.error_strings << 'FAILED'
68
+
69
+ OrigenSim.error_strings # => ['ERROR', 'FAILED']
70
+
71
+ OrigenSim.error_strings = ['FAILED']
72
+
73
+ OrigenSim.error_strings # => ['FAILED']
74
+ ~~~
75
+
76
+ Similar variables exist to configure what you want to catch as a warning:
77
+
78
+ ~~~ruby
79
+ OrigenSim.warning_strings # => ['WARNING']
80
+
81
+ OrigenSim.warning_string_exceptions # => []
82
+ ~~~
83
+
84
+ and also to match any output lines that you simply want to be shown in the console by default:
85
+
86
+ ~~~ruby
87
+ OrigenSim.log_string # => []
88
+ ~~~
89
+
90
+ It is conventional to do all such configuration like this with `environment/sim.rb`, where you can decide
91
+ to make it global (applies to all targets), target-specific, or a combination of both:
92
+
93
+ ~~~ruby
94
+ # environment/sim.rb
95
+
96
+ # Will apply to all targets
97
+ OrigenSim.error_strings << 'FAILED'
98
+
99
+ case Origen.target.name
100
+
101
+ when "my_dut1"
102
+ OrigenSim.cadence do |sim|
103
+ # Configuration of Cadence simulator to be used for DUT1 here
104
+ end
105
+
106
+ # Known problem with this specific DUT only
107
+ OrigenSim.error_string_exceptions << 'uninitialized value in ROM at'
108
+
109
+ when "my_dut2"
110
+ OrigenSim.synopsys do |sim|
111
+ # Configuration of Synopsys simulator to be used for DUT2 here
112
+ end
113
+
114
+ # ...
115
+ ~~~
116
+
117
+
118
+ % end
@@ -0,0 +1,193 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ Patterns are simulated by simply generating the pattern with
4
+ a [simulation environment](<%= path "guides/simulation/environment" %>)
5
+ selected:
6
+
7
+ ~~~text
8
+ origen g my_pattern -e environment/sim.rb
9
+ ~~~
10
+
11
+ Most of the [common pattern API](<%= path "guides/pattern/common" %>) is supported
12
+ by OrigenSim and therefore you should expect to find the simulation environment
13
+ a drop-in replacement for your conventional ATE environment driver.
14
+
15
+ If you come across an API that OrigenSim does not support but you think that
16
+ it should, please raise a ticket here describing what you
17
+ tried to do <https://github.com/Origen-SDK/origen_sim/issues>.
18
+
19
+
20
+ #### Waiting For Events
21
+
22
+ When your pattern invokes some DUT action and you need to wait for it to complete, you
23
+ normally have two options:
24
+
25
+ * Calculate how long it should take and wait for a fixed delay
26
+ * Implement a match loop to dynamically wait for an expected response to occur
27
+
28
+ Both of these are fully supported by OrigenSim, see the
29
+ [Timing and Waiting guide](<%= path "guides/pattern/timing" %>) for more information on these APIs.
30
+
31
+ However, if your pattern generation flow is going to be supported by simulation, then you also have
32
+ a third option - to derive the required wait time from the simulation itself.
33
+
34
+ OrigenSim makes this very easy via the following API:
35
+
36
+ ~~~ruby
37
+ cc "Wait for the program command to complete"
38
+
39
+ tester.sim_delay :program_command do
40
+ dut.pin(:done).assert!(1)
41
+ end
42
+ dut.pin(:done).dont_care # Any pin assertions/reads created within the block will persist beyond it, so
43
+ # remember to clear any assertions that you don't want to carryover afterwards
44
+ ~~~
45
+
46
+ The `sim_delay` method provides the convenience of a match loop for the purposes of
47
+ delay calculation but will still generate a static pattern for the ATE. It will automatically calculate how
48
+ long the given block takes to pass and then insert that delay when later generating the pattern for an ATE.
49
+
50
+ An ID must be given to each delay, `:program_command` in this example, and if the same ID is used in multiple
51
+ calls to `sim_delay` then it means that the same delay will be used for each occurrence.
52
+
53
+ When simulating a pattern that contains `sim_delay` block(s) for the first time, the delay will
54
+ be calculated from the simulation and stored in an Org file (Origen native pattern format) within your
55
+ application's pattern directory. These files should be committed to your revision control system and considered
56
+ as part of your application.
57
+
58
+ The next time that you simulate it, the previously calculated delay will be inserted into the
59
+ pattern and therefore the simulation will be verifying that the delay is correct.
60
+
61
+ If you want to re-calculate the delays during a simulation then run with the `--sim_capture` switch:
62
+
63
+ ~~~text
64
+ origen g my_pattern -e environment/sim.rb --sim_capture
65
+ ~~~
66
+
67
+ Additional padding can be added to the calculated delay like this (all the usual `time_in_us:` style
68
+ of time options are supported):
69
+
70
+ ~~~ruby
71
+ tester.sim_delay :program_command, padding: { time_in_cycles: 10 } do
72
+ dut.pin(:done).assert!(1)
73
+ end
74
+ dut.pin(:done).dont_care # Any pin assertions/reads created within the block will persist beyond it, so
75
+ # remember to clear any assertions that you don't want to carryover afterwards
76
+ ~~~
77
+
78
+ By default, the block will be evaluated constantly until it passes when calculating the delay from
79
+ the simulation.
80
+
81
+ If the time is long and this is making your simulation run too slow, you can use lower resolution
82
+ by supplying a `:resolution` option, either as a number of cycles:
83
+
84
+
85
+ ~~~ruby
86
+ tester.sim_delay :program_command, resolution: 10 do
87
+ dut.pin(:done).assert!(1)
88
+ end
89
+ dut.pin(:done).dont_care # Any pin assertions/reads created within the block will persist beyond it, so
90
+ # remember to clear any assertions that you don't want to carryover afterwards
91
+ ~~~
92
+
93
+ or by supplying a hash filled with the usual time options:
94
+
95
+ ~~~ruby
96
+ tester.sim_delay :program_command, resolution: { time_in_ns: 50 } do
97
+ dut.pin(:done).assert!(1)
98
+ end
99
+ dut.pin(:done).dont_care # Any pin assertions/reads created within the block will persist beyond it, so
100
+ # remember to clear any assertions that you don't want to carryover afterwards
101
+ ~~~
102
+
103
+ #### Capturing Responses from the Simulation
104
+
105
+ Sometimes the response from your DUT maybe hard to predict and/or complicated to model in Origen, think about a digital data
106
+ stream response from a pin when testing a communications protocol.
107
+
108
+ OrigenSim provides an API for such a case which allows pin output values for a subset of pins/vectors
109
+ to be sampled during a simulation. The response is then captured and converted into the corresponding
110
+ expect data when the same pattern is later generated for the ATE.
111
+
112
+ Capturing is really easy, just wrap the operation you want to capture in your pattern source code like this:
113
+
114
+ ~~~ruby
115
+ tester.sim_capture :cmd55, :dout, :test_bus, :tdo do
116
+ dut.pins(:din_port).drive!(0x1234_5678)
117
+ dut.cmd.write!(0x55)
118
+ 60.cycles
119
+ end
120
+ ~~~
121
+
122
+ The first argument is an ID for the capture, this can be anything but the user must assign it.
123
+ Then supply a list of pin/pin_group IDs (or pin objects) that you want to capture.
124
+
125
+ If you use the same ID more than once it means that the same captured data will be used in multiple places.
126
+
127
+ When you add this to the pattern an error will be raised if you try to generate an ATE pattern, this will
128
+ advise that the data has not been captured yet and it must be run in a simulation first.
129
+
130
+ When you run it in a simulation for the first time, the data will be captured and stored to your application
131
+ in the `pattern/sim_capture` directory. These files should be checked into your application as if they were regular patterns.
132
+
133
+ On subsequent simulation runs, the data will not be captured but instead will be re-played from the simulation
134
+ - i.e. the pattern will assert that the DUT output matches what is in the capture file.
135
+ In other words, by adding this and then simulating twice using the same command, you are both capturing and
136
+ then verifying the captured data.
137
+
138
+ Add this switch to update the captures during a subsequent simulation run:
139
+
140
+ ~~~text
141
+ origen g my_pattern --sim_capture
142
+ ~~~
143
+
144
+ To use the captured data in an ATE pattern, simply switch to an ATE target and generate as normal.
145
+
146
+ A known limitation of this feature is that the pin state data is currently captured at the end of a cycle, not
147
+ at the point during the cycle where it will be read by the pattern.
148
+ However, if this were to be a problem in a particular application, you would see it fail when re-playing the
149
+ captured data in simulation.
150
+
151
+ #### Creating Simulation-Only Assertions
152
+
153
+ Users are of course encouraged to write patterns that test the DUT via its pin interface since such
154
+ patterns will work in physical environments like the ATE.
155
+
156
+ However, it can be useful to supplement your patterns with simulation-only assertions which peek inside
157
+ the DUT to check that it is behaving as expected. Such assertions can report useful failure information
158
+ back to the user which may help when debugging a failed pattern simulation.
159
+
160
+ ~~~ruby
161
+ # This code must be skipped when the pattern is generating for an ATE target environment
162
+ if tester.sim?
163
+ value = tester.simulator.peek("origen.dut.path.to.net").to_i[7..4]
164
+ if value != 0xA
165
+ OrigenSim.error "The internal node was #{value.to_hex} instead of 0xA!"
166
+ end
167
+ end
168
+ ~~~
169
+
170
+ Note the use of `OrigenSim.error` to report the error message, this will cause the simulation result
171
+ to be reported as a FAIL, even if all pin level assertions otherwise pass.
172
+
173
+ Also note that the value returned from the `peek` method is converted into an integer. This is because
174
+ `peek` returns an instance of [Origen::Value](<%= path "api/Origen/Value.html" %>) which can also handle
175
+ `X` or `Z` values.
176
+
177
+ So for example, if you actually wanted a given bit to be `Z` you could write your assertion as:
178
+
179
+ ~~~ruby
180
+ unless tester.simulator.peek("origen.dut.path.to.net")[4].z?
181
+ OrigenSim.error "Bit 4 of some net was not in hi-Z mode!"
182
+ end
183
+ ~~~
184
+
185
+ It is also possible to force nets within the DUT via a corresponding `poke` method:
186
+
187
+ ~~~ruby
188
+ if tester.sim?
189
+ test.simulator.poke "path.to.some.net[15:8]", 0x51
190
+ end
191
+ ~~~
192
+
193
+ % end
@@ -1,6 +1,9 @@
1
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
+ % Array(options[:tcl_inputs]).each do |line|
5
+ <%= line %>
6
+ % end
4
7
 
5
8
  % Hash(options[:force]).each do |net, value|
6
9
  % net = net.to_s.strip.sub(/^(origen\.|origen\.dut\.|\.)/, '')
@@ -75,6 +75,8 @@ module pin_drivers(errors, <%= dut.rtl_pins.map { |n, p, o| "#{p.id}_o" }.join('
75
75
 
76
76
  output reg [31:0] errors = 0;
77
77
  reg sync = 0;
78
+ reg [31:0] match_errors = 0;
79
+ reg match_loop = 0;
78
80
 
79
81
  always @(
80
82
 
@@ -86,7 +88,10 @@ module pin_drivers(errors, <%= dut.rtl_pins.map { |n, p, o| "#{p.id}_o" }.join('
86
88
  % end
87
89
  % end
88
90
  ) begin
89
- errors[31:0] = errors[31:0] + 1;
91
+ if (match_loop == 1)
92
+ match_errors[31:0] = match_errors[31:0] + 1;
93
+ else
94
+ errors[31:0] = errors[31:0] + 1;
90
95
  end
91
96
 
92
97
  % dut.rtl_pins.each do |name, pin, options|
@@ -101,7 +106,9 @@ module debug(errors);
101
106
  input [31:0] errors;
102
107
 
103
108
  reg [1023:0] pattern = 0;
104
- reg [1023:0] comments = 0;
109
+ % OrigenSim::NUMBER_OF_COMMENT_LINES.times do |i|
110
+ reg [1023:0] comments<%= i %> = 'h20; // Contain a space by default
111
+ % end
105
112
 
106
113
  reg handshake;
107
114
 
@@ -170,7 +177,16 @@ module origen;
170
177
  $vcdplusmemon;
171
178
  end
172
179
  `endif
173
-
180
+
181
+ `ifdef ORIGEN_FSDB
182
+ initial
183
+ begin
184
+ $fsdbDumpfile("origen.fsdb");
185
+ $fsdbDumpvars(0, "+all");
186
+ end
187
+ `endif
188
+
189
+
174
190
  always @(posedge finish) begin
175
191
  //$display("********************************");
176
192
  //$display("Finishing simulation...");
@@ -0,0 +1,15 @@
1
+ ---
2
+ title: Origen - Guides
3
+ ---
4
+ <%= render "templates/web/partials/navbar.html" %>
5
+
6
+ %# Add/edit sections here, the code below will expand this with the correct markup,
7
+ %# pass in the topic you want selected via the :tab option.
8
+ % i = OrigenDocHelpers::GuideIndex.new
9
+ % Origen.app.config.shared[:origen_guides_index].call(i)
10
+
11
+ % render "doc_helpers/searchable.html", options.merge(index: i, root: "", prompt: "Search the guides...") do
12
+
13
+ <%= yield %>
14
+
15
+ % end
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.12.0
4
+ version: 0.13.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-28 00:00:00.000000000 Z
11
+ date: 2018-10-04 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.33.3
19
+ version: 0.35.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.33.3
26
+ version: 0.35.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: origen_testers
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -75,6 +75,7 @@ files:
75
75
  - ext/origen.h
76
76
  - ext/vpi_user.h
77
77
  - lib/origen_sim.rb
78
+ - lib/origen_sim/artifacts.rb
78
79
  - lib/origen_sim/commands/build.rb
79
80
  - lib/origen_sim/commands/ci.rb
80
81
  - lib/origen_sim/commands/co.rb
@@ -98,12 +99,24 @@ files:
98
99
  - program/p1.rb
99
100
  - program/p2.rb
100
101
  - templates/empty.gtkw
102
+ - templates/empty.rc
101
103
  - templates/empty.svcf
102
104
  - templates/empty.tcl
105
+ - templates/origen_guides/simulation/app.md.erb
106
+ - templates/origen_guides/simulation/artifacts.md.erb
107
+ - templates/origen_guides/simulation/compiling.md.erb
108
+ - templates/origen_guides/simulation/debugging.md.erb
109
+ - templates/origen_guides/simulation/environment.md.erb
110
+ - templates/origen_guides/simulation/flows.md.erb
111
+ - templates/origen_guides/simulation/howitworks.md.erb
112
+ - templates/origen_guides/simulation/introduction.md.erb
113
+ - templates/origen_guides/simulation/log.md.erb
114
+ - templates/origen_guides/simulation/patterns.md.erb
103
115
  - templates/probe.tcl.erb
104
116
  - templates/rtl_v/origen.v.erb
105
117
  - templates/web/index.md.erb
106
118
  - templates/web/layouts/_basic.html.erb
119
+ - templates/web/layouts/_guides.html.erb
107
120
  - templates/web/partials/_navbar.html.erb
108
121
  - templates/web/release_notes.md.erb
109
122
  homepage:
@@ -125,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
138
  version: 1.8.11
126
139
  requirements: []
127
140
  rubyforge_project:
128
- rubygems_version: 2.6.14.1
141
+ rubygems_version: 2.7.7
129
142
  signing_key:
130
143
  specification_version: 4
131
144
  summary: Plugin that provides a testbench environment to simulate Origen test patterns