• Guides
  • Videos
  • Publications
  • API
  • Github
  • Community
  • Release Notes
  • Plugins
Installing Origen
  • Introduction
  • How to Install
  • How to Install (Windows)
  • Company Customization
  • Understanding Gems
  • Invoking Considerations
  • Workspace Management
Getting Started with Origen
  • Core concepts
  • Creating a New App
  • Directory Structure
  • The Initial Commit
  • Creating New Files
  • Understanding Blocks
  • Application Architecture
Runtime Environment
  • Introduction
  • Mode
  • Environment
  • Target
  • Production Targets
  • Global Setup
  • Load Order
  • Programming
Models
  • Introduction
  • Naming
  • Definition & Hierarchy
  • Adding Attributes
  • Versioning
  • Bugs & Features
  • Package, Mode & Configuration
  • Registers
  • Pins
  • Power Domains
  • Hardware Attributes
  • Parameters
  • Specifications
  • Fuses
  • Generic Components
  • Creating Your Own Components
Compiler (Views)
  • Introduction
  • Creating Templates
  • Using Sub-Templates
  • Helpers
  • Running The Compiler
  • Inline Compiler
Controllers
  • Introduction
  • Shadow Controllers
  • Direct Controllers
Pattern Generator
  • Introduction
  • Creating Patterns
  • Pins
  • Timing and Waiting
  • Registers
  • Documenting Patterns
  • Generating by Name
  • Common API
  • J750 API
  • V93K API
  • UltraFlex API
  • STIL & Other Formats
  • Custom Testers
  • Running The PatGen
  • Concurrent Patterns
Test Program Generator
  • Introduction
  • Philosophy
  • Creating Flows
  • Managing Flow Control
  • Creating an Interface
  • Additional Resources
  • Dynamic Custom Code
  • Characterization API
  • J750 API
  • V93K Common API
  • V93K SMT7 API
  • V93K SMT8 API
  • UltraFLEX API
  • Documenting the Program
  • Creating Custom Testers
  • Running the ProgGen
Decompilation
  • Overview & Example
  • Decompiling, Adding Pins, & Executing
  • Working with Decompiled Patterns
  • Platform Specifics
Simulation
  • Introduction
  • How It Works
  • Compiling the DUT
  • AMS Support
  • Environment Setup
  • Application Setup
  • Simulating Patterns
  • Simulating Flows
  • Direct DUT Manipulation
  • Simulator Log Output
  • Artifacts
  • Debugging
Documentation Generator
  • Introduction
  • Markdown
  • Linking
  • Styling
  • Testing
  • API Generation
  • Deploying
Plugins
  • Introduction
  • Using a Plugin
  • Creating a Plugin
  • Current & Default Plugins
  • Dev Environment
  • Dev Considerations
  • Paths & Origen.root
  • Config & Origen.app
Miscellaneous
  • Revision Control
  • Origen Remotes
  • Lint Testing
  • Session Store
  • LSF API
  • Users, Emails & Maillists
  • Utilities & Helpers
  • Ruby Extensions
  • Logger
  • Adding Commands
  • Overriding Commands
  • Callbacks
  • Application Callbacks
  • Miscellaneous Topics
Advanced Topics
  • Introduction
  • Invocation Customization
  • Custom App Generators

Test Program Generator

V93K Common API


Interface Considerations

Be sure to read and understand the guide to Creating an Interface before reading this section. This guide will describe the API to generate V93K/SmarTest test program components from within an interface file.

To re-cap this is the shell required to implement an interface:

# lib/vreg/interface.rb
module Vreg
  class Interface
    include OrigenTesters::ProgramGenerators

    # An example method that can be called from your test flow to generate a functional test
    def func(name, options={})
      # If your interface supports multiple platforms, add conditional logic like this, if you
      # only ever want to support one platform then you don't need this
      if tester.j750?
        # Functional test implementation for J750
      elsif tester.v93k?
        # Functional test implementation for V93K
      end
    end

  end
end

The OrigenTesters::ProgramGenerators will provide the interface with access to all of the platform generator APIs for the platforms that it supports.

If your interface supports multiple platforms then add conditional logic to separate them as shown above.

Creating a Test Suite

Most of the effort in generating a V93K test program is in generating the test suites and their associated test methods.

A new test suite and test method can be instantiated and linked together like this:

t = test_suites.add(:vreg_func)
t.test_method = test_methods.origen.functional_test

These lines of code do the following things:

  • Instantiates a new test suite object and assigns it to the local variable t
  • Sets its name to ‘vreg_func’ and inserts it into the flow file (but not into the actual test flow)
  • Instantiates a new functional test method object and attaches it to the test suite
  • Inserts the test method into the flow file (but not into the actual test flow)

You will of course want to then decorate your new test with attributes that are specific to your application, here for example to set the levels and timing:

t.tim_equ_set = 15
t.tim_spec_set = 1
t.timset = 1
t.lev_equ_set = 20
t.lev_spec_set = 8
t.levset = 1

or to assign a spec in SMT8:

t.spec = 'my_spec_min'

The default namespace and folder paths are determined by your environment with tester.package_namespace and tester.spec_path/tester.seq_path respectively. If you need to override these values for specific test suites you have the following available:

# Overrides spec namespace and folder path
t.spec_namespace
t.spec_path
# Overrides sequence and pattern namespace
t.seq_namespace
# Overrides sequence folder path
t.seq_path

If the test method provides parameters, you can set them in the same way. As a convenience, Origen will automatically work out whether the reference is to a parameter of the test suite or of the test method, and will assign it accordingly. For example, let’s say this functional test method had a parameter named checkShutdown, you could set that like this:

t.check_shutdown = 1   # By Ruby convention, use the lower-cased underscored version of the C++ name

# The above is a shorthand equivalent to:
t.test_method.check_shutdown = 1

Attributes can also be passed in when instantiating the new test suite/method, this is equivalent if you prefer:

t = test_suites.add(:vreg_func, tim_equ_set: 15, tim_spec_set: 1, timset: 1, lev_equ_set: 20)
t.test_method = test_methods.origen.functional_test(check_shutdown: 1)

Limits

The limits can be set for all test objects using the following API, see here for some examples of the available unit helpers:

t.lo_limit = 100.uA
t.hi_limit = 150.uA

Custom Test Methods

An API exists to define the naming and parameter signature of test methods provided by a 3rd party library, enabling them to be used within an interface exactly like in the examples above. Additionally, it is possible to define helper methods that are associated with each test method, making them easier to use within an Origen test program interface.

This is best shown by example, here is how to define a custom test method library and a custom test method within an Origen interface:

# lib/vreg/interface.rb
module Vreg
  class Interface
    include OrigenTesters::ProgramGenerators

    def initialize(options={})
      add_my_tml if tester.v93k?
    end

    # Define the test methods from a custom V93K library
    def add_my_tml
      # The identifier you give here is what you will use to access the test methods from your interface
      # code, for example: test_methods.my_tml.my_test
      #
      # This will also be the C++ namespace that is used within SMT to access the test method classes
      # defined in this library.
      add_tml :my_tml,
        # [OPTIONAL] If you need the C++ namespace to be different to the above identifier then you can
        # specify the C++ name like this:
        class_name:      'MyTmlNamespace',

        # Here is a test definition.
        # The identifier should be lower-cased and underscored, in-keeping with Ruby naming conventions.
        # By default the class name will be the camel-cased version of this identifier, so 'myTest' in
        # this case.
        my_test: {
          # [OPTIONAL] The C++ test method class name can be overridden from the default like this:
          class_name:   'MyTestClass',
          # [OPTIONAL] If the test method does not require a definition in the testmethodlimits section
          #    of the .tf file, you can suppress like this:
          render_limits_in_file: false,
          # Parameters can be defined with an underscored symbol as the name, this can be used
          # if the C++ implementation follows the standard V93K convention of calling the attribute
          # the camel cased version, starting with a lower-cased letter, i.e. 'testerState' in this
          # first example.
          # The attribute definition has two required parameters, the type and the default value.
          # The type can be :string, :current, :voltage, :time, :frequency, integer, :double or :boolean
          pin_list: [:string, ''],
          samples: [:integer, 1],
          precharge_voltage: [:voltage, 0],
          settling_time: [:time, 0],
          # An optional parameter that sets the limits name in the 'testmethodlimits' section
          # of the generated .tf file.  Defaults to 'Functional' if not provided.
          test_name: [:string, 'SpecSearch']
          # An optional 3rd parameter can be supplied to provide an array of allowed values. If supplied,
          # Origen will raise an error upon an attempt to set it to an unlisted value.
          tester_state: [:string, 'CONNECTED', %w(CONNECTED UNCHANGED DISCONNECTED)],
          force_mode: [:string, 'VOLT', %w(VOLT CURR)],
          # The name of another parameter can be supplied as the type argument, meaning that the type
          # here will be either :current or :voltage depending on the value of :force_mode
          force_value: [:force_mode, 3800.mV],
          # In cases where the C++ library has deviated from standard attribute naming conventions
          # (camel-cased with lower cased first character), the absolute attribute name can be given
          # as a string.
          # The Origen accessor for these will be the underscored version, with '.' characters
          # converted to underscores e.g. tm.an_unusual_name
          'An.UnusualName' => [:string, 'NO', %w(NO YES)],
          # Attribute aliases can be defined like this:
          aliases: {
            my_name: 'An.UnusualName',
            precharge: :precharge_voltage,
          },
          # Define any methods you want the test method to have
          methods: {
            # If you define a method called 'finalize', it will be called automatically before the test
            # method is finally rendered, making it a good place to do any last minute attribute
            # manipulation based on the final values that have been set by the user.
            # The test method object itself will be passed in as an argument.
            #
            # In this example it will set the pre-charge if it has not already been set and a voltage is
            # being forced above a given threshold.
            finalize: -> (tm) {
              if tm.force_mode == 'VOLT' && tm.precharge_voltage == 0 && tm.force_value > 3.5.V
                # Set the pre-charge level to 1V below the force value
                tm.precharge_voltage = tm.force_value - 1.V
              end
            },
            # Example of a custom helper method, here to provide a single method to force a current and
            # which will configure multiple test method attributes.
            force_current: -> (tm, value) {
              tm.force_mode = 'CURR'
              tm.force_value = value
            },
          }
        },
        
        my_other_test: {
          # Define another test in exactly the same way...
        }
    end
  end
end

Here is an example of how the above definition might be used with test program interface logic:

# An example method that can be called from your test flow to generate a DC measurement test like this:
#
#   measure :vreg, force: 10.uA, lo_limit: 1.25, hi_limit: 1.75
#
#   measure :iref, force: 1.2.V, lo_limit: 20.uA, hi_limit: 30.uA, type: :current
def measure(name, options={})
  t = test_suites.add(name, options)
  t.test_method = test_methods.my_tml.my_test(pin_list: '@')
  if options[:type] == :current
    # Force mode is 'VOLT' by default per the above definition
    t.force_value = options[:force]
  else
    # Here calling the helper method to configure the method for force current mode
    t.force_current(options[:force])
  end
end

Distribute as a Plugin

Commonly, a custom test method library will not be specific to any one test program application and it will be used by many test programs within a group or company. In such a case, you don’t want to have the Origen definition of the given library be duplicated in all of your applications. Rather, it is preferable to develop and maintain the definition in a central place and then include it in all of the applications that wish to use the library.

This can be easily achieved by wrapping the Origen definition in an Origen plugin.

Here is an example of how to package a library definition for inclusion in a plugin:

# lib/my_library.rb within the my_library plugin
module MyLibrary
  # Define the test methods from a custom V93K library
  def add_my_library
    # The definition here is identical to the original example above
    add_tml :my_tml,
      # [OPTIONAL] If you need the C++ namespace to be different to the above identifier then you can
      # specify the C++ name like this:
      class_name:      'MyTmlNamespace',

      # Here is a test definition.
      # The identifier should be lower-cased and underscored, in-keeping with Ruby naming conventions.
      # By default the class name will be the camel-cased version of this identifier, so 'myTest' in
      # this case.
      my_test: {

      # ...

    end
  end

  # [OPTIONAL] You can also supply complete interface method definitions which use this library
  # An example method that can be called from your test flow to generate a DC measurement test like this:
  #
  #   measure :vreg, force: 10.uA, lo_limit: 1.25, hi_limit: 1.75
  #
  #   measure :iref, force: 1.2.V, lo_limit: 20.uA, hi_limit: 30.uA, type: :current
  def measure(name, options={})
    t = test_suites.add(name, options)
    t.test_method = test_methods.my_tml.my_test(pin_list: '@')
    if options[:type] == :current
      # Force mode is 'VOLT' by default per the above definition
      t.force_value = options[:force]
    else
      # Here calling the helper method to configure the method for force current mode
      t.force_current(options[:force])
    end
  end
end

Then simply add the plugin to a given application, and it can be used within an interface like this:

module MyApp
  class Interface
    include OrigenTesters::ProgramGenerators
    include MyLibrary

    def initialize(options={})
      add_my_library
    end

    # You don't need to do anything here, and your flow will already support the measure method!
    
    # Some application-specific flow method that uses the library:
    def some_test(name, options = {})
      t = test_suites.add(name, options)
      t.test_method = test_methods.my_tml.my_other_test
      t.some_parameter = #...
    end
  end
end

For a more advanced integration which gets rid of the need to even call add_my_library, you can refer to how the origen_std_lib interface integration works here.


Comments

Generated with the Origen Semiconductor Developer's Kit

Origen is released under the terms of the MIT license