% render "layouts/guides.html" do
Patterns are simulated by simply generating the pattern with
a [simulation environment](<%= path "guides/simulation/environment" %>)
selected:
~~~text
origen g my_pattern -e environment/sim.rb
~~~
Most of the [common pattern API](<%= path "guides/pattern/common" %>) is supported
by OrigenSim and therefore you should expect to find the simulation environment
a drop-in replacement for your conventional ATE environment driver.
If you come across an API that OrigenSim does not support but you think that
it should, please raise a ticket here describing what you
tried to do .
#### Waiting For Events
When your pattern invokes some DUT action and you need to wait for it to complete, you
normally have two options:
* Calculate how long it should take and wait for a fixed delay
* Implement a match loop to dynamically wait for an expected response to occur
Both of these are fully supported by OrigenSim, see the
[Timing and Waiting guide](<%= path "guides/pattern/timing" %>) for more information on these APIs.
However, if your pattern generation flow is going to be supported by simulation, then you also have
a third option - to derive the required wait time from the simulation itself.
OrigenSim makes this very easy via the following API:
~~~ruby
cc "Wait for the program command to complete"
tester.sim_delay :program_command do
dut.pin(:done).assert!(1)
end
dut.pin(:done).dont_care # Any pin assertions/reads created within the block will persist beyond it, so
# remember to clear any assertions that you don't want to carryover afterwards
~~~
The `sim_delay` method provides the convenience of a match loop for the purposes of
delay calculation but will still generate a static pattern for the ATE. It will automatically calculate how
long the given block takes to pass and then insert that delay when later generating the pattern for an ATE.
An ID must be given to each delay, `:program_command` in this example, and if the same ID is used in multiple
calls to `sim_delay` then it means that the same delay will be used for each occurrence.
When simulating a pattern that contains `sim_delay` block(s) for the first time, the delay will
be calculated from the simulation and stored in an Org file (Origen native pattern format) within your
application's pattern directory. These files should be committed to your revision control system and considered
as part of your application.
The next time that you simulate it, the previously calculated delay will be inserted into the
pattern and therefore the simulation will be verifying that the delay is correct.
If you want to re-calculate the delays during a simulation then run with the `--sim_capture` switch:
~~~text
origen g my_pattern -e environment/sim.rb --sim_capture
~~~
Additional padding can be added to the calculated delay like this (all the usual `time_in_us:` style
of time options are supported):
~~~ruby
tester.sim_delay :program_command, padding: { time_in_cycles: 10 } do
dut.pin(:done).assert!(1)
end
dut.pin(:done).dont_care # Any pin assertions/reads created within the block will persist beyond it, so
# remember to clear any assertions that you don't want to carryover afterwards
~~~
By default, the block will be evaluated constantly until it passes when calculating the delay from
the simulation.
If the time is long and this is making your simulation run too slow, you can use lower resolution
by supplying a `:resolution` option, either as a number of cycles:
~~~ruby
tester.sim_delay :program_command, resolution: 10 do
dut.pin(:done).assert!(1)
end
dut.pin(:done).dont_care # Any pin assertions/reads created within the block will persist beyond it, so
# remember to clear any assertions that you don't want to carryover afterwards
~~~
or by supplying a hash filled with the usual time options:
~~~ruby
tester.sim_delay :program_command, resolution: { time_in_ns: 50 } do
dut.pin(:done).assert!(1)
end
dut.pin(:done).dont_care # Any pin assertions/reads created within the block will persist beyond it, so
# remember to clear any assertions that you don't want to carryover afterwards
~~~
#### Capturing Responses from the Simulation
Sometimes the response from your DUT maybe hard to predict and/or complicated to model in Origen, think about a digital data
stream response from a pin when testing a communications protocol.
OrigenSim provides an API for such a case which allows pin output values for a subset of pins/vectors
to be sampled during a simulation. The response is then captured and converted into the corresponding
expect data when the same pattern is later generated for the ATE.
Capturing is really easy, just wrap the operation you want to capture in your pattern source code like this:
~~~ruby
tester.sim_capture :cmd55, :dout, :test_bus, :tdo do
dut.pins(:din_port).drive!(0x1234_5678)
dut.cmd.write!(0x55)
60.cycles
end
~~~
The first argument is an ID for the capture, this can be anything but the user must assign it.
Then supply a list of pin/pin_group IDs (or pin objects) that you want to capture.
If you use the same ID more than once it means that the same captured data will be used in multiple places.
When you add this to the pattern an error will be raised if you try to generate an ATE pattern, this will
advise that the data has not been captured yet and it must be run in a simulation first.
When you run it in a simulation for the first time, the data will be captured and stored to your application
in the `pattern/sim_capture` directory. These files should be checked into your application as if they were regular patterns.
On subsequent simulation runs, the data will not be captured but instead will be re-played from the simulation
- i.e. the pattern will assert that the DUT output matches what is in the capture file.
In other words, by adding this and then simulating twice using the same command, you are both capturing and
then verifying the captured data.
Add this switch to update the captures during a subsequent simulation run:
~~~text
origen g my_pattern --sim_capture
~~~
To use the captured data in an ATE pattern, simply switch to an ATE target and generate as normal.
A known limitation of this feature is that the pin state data is currently captured at the end of a cycle, not
at the point during the cycle where it will be read by the pattern.
However, if this were to be a problem in a particular application, you would see it fail when re-playing the
captured data in simulation.
#### Configuring the Capture Storage Location
By default, both `sim_delay` and `sim_capture` will save their captured data to
Org files (Origen native pattern format) using the following file naming rule:
`Origen.root/pattern/org//.org`.
If your application is a top-level application then the default setting should work fine unless you wish
to share/re-use captured data between multiple targets.
Another reason to change from the default would be if data is captured at plugin-level and this needs
to be referenced later when running within a top-level application.
There are potentially two issues in that case:
* `Origen.root` will point to the top-level application's root instead of the plugin's
* The target name used at the top-level could be different from the one that was used within the plugin to capture
the data
In such cases, the default capture directory can be changed by setting the `OrigenSim.capture_dir` attribute.
This can be set anytime before the first call is made to `sim_delay` or `sim_capture`.
For example, a plugin that needs its captured data to work later as part of a top-level application,
could set the capture directory in a [startup callback](<%= path "guides/misc/callbacks/#startup(options)" %>),
like this:
~~~ruby
def startup(options)
# Only modify this if we are the current app or plugin
if Origen.app!.current? || Origen.app!.current_plugin?
# Use a directory within our root and named after the current IP block, rather than the target
OrigenSim.capture_dir = Origen.root!.join('pattern', 'org', dut.myip.name)
end
end
~~~
#### Creating Simulation-Only Assertions
Users are of course encouraged to write patterns that test the DUT via its pin interface since such
patterns will work in physical environments like the ATE.
However, it can be useful to supplement your patterns with simulation-only assertions which peek inside
the DUT to check that it is behaving as expected. Such assertions can report useful failure information
back to the user which may help when debugging a failed pattern simulation.
~~~ruby
# This code must be skipped when the pattern is generating for an ATE target environment
if tester.sim?
value = tester.simulator.peek("origen.dut.path.to.net").to_i[7..4]
if value != 0xA
OrigenSim.error "The internal node was #{value.to_hex} instead of 0xA!"
end
end
~~~
Note the use of `OrigenSim.error` to report the error message, this will cause the simulation result
to be reported as a FAIL, even if all pin level assertions otherwise pass.
Also note that the value returned from the `peek` method is converted into an integer. This is because
`peek` returns an instance of [Origen::Value](<%= path "api/Origen/Value.html" %>) which can also handle
`X` or `Z` values.
So for example, if you actually wanted a given bit to be `Z` you could write your assertion as:
~~~ruby
unless tester.simulator.peek("origen.dut.path.to.net")[4].z?
OrigenSim.error "Bit 4 of some net was not in hi-Z mode!"
end
~~~
It is also possible to force nets within the DUT via a corresponding `poke` method:
~~~ruby
if tester.sim?
test.simulator.poke "path.to.some.net[15:8]", 0x51
end
~~~
% end