origen_sim 0.12.0 → 0.13.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.
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