• 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

Managing Flow Control


The runtime flow control of a test program is an area that can be particularly messy:

  • Need to deal with different and often obscure vendor APIs
  • It can be very hard to decipher both the intention and the actual behavior during code reviews
  • It is easy to make mistakes
  • Mistakes can be costly - there have been many customer quality incidents in the past from missed test caused by errors in flow control

To deal with these problems Origen provides a simple and intuitive API to describe runtime flow logic:

  • Generates legal and battle-tested code
  • Takes care of cross-platform implementation
  • Makes flow control easy to review
  • Covers over gaps or weaknesses in the vendor APIs

Conditional tests fall into two categories:

  • Those that will run based on the flow execution environment. For example based on the job selected at runtime or on some enable flag that can be set by the user at runtime.
  • Those that will only run based on the outcome of another test - i.e. execute a given test based on whether a previous test passed, failed or ran at all.

Execution Based on the Runtime Environment

The following methods are available to describe these cases:

  • if_enable / unless_enable - Run the test if a flow runtime option is/is not enabled at runtime
  • if_job / unless_job - Run based on the current job (P1, FR, QC, etc)

Here are some examples of how to apply these methods to single tests:

# Run this test to characterize the vreg, only if the 'vreg_cz' flag has been enabled
para :vreg_meas, softbin: 107, cz: true, if_enable: "vreg_cz"
# Apply HVST to the vreg module, unless the 'skip_hvst' flag has been enabled
func :vreg_hvst, softbin: 101, hv: 10.V, vdd: :max, unless_enable: "skip_hvst"
# Run this test only at cold
para :vreg_meas, softbin: 105, lo: 1.12, hi: 1.34V, if_job: "FC"

The use of if/unless_enable will make use of flow enable words on Teradyne platforms and user flow variables on Advantest. The if/unless_job control will make use of the job column on Teradyne platforms and a user flow variable named @JOB on Advantest.

Both of these controls support a block form, which allows it to be applied to a group of test and, in the case of enable words, it also provides a way to implement AND and OR logic:

# OR - Run these tests if either word is set
if_enable [:word1, :word2] do
  func: :test1
  func: :test2
end

# AND - Run these tests if both words are set
if_enable :word1 do
  if_enable :word2 do
    func: :test1
    func: :test2
  end
end

Execution Based on Relational Expressions

The following methods are available to describe these cases:

  • whenever - Run the test(s) if the relational expression evaluates to TRUE
  • whenever_all - Run the test(s) if ALL of the relational expressions evaluate to TRUE
  • whenever_any - Run the test(s) if ANY of the relational expressions evaluate to TRUE

The following relational operators are available for use with the above methods:

  • eq - equal to
  • ne - not equal to
  • gt - greater than
  • ge - greater than or equal to
  • lt - less than
  • le - less than or equal to

Here are some examples of how to apply these methods:

# Run these tests if VAR1 is greater than 2
whenever gt(:var1, 2) do
  func: :test1
  func: :test2
end

# Run these tests if VAR1 is greater than 2 AND VAR2 is less than VAR3
whenever_all gt(:var1, 2), lt(:var2, :var3) do
  func: :test1
  func: :test2
end

# Run these tests if VAR1 is greater than 2 OR VAR2 is less than VAR3
whenever_any gt(:var1, 2), lt(:var2, :var3) do
  func: :test1
  func: :test2
end

Additionally, these variables can be set in the flow using the set method as shown in here:

# Set the VAR1 = 1
set :var1, 1
set :var2, 'OFF'
set :var3, 3.14

# Update VAR1 value based on some runtime condition
if_enable :some_other_variable do
  set :var1, 3
end

# Run these tests if VAR1 is greater than 2
whenever gt(:var1, 2) do
  func: :test1
  func: :test2
end

Execution Based on a Previous Test

The following methods are available to describe these cases:

  • if_ran / unless_ran - Run only if a previous test did or did not run
  • if_failed (unless_passed) - Run only if a previous test failed
  • if_passed (unless_failed) - Run only if a previous test passed

All of these methods require you to provide the ID of the previous test on which the conditional execution will depend. This ID must be assigned by you in the flow line of the previous test by adding an :id key, like this:

para :vreg_meas, softbin: 105, lo: 1.12, hi: 1.34, id: :vreg_meas_1

The ID can be any value you like as long as it is unique, Origen will raise an error if any duplicate IDs are encountered.

On the dependent tests the API is similar to the previous examples except the ID of the previous test is given in place of the enable flag or job name. Here are some examples:

para :vreg_meas, softbin: 105, lo: 1.12, hi: 1.34, id: :vreg_meas_1
# Automatically characterize the vreg if the measurement fails
para :vreg_meas, softbin: 107, cz: true, if_failed: :vreg_meas_1
# Then bin out
bin 3, softbin: 105, if_failed: :vreg_meas_1
# Check if the HVST has already been run on this device
func :rd_vreg_hvst_passcode, softbin: 50, vdd: :nom, id: :vreg_hvst_done
# If not run it
func :vreg_hvst, softbin: 101, hv: 10.V, vdd: :max, unless_passed: :vreg_hvst_done
# And program the flag for next time
func :pgm_vreg_hvst_passcode, softbin: 51, vdd: :nom, unless_passed: :vreg_hvst_done

Origen automatically takes care of setting up all of the tests in the relationship:

  • The parent tests in the relationship are automatically set to continue on fail
  • Flag(s) will be set to indicate whether the parent test passed or failed
  • Conditional execution flags are set on all dependent tests

AND and OR conditions can be created by using if_any/all_failed/passed variations as follows:

func :test1, id: :t1
func :test2, id: :t2

# OR logic - This test will run if either of the referenced tests fail
func :test3, if_any_failed: [:t1, :t2]

# AND logic - This test will only run if both of the referenced tests fail
func :test4, if_all_passed: [:t1, :t2]

# Block forms are available as with all condition APIs
if_any_passed [:t1, :t2] do
  #...
end

References to External Tests

It is possible to generate conditional relationships between tests that span across different flow modules, in that case the test ID must be appended with :extern_. This will indicate to Origen that the reference is external and will prevent an error being raised for the ID not being found within the current flow.

Here is an example:

# program/flow_1.rb
Flow.create do
  # This ID can only be referenced within this flow
  func :test1, id: :t1
  # This ID can be referenced outside of this flow
  func :test2 id: :extern_t2
end

# program/flow_2.rb
Flow.create do
  # This will generate an undefined ID error
  func :test3, if_failed: :t1
  # But this will work, since the ID's name indicates that it is an intentional external reference
  func :test4, if_failed: :extern_t2
end

Applying Conditions to Sub-Flows

All of the flow control methods have a block form which will apply the condition to all tests within the block.

A very useful pattern is to split your code into small re-usable snippets and then wrap the import with these flow control methods to apply conditional execution. For example, here the ‘FH’ job requirement will be applied to all tests imported from the vreg component:

# Only run the vreg tests at hot
if_job "FH" do
  import "components/vreg"
end

Conditions Applied to Groups

Groups can also be used to implement AND/OR logic, here is an example of how you might implement a speed binning flow:

group "200Mhz", id: :spec200 do
  func :test1_200
  func :test2_200
end

# Bin out to bin 1 if passed at 200 Mhz, here if_passed will apply to all tests in the group
pass 1, if_passed: :spec200

group "100Mhz", id: :spec100 do
  func :test1_100
  func :test2_100
end

# Bin out to bin 2 if passed at 100 Mhz, here if_passed will apply to all tests in the group
pass 2, if_passed: :spec100

# Otherwise we have failed
bin 3

Manually Setting and Referencing Flags

It may be sometimes be necessary to react on a flag that is controlled by a 3rd party and which will be passed into an Origen-based test block, or to set a flag which a 3rd party test block will later reference.

An API exists to manually set and react to flags in these situations:

log "Example of manual flag setting upon pass or fail"
test :test1, on_pass: { set_flag: :my_pass_flag }, on_fail: { set_flag: :my_fail_flag }, continue: true

# Execute only if the above pass flag was set
test :test2, if_flag: :my_pass_flag

# Execute only if the above pass flag was not set
unless_flag :my_pass_flag do
  test :test3
end

log "Example of manually unsetting flag"
test :test4, on_pass: { unset_flag :my_custom_flag1 }

Note that flag names will usually be forced to uppercase, this is to institute a convention that flags/flow variables are always uppercased in order to avoid any test program bugs from incorrectly referencing a given flag due to case sensitivity.

However, if you need to reference a flag from a 3rd party test module that does not follow this convention, then a literal flag can be supplied by prefixing it with $ as shown below:

test :test1, on_fail: { set_flag: :$My_Mixed_Flag }, continue: true
test :test2, if_flag: "$My_Mixed_Flag"
unless_flag "$My_Mixed_Flag" do
  test :test3
end

test :extra_test, if_enable: :$MCEn_extras
unless_enable "$MCEn_test" do
  test :test1
  test :test2
end

For custom environment libraries, there might be a need to reference a flag without using the native flag API. add_flag will allow the flow and sub-flow to have access to the flag without adding to the flow.

log "Example of manually adding a flag to a flow without calling the flag"
add_flag :my_custom_flag2

In all cases the $ will be removed from the final flag name that appears in the test program.

Whenever you set a flag or automation initializes a variable, you can remove the variable from initialization flow by labeling as a global flag with the add_global_flag API. The below example will set the global variable in the flow but not initialize it to a value. non_global will behave as normal.

add_global_flag :global
test :global_test1, on_fail: { set_flag: :$non_global }, continue: true
unless_flag "$global" do
  set_flag '$non_global'
end
if_flag "$non_global" do
  set_flag '$global'
end

Adding the V93K bypass option:

Add the flow bypass option:

Flow.create interface: 'My::Interface', flow_bypass: true do
  test :test1
end

Flow.create interface: 'My::Interface' do
  flow.flow_bypass = true
  test :test1
end

Add group bypass option:

group :my_group, bypass: true do
  test :test1
end

Add group comment/description options;

group :my_other_group, comment: "This is the other group" do
  test :test1
end

Flow Loops for V93k

Use flow loop control to permit re-running tests without using additional sequence labels.

loop from: 0, to: 5, step: 1, var: '$LOOP_VARIABLE' do
  func :test_myloop, number: 56000
end

Indicating step value is optional, default is 1.

These loops can also be nested:

loop from: 0, to: 9, step: 2, var: '$LOOP_VARIABLE1'do
  loop from: 1, to: 10, step: 1, var: '$LOOP_VARIABLE2' do
    loop from: 1, to: 5, step: 1, var: '$LOOP_VARIABLE3' do
      func :test_myloop5, number: 56400
    end
  end
end

You can also indicate a test number increment if desired (default is 1):

loop from: 0, to: 5, var: '$LOOP_VARIABLE', test_num_inc: 2 do
    func :test_myloop3, number: 56200
end

You can also provide a variable starting point:

loop from: '$TEST_VARIABLE', to: 5, var: '$LOOP_VARIABLE' do
    func :test_myloop6, number: 56600
end

Decrementing loops, having from: value > to: value and using negative step:, is also supported.

Loop Rules For Each Environment

SMT7 cannot support a variable stop location. Only the from: parameter is allowed to be a variable.

SMT8 cannot have a step other than -1 or 1. The limitations of the range flow restrict those steps. The to: parameter can be a flow variable just like from:.


Comments

Generated with the Origen Semiconductor Developer's Kit

Origen is released under the terms of the MIT license