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,135 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ The execution of an Origen simulation is fully controlled by Origen/Ruby, this means that if you
4
+ insert a regular Ruby debugger breakpoint into your application code then you can step through the
5
+ simulation in real time.
6
+
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
+ When a simulation is running most of the communication is one-way, Origen tells the simulator what to do,
14
+ and for performance reasons there is no handshake between Origen and the simulator at every instruction. Instead,
15
+ Origen fires off instructions into a buffer, the simulator executes them as fast as it can, and then Origen
16
+ periodically waits for the simulator to catch up if it is running too far ahead.
17
+
18
+ If you have entered a breakpoint and you suspect that the simulator may be still catching up, you can run:
19
+
20
+ ~~~ruby
21
+ tester.sync_up
22
+ ~~~
23
+
24
+ When that method returns you are guaranteed that the simulator is at the same point.
25
+
26
+ Note that most of the time you will not need to do this manually since Origen will automatically sync up for
27
+ any operation that involves reading data from the simulation, e.g. peeking or reading registers.
28
+
29
+ If you have a wave viewer open during the debug session it may still look like the simulation is running behind, or the
30
+ wave viewer may appear to hang if you have tried to refresh it.
31
+ This is because the simulator is buffering output that has yet to be written to the wave dump.
32
+
33
+ You can force it to flush the buffer and update the wave viewer by running:
34
+
35
+ ~~~ruby
36
+ tester.flush
37
+ ~~~
38
+
39
+ Note that flushing will internally call a `sync_up` so you don't have to do both of these manually.
40
+
41
+ #### Accessing the DUT's Internal Nets
42
+
43
+ The methods `tester.simulator.peek` and `tester.simulator.poke` are available for reading and writing values
44
+ to internal DUT nets respectively.
45
+
46
+ See the section on [Creating Simulation-Only Assertions](<%= path "guides/simulation/patterns/#Creating_Simulation-Only_Assertions" %>)
47
+ for more details on these.
48
+
49
+ #### Register Reading (and Writing)
50
+
51
+ Referencing a register from the console will show you what Origen thinks the register currently contains:
52
+
53
+ ~~~text
54
+ dut.my_block.my_reg
55
+
56
+ =>
57
+ 0x10008000 - :my_reg
58
+ ===============================================================================================================
59
+ │ 15 │ 14 │ 13 │ 12 │ 11 │ 10 │ 9 │ 8 │
60
+ │ d[15:8] │
61
+ │ 0x0 │
62
+ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤
63
+ │ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │
64
+ │ d[7:0] │
65
+ │ 0x0 │
66
+ └─────────────┴─────────────┴─────────────┴─────────────┴─────────────┴─────────────┴─────────────┴─────────────┘
67
+
68
+ ~~~
69
+
70
+ However, this may not be what the simulation currently reflects. To see what the simulation holds, call `sync`
71
+ on the register:
72
+
73
+ ~~~text
74
+ dut.my_block.my_reg.sync
75
+
76
+ =>
77
+ 0x10008000 - :my_reg
78
+ ===============================================================================================================
79
+ │ 15 │ 14 │ 13 │ 12 │ 11 │ 10 │ 9 │ 8 │
80
+ │ d[15:8] │
81
+ │ 0x8E │
82
+ ├─────────────┼─────────────┼─────────────┼─────────────┼─────────────┼─────────────┼─────────────┼─────────────┤
83
+ │ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │
84
+ │ d[7:0] │
85
+ │ 0xFF │
86
+ └─────────────┴─────────────┴─────────────┴─────────────┴─────────────┴─────────────┴─────────────┴─────────────┘
87
+
88
+ ~~~
89
+
90
+ A convenience API exists for this by appending `!` to the register name:
91
+
92
+ ~~~text
93
+ dut.my_block.my_reg!
94
+ ~~~
95
+
96
+ Note that this works by firing off a conventional `read_register` request to your DUT model/controller.
97
+
98
+ That means that it should work for breakpoints in the majority of application code, however if you have stopped it
99
+ or stepped into a place in low-level code, such as in the middle of a prior transaction, then this feature may not work.
100
+
101
+ #### Advancing Time
102
+
103
+ If you have just written to a register, it may kick off some operation within the DUT and time (clock cycles)
104
+ will be required before you will be able to observe the response.
105
+
106
+ It is important to understand that the simulator is also paused during a breakpoint and therefore simulation time
107
+ is not continuing to run while you are at the console.
108
+
109
+ Simulation time can be advanced by calling the usual `tester.wait` API, however these convenience APIs exist for advancing
110
+ time during a debugger breakpoint (and they can also be used in source code if you wish):
111
+
112
+ ~~~ruby
113
+ 10.cycles
114
+
115
+ 10.ns!
116
+
117
+ 10.us!
118
+
119
+ 10.ms!
120
+
121
+ 10.s!
122
+ ~~~
123
+
124
+ Note that 10 is just used as an example here, you can apply any number that you want.
125
+
126
+
127
+ #### Checking The Error Count
128
+
129
+ You can query the current error count by running:
130
+
131
+ ~~~ruby
132
+ tester.simulator.error_count # => 0
133
+ ~~~
134
+
135
+ % end
@@ -0,0 +1,217 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ By convention, the OrigenSim simulator driver is configured within the file `environment/sim.rb`.
4
+
5
+ Usually the simulator configuration may be different for each DUT target, so often this file is structured like this
6
+ to enable a single Origen simulation environment setup file to support multiple DUT targets within the
7
+ application:
8
+
9
+ ~~~ruby
10
+ # environment/sim.rb
11
+
12
+ case Origen.target.name
13
+
14
+ when "my_dut1"
15
+ OrigenSim.cadence do |sim|
16
+ # Configuration of Cadence simulator to be used for DUT1 here
17
+ end
18
+
19
+ when "my_dut2"
20
+ OrigenSim.synopsys do |sim|
21
+ # Configuration of Synopsys simulator to be used for DUT2 here
22
+ end
23
+
24
+ else
25
+ Origen.log.error "No simulation environment has been setup for target #{Origen.target.name}, edit environment/sim.rb to add one."
26
+ exit 1
27
+ end
28
+ ~~~
29
+
30
+ #### Configuring The Simulator
31
+
32
+ Here is an example of configuring the simulator with some generic options that are supported by all simulators:
33
+
34
+ ~~~ruby
35
+ OrigenSim.cadence do |sim|
36
+ # By default a simulation will be given 60 seconds to startup, if it fails to start within this time the
37
+ # simulation will be abandoned and considered failed. If a particular simulation is known to be slow to start,
38
+ # the timeout can be extended as shown in this example (5 minutes):
39
+ sim.startup_timeout 5 * 60
40
+ # Sometimes due to different Verilog timescale references, the time specified by Origen may not align to what
41
+ # is seen in the simulation. For example, your Origen application might define a cycle period of 40ns but in
42
+ # the simulation this manifests as 400ns. Such differences can be fixed by specifying this time factor which
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
46
+ end
47
+ ~~~
48
+
49
+ Note that defining a configuration like this will also instantiate an instance of `OrigenSim::Tester` and assign it to
50
+ the global variable `tester`.
51
+ This `tester` object will behave like any other Origen tester driver and your application will be unaware that it is
52
+ driving a simulator rather than an ATE-specific pattern renderer.
53
+
54
+ Note also that the `post_process_run_cmd` option is available for all simulators, however it is reserved for discussion
55
+ later in this guide since it is more of an advanced topic.
56
+
57
+ #### Cadence (irun) Specific Configuration
58
+
59
+ Additionally, a Cadence simulator setup supports the following vendor-specific options:
60
+
61
+ ~~~ruby
62
+ OrigenSim.cadence do |sim|
63
+ # By default the simulation will be run by calling 'irun', this can be changed to anything you want, but it
64
+ # is usually a good idea to use this option to lock to a specific version of irun (the same version that was
65
+ # used to compile the DUT snapshot)
66
+ sim.irun '/tools/cadence/15.10.023/bin/irun'
67
+ # The default wave viewer is 'simvision', this can also be changed
68
+ sim.simvision '/tools/cadence/15.10.023/bin/simvision'
69
+ # The cadence simulator configuration does support the use of forces, though this is generally discouraged
70
+ sim.force {
71
+ 'origen.dut.vref_0v8' => 1,
72
+ 'origen.dut.pmc.some.internal.node' => 1,
73
+ }
74
+ # Custom probes can be specified, e.g. to include memory contents in the wave dump
75
+ sim.tcl_inputs %Q(
76
+ probe -create -shm origen.dut.mems.user -all -memories -variables -unpacked 262144 -depth all
77
+ probe -create -shm origen.dut.mems.cache -all -memories -variables -unpacked 262144 -depth all
78
+ )
79
+ end
80
+ ~~~
81
+
82
+ #### Synopsys Specific Configuration
83
+
84
+ Here are the vendor-specific options for Synopsys:
85
+
86
+ ~~~ruby
87
+ OrigenSim.cadence do |sim|
88
+ # By default the simulation will be run by calling 'vcs', this can be changed to anything you want, but it
89
+ # is usually a good idea to use this option to lock to a specific version of vcs (the same version that was
90
+ # used to compile the DUT snapshot)
91
+ sim.vcs "/tools/synopsys/L-2016.06/bin/vcs"
92
+ # The default wave viewer is 'dve', this can also be changed
93
+ sim.dve "/tools/synopsys/L-2016.06/bin/dve"
94
+ end
95
+ ~~~
96
+
97
+ Origen Sim also offers the option to use Verdi as a wave viewer instead of 'dve', the vendor-specific options for Synopsys w/Verdi would be:
98
+
99
+ ~~~ruby
100
+ OrigenSim.cadence do |sim|
101
+ sim.vcs "/tools/synopsys/L-2016.06/bin/vcs"
102
+ sim.verdi "/tools/synopsys/L-2016.06/bin/verdi"
103
+ end
104
+ ~~~
105
+
106
+ #### Icarus Verilog Specific Configuration
107
+
108
+ Here are the vendor-specific options for Icarus Verilog:
109
+
110
+ ~~~ruby
111
+ OrigenSim.cadence do |sim|
112
+ # By default the simulation will be run by calling 'vvp', this can be changed to anything you want, but it
113
+ # is usually a good idea to use this option to lock to a specific version of vvp (the same version that was
114
+ # used to compile the DUT snapshot)
115
+ sim.vvp "/tools/icarus/0.9.7/bin/vvp"
116
+ # The default wave viewer is 'gtkwave', this can also be changed
117
+ sim.gtkwave "/tools/gtkwave/3.3.66/bin/gtkwave"
118
+ end
119
+ ~~~
120
+
121
+ #### Generic and Advanced Simulator Configuration
122
+
123
+ A generic simulator configuration allows you to use a tool that is not supported out of the box by <code>OrigenSim</code>. For these, it
124
+ is your responsibility to provide the command to start the simulation process, however, this allows for arbitrary commands to
125
+ start the process and allows end users to still use <code>origen g</code> as if with a fully <code>OrigenSim</code> supported
126
+ simulator configuration.
127
+
128
+ An example of such a configuration could be:
129
+
130
+ ~~~ruby
131
+ OrigenSim.generic do |sim|
132
+ sim.generic_run_cmd do |s|
133
+ # Return the command to start the simulation
134
+ "path/to/custom/sim/script +socket+#{s.socket_id}"
135
+ end
136
+ end
137
+ ~~~
138
+
139
+ Here is an example using the predecessor of the supported Cadence tool <code>irun</code>, <code>ncsim</code>:
140
+
141
+ ~~~ruby
142
+ OrigenSim.generic do |sim|
143
+ sim.testbench_top 'na_origen'
144
+ sim.generic_run_cmd do |s|
145
+ "ncsim na_origen -loadpli origen.so:bootstrap +socket+#{s.socket_id}"
146
+ end
147
+ end
148
+ ~~~
149
+
150
+ The following commonly used options are available to a generic simulation configuration:
151
+
152
+ * `testbench_top` - Defines the testbench name if different from <code>origen</code>.
153
+ * `view_waveform_cmd` - Required for generic configurations - prints out this statement following a simulation instructing the
154
+ user on how to open the waveforms for viewing. For supported simulators, this is already provided, but can be overwritten.
155
+ * `generic_run_cmd` - Either a string, array to be joined by ' && ', or a block returning either of the aforementioned that
156
+ the generic configuration will use to launch the simulation.
157
+ * `post_process_run_cmd` - Block object to post-process the command that OrigenSim will launch the simulation with. This can be used
158
+ to post-process the command for any supported vendor. This block should return the command to run, as a string.
159
+
160
+ An example of the <code>post_process_run_cmd</code> usage is:
161
+
162
+ ~~~ruby
163
+ OrigenSim.cadence do |sim|
164
+ sim.post_process_run_cmd do |cmd, s|
165
+ # cmd is the current command that will be run. s is the simulator object, same as sim in this case.
166
+ # this should return either a string or an array to be joined by ' && ' (chain commands)
167
+ # note that we must RETURN the string. We cannot just edit it.
168
+
169
+ # add an environment variable and run setup script as an example
170
+ return "export PROJECT=my_rtl && source #{Origen.app.root.join('settings.sh')} && #{cmd}"
171
+
172
+ # or, we could return
173
+ return [
174
+ 'export PROJECT=my_rtl',
175
+ "source #{Origen.app.root.join('settings.sh')}",
176
+ cmd
177
+ ]
178
+ #=> "export PROJECT=my_rtl && source #{Origen.app.root.join('settings.sh')} && #{cmd}"
179
+ end
180
+ end
181
+ ~~~
182
+
183
+ #### Simulation Object Checkin/Checkout
184
+
185
+ Environment setups can also include information on the url and version of where the compiled simulation object
186
+ is to be stored - often this will not be checked into the same repository as the main application code since
187
+ for example Git, which is good for application code storage, is not really so good for storing large binaries
188
+ like the simulation objects.
189
+
190
+ Here is an example setup:
191
+
192
+ ~~~ruby
193
+ OrigenSim.synopsys do |sim|
194
+ sim.rc_dir_url 'sync://sync-12345:12345/Projects/origen_sim_snapshots'
195
+ sim.rc_version 'Trunk'
196
+ end
197
+ ~~~
198
+
199
+ The `rc_dir_url` option should point to a directory in the repository where the snapshot files should be
200
+ stored, not to the snapshot file itself.
201
+
202
+ The `rc_version` can be set to the version to use, which can be a pointer to latest like 'Trunk' or 'master' or
203
+ to an absolute version.
204
+
205
+ The object should be committed to the repository by running the `origen sim:ci` command with the environment/target
206
+ setup to select the object to be checked in.
207
+ Origen Sim will then automatically tar up the object and check it in.
208
+
209
+ This same command can be run again in future to check in new versions.
210
+
211
+ Origen Sim will then automatically check for the presence of the object in the local workspace and will fetch
212
+ it as required - i.e. if not present or if the `rc_version` has been updated.
213
+
214
+ Note that when a latest pointer is used as the version, the remote repository is not automatically checked for updates.
215
+ If you want to fetch the latest version or force a re-checkout at anytime you can run the `origen sim:co` command.
216
+
217
+ % end
@@ -0,0 +1,69 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ A flow, meaning a sequence of patterns, can be simulated in two ways - by supplying
4
+ a list of patterns or by configuring a test program generator flow to support simulation.
5
+
6
+ #### Simulating a Pattern List
7
+
8
+ If you were to run this:
9
+
10
+ ~~~text
11
+ origen g my_pat_1 my_pat_2 -e environment/sim.rb
12
+ ~~~
13
+
14
+ then it would run the two patterns as two independent simulations, creating two waveforms named after each pattern.
15
+
16
+ They can be combined into a single simulation by adding a `--flow` option:
17
+
18
+ ~~~text
19
+ origen g my_pat_1 my_pat_2 -e environment/sim.rb --flow my_flow
20
+ ~~~
21
+
22
+ This will simulate the given patterns back-back and dump them to a waveform named after the flow option, in this case "my_flow".
23
+
24
+ The list of patterns can also be supplied via a list file:
25
+
26
+
27
+ ~~~text
28
+ origen g list/regression.list -e environment/sim.rb --flow regression
29
+ ~~~
30
+
31
+ #### Simulating a Test Program Flow
32
+
33
+ To simulate a pattern sequence defined by a [test program flow](<%= path "guides/program/flows" %>), it is necessary
34
+ to [setup your interface](<%= path "guides/program/interface" %>) to support the simulation tester driver
35
+ as if it were another ATE.
36
+
37
+ The simulation tester driver has no concept of test methods, suites or instances, so its interface setup is very simple -
38
+ once you have the pattern name simply pass that to the `test` method:
39
+
40
+ ~~~ruby
41
+ # Example interface method
42
+ def func(name, options = {})
43
+ # Resolve the pattern name as required
44
+ pattern = extract_pattern_name(name, options)
45
+
46
+ if tester.sim?
47
+ test(pattern, options)
48
+
49
+ elsif tester.v93k?
50
+ t = test_suites.add(:vreg_func)
51
+ t.test_method = test_methods.origen.functional_test
52
+ t.pattern = pattern
53
+ test(t, options)
54
+
55
+ else
56
+ fail "The test program interface has not been setup for #{tester.class}!"
57
+ end
58
+ end
59
+ ~~~
60
+
61
+ To simulate the flow, run the program generator as normal but with the simulation environment selected:
62
+
63
+ ~~~text
64
+ origen p program/my_flow.rb -e environment/sim.rb
65
+ ~~~
66
+
67
+ The generated wave will be named after the flow, _my_flow_ in this example.
68
+
69
+ % end
@@ -0,0 +1,64 @@
1
+ % render "layouts/guides.html" do
2
+
3
+ Here are some technical details on how OrigenSim works which should provide some context when it comes
4
+ to [compiling your DUT design to work with OrigenSim](<%= path "guides/simulation/compiling" %>).
5
+
6
+ Origen provides components that can be compiled into a simulation object along with the design under test (DUT),
7
+ a high level view of the process looks like this:
8
+
9
+ <img src="https://user-images.githubusercontent.com/158364/28324051-6a149088-6bd2-11e7-936d-49ec87b2c0bb.png" alt="origen_sim" style="
10
+ width: 100%;
11
+ ">
12
+
13
+ The main Origen Ruby process is invoked by generating a pattern as usual, e.g. <code>origen g my_pattern</code>,
14
+ but with the environment setup to instantiate an instance of <code>OrigenSim::Tester</code> instead of say
15
+ <code>OrigenTesters::V93K</code>.
16
+ The OrigenSim tester will start off a Verilog process in parallel which will run a simulation on an object that
17
+ has been created beforehand. This simulation object contains the DUT wrapped in an OrigenSim testbench, and which
18
+ has been compiled into a snapshot/object that also includes a [Verilog VPI](https://en.wikipedia.org/wiki/Verilog_Procedural_Interface)
19
+ extension which provides a communication interface between Origen and the simulation world.
20
+
21
+ When the simulation process starts, the VPI extension immediately takes control and halts the simulator while it
22
+ listens for further instructions from a Linux socket which was setup by OrigenSim before the simulation was started.
23
+ As the Origen pattern generation process executes, the <code>OrigenSim::Tester</code> will translate any requests
24
+ to drive or expect pin values, or to generate a cycle, into messages which are passed into the Linux socket.
25
+ Upon receving these messages, the VPI process will manipulate the testbench's pin drivers to drive or read from
26
+ the DUT and it will advance time by a cycle period every time a cycle is generated in the pattern.
27
+ The testbench to wrap and instantiate the DUT is generated by OrigenSim and it provides a standard interface through
28
+ which Origen can access any DUT.
29
+
30
+ In principle the DUT object can be any design view that is wrapped by a conventional top-level Verilog module, meaning that
31
+ OrigenSim can be used to run RTL or gate-level simulations depending on what has been compiled into the snapshot.
32
+
33
+ **Note also that the DUT can be either an IP-block or an SoC, and so OrigenSim can be used equally well for running
34
+ both IP-level and top-level simulations.**
35
+
36
+ ### The Testbench
37
+
38
+ The testbench is quite simple and it does little more than instantiate the DUT module and connect all of its pins to
39
+ instances of [this pin driver module](https://github.com/Origen-SDK/origen_sim/blob/master/templates/rtl_v/origen.v.erb#L14).
40
+ The testbench module is named `origen` by default and all OrigenSim simulation dumps will have this same top-level structure:
41
+
42
+ ~~~text
43
+ .
44
+ └── my_pattern
45
+ └── origen
46
+ ├── debug // Contains an error count, pattern name and comments, and other debug aids
47
+ ├── dut // Your DUT
48
+ └── pins
49
+ ├── tdi // Driver for the TDI pin (for example)
50
+ ├── tdo
51
+ └── tck
52
+ ~~~
53
+
54
+
55
+ The driver contains a number of registers which are written to directly by the VPI process, allowing it to drive or expect a
56
+ given data value (stored in <code>origen.pins.MYPIN.data</code>) by writing a 1 to <code>origen.pins.MYPIN.drive</code>
57
+ or <code>origen.pins.MYPIN.compare</code> respectively.
58
+ If the value being driven by the pin does not match the expect data during a cycle, then an error signal will be asserted by the
59
+ driver and this will increment an error counter that lives in <code>origen.debug.errors[31:0]</code>.
60
+
61
+ An error count > 0 will result in the pattern simulation status being reported as a FAIL by Origen and this can be used
62
+ to create simulation-based regression test suites for your application.
63
+
64
+ % end