% 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: ~~~ruby # A very basic, pre-defined .atp source for the J750 platform src = OrigenTesters::IGXLBasedTester.sample_direct_source # Decompile this source. pat = OrigenTesters.decompile_text(src, decompiler: OrigenTesters::IGXLBasedTester::Pattern) #=> OrigenTesters::IGXLBasedTester::Pattern object ~~~ Since we've specified that this is an `IGXLBasedTester` source, the `#decompile_text` method will use that as the target decompiler and return an object corresponding to that specific platform's decompiler: `OrigenTesters::IGXLBasedTester::Pattern`. If you have your own pattern source you'd rather compile, the `#decompile` method will accept a filename either as a `String` or `Pathname` object: ~~~ruby pat = OrigenTesters.decompile('path/to/src.atp') #=> (for a source ending with .atp) #=> OrigenTesters::IGXLBasedTester::Pattern object ~~~ Now, we can interact with our decompiled pattern. Some easy things we may want to do: * [Query which pins are present in the pattern source](#Discerning_Pattern_Source_Pins) * [Add those pins to the 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 ~~~ There's much more to vectors and vector types. [See the vectors section](<%= path "guides/decompilation/universalapi#Vector_Body_Elements" %>) for further details. #### Executing the Pattern Source Now that we've added any missing pins to our `dut` and we've seen how to access the vectors themselves, we can `execute` the pattern source. The `#execute` method will iterate through each vector, apply the pin states, and cycle the tester `repeat` number of times. ~~~ruby pat.execute ~~~ % end