% render "layouts/guides.html" do % # Test pattern that'll be used throughout these guides. % # Using the actual pattern object itself to get real return values when possible. % class OrigenDecompilerDocDut % include Origen::TopLevel % end % Origen.load_target('configurable', dut: OrigenDecompilerDocDut) % pat = OrigenTesters.decompile_text(OrigenTesters::IGXLBasedTester.sample_direct_source, decompiler: OrigenTesters::IGXLBasedTester::Pattern) Origen provides some basic functionality for decompiling, or reverse-compiling, a pattern from its text representation (e.g., `.atp` for the J750 platform), returning an object which Origen can work with. ### Philosophy The decompiler attempts to support two, somewhat competing, goals: 1. Provide a `universal API` for working with decompiled patterns from any platform. 2. Allow platforms to implement the `universal API` in such a way that still maintains the aspects only present on that particular platform (_platform-specifics_). The aim is to provide the best of both worlds: a generic-enough, `universal API` to accomplish most tasks, without regard to platform-specifics, but not bar those platform-specifics completely in the event that such a generic method either isn't available, isn't possible, or wouldn't be applicable across more than a single platform. ### Definitions In the context of the _decompilation_ sections, the following definition apply: * Pattern Source: The text-representation of the a pattern. * Platform: Producer of `Pattern Sources`. In most cases, this will be an ATE, such as `j750`, or `v93k`, but this also could be `STIL` or `WGL`. * Platform-Specifics: Any aspect which separates this platform from another, outside of the _actual_ parsing and grammar rules. * (Decompiled) Pattern: The instance of an object returned after successful decompilation of a `Pattern Source` by a `Decompiler`. * Note, this will often be written fully as `decompiled pattern`, to avoid additional confusion. * Decompiler: The object that takes a `Pattern Source` and returns a `Pattern`. There are two _flavors_ of this: * In some context, this will be the `generic Decompiler`, that is, the abstract base which, itself, can't actually decompile anything. * However, in most contexts this will refer to a specific platform. For example, _"the J750 decompiler"_, refers to the J750's implementation of the `generic decompiler`, or the `OrigenTesters::IGXLBasedTester::Pattern` class. ### Example Decompilation This example shows some basic usage of the decompiler, without assuming you have a pattern source for a supported platform ready to go. This example makes use of the `J750` platform. If you aren't familiar with this platform, don't worry; understanding of the pattern source format is not a requirement for _using_ the decompiler, specifically in the sense of the `universal API`. #### Requirements In order to follow along with these examples, you will need: * Some `dut` object that does not have the pins `tclk`, `tms`, `tdo`, or `tdi` already defined (you can still follow along, but you will not receive identical return values from `#add_pins` (covered later) if these pins are already defined). #### Decompiling Direct Source The first step to working with a pattern source in Origen is to decompile said source. The decompiler is accessed directly on the `OrigenTesters` module, and contains methods to decompile a source from a given input string. Consider the source, from a J750 `.atp`, below: ~~~ <%= OrigenTesters::IGXLBasedTester.sample_direct_source %> ~~~ Placing this in a `String`, we can decompile this directly using the the `#decompile_text` method and providing the target decompiler:
String
already:
OrigenTesters::IGXLBasedTester.sample_direct_source
DUT
](#Adding_Missing_Pins)
* [Iterate through the vectors, printing the repeat count and the pin states](#Vectors)
* [Execute the source in its entirety, in the context of the current DUT
](#Executing_the_Pattern_Source)
#### Discerning Pattern Source Pins
There's two methods available to retrieve the pins: `#pins` and `#pin_sizes`.
~~~ruby
# Return an array of pins, in the order they appear in the pattern
pat.pins
#=> <%= pat.pins %>
# Return the pin names and their respective size
pat.pin_sizes
#=> <%= pat.pin_sizes %>
~~~
#### Adding Missing Pins
One of the most common operations with respect to the pins is to simply add any
missing pins to the current `dut`. The decompiled pattern has a built-in method
to do just that:
~~~ruby
# Assume the current dut has no pins
dut.pins
#=> <%= dut.pins %>
pat.add_pins
#=> <%= pat.add_pins %>
dut.pins
#=> <%= dut.pins %>
~~~
`#add_pins` will return any pins it added to the `dut`. For example, if the `dut`
already had all the pins from the pattern defined, `#add_pins` would've returned
`an empty array`. Running the above a second time:
~~~ruby
# Assume the current dut has no pins
dut.pins
#=> <%= dut.pins %>
pat.add_pins
#=> <%= pat.add_pins %>
dut.pins
#=> <%= dut.pins %>
~~~
#### Vectors
We can iterate through each _'vector'_ in the decompiled pattern with `#each_vector`.
This method takes a block and runs it for each _'vector'_ encountered. Notice the
quotes around _'vector'_. Each `v` in the example above is actually a `VectorBodyElement` object
that acts as a placeholder for any `element type` that could appear.
Each `vector body element` has a `type` associated with it to discern exactly
what it is:
~~~ruby
pat.each_vector { |v| puts v.type }
% # Use the collect method to return an actual array that'll render in the docs.
<%= pat.collect { |v| ":#{v.type}" }.join("\n") %>
#=> nil
~~~
Now that we have the `type`, we can access the underlying `element`.
In the example below, we'll check the `type` first and, in the event of a `:vector`,
access the underlying `element` and print its repeat count and pin states.
~~~ruby
pat.each_vector { |v| puts "(#{v.element.repeat}) #{v.element.pin_states}" if v.type == :vector }
% # Use the collect method to return an actual array that'll render in the docs.
<%= pat.select { |v| v if v.type == :vector }.map { |v| "(#{v.element.repeat}) #{v.element.pin_states}" } .join("\n") %>
#=> nil
~~~
#each_vector
returns nil
, NOT an
array containing all the vectors like a normal `each` method would do.
See the section on working with vectors
for why this is the case.