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.
- checksums.yaml +5 -5
- data/config/application.rb +17 -2
- data/config/shared_commands.rb +7 -0
- data/config/version.rb +1 -1
- data/ext/bridge.c +13 -3
- data/lib/origen_sim.rb +10 -0
- data/lib/origen_sim/artifacts.rb +101 -0
- data/lib/origen_sim/commands/build.rb +41 -9
- data/lib/origen_sim/heartbeat.rb +13 -1
- data/lib/origen_sim/origen_testers/api.rb +90 -7
- data/lib/origen_sim/simulation.rb +49 -4
- data/lib/origen_sim/simulator.rb +171 -19
- data/lib/origen_sim/stderr_reader.rb +19 -13
- data/lib/origen_sim/stdout_reader.rb +22 -16
- data/lib/origen_sim/tester.rb +110 -1
- data/lib/origen_sim_dev/dut.rb +5 -0
- data/pattern/test.rb +143 -0
- data/templates/empty.gtkw +19 -1
- data/templates/empty.rc +86 -0
- data/templates/empty.svcf +79 -9
- data/templates/empty.tcl +37 -9
- data/templates/origen_guides/simulation/app.md.erb +131 -0
- data/templates/origen_guides/simulation/artifacts.md.erb +115 -0
- data/templates/origen_guides/simulation/compiling.md.erb +190 -0
- data/templates/origen_guides/simulation/debugging.md.erb +135 -0
- data/templates/origen_guides/simulation/environment.md.erb +217 -0
- data/templates/origen_guides/simulation/flows.md.erb +69 -0
- data/templates/origen_guides/simulation/howitworks.md.erb +64 -0
- data/templates/origen_guides/simulation/introduction.md.erb +35 -0
- data/templates/origen_guides/simulation/log.md.erb +118 -0
- data/templates/origen_guides/simulation/patterns.md.erb +193 -0
- data/templates/probe.tcl.erb +3 -0
- data/templates/rtl_v/origen.v.erb +19 -3
- data/templates/web/layouts/_guides.html.erb +15 -0
- 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
|