• 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

Miscellaneous

Callbacks


Callbacks provide a way for an application to hook into the Origen process and have the opportunity to modify the standard behavior in some way.

This could also be accomplished by redefining any of Origen’s code at application-level but that approach is not recommended since it leaves the application at risk of breaking if Origen ever makes changes to how things work internally.

Callbacks on the other hand are an official API that will always work between releases.

Note that it is very easy to add additional callbacks to Origen, so if you can see the need for one that is not already covered please contact us via the community channels to discuss.

Registering Listeners

Callbacks work by registering listeners with Origen. As the Origen process executes it will come across various points where callbacks have been enabled and which will cause Origen to pause and ask all of the listeners if they have any code that they wish to execute. If so control will transfer to the listener who will execute something and who may or may not return control back to the Origen process when complete.

In other words Origen will call-back to the application at various points during the process.

A listener can be any object instance within your application and by default the application itself (as defined in config/application.rb) and any classes which include Origen::TopLevel or Origen::Model are already registered as listeners.

Additional custom classes can be registered by simply including the callbacks module:

module NVM
  class CallbackHandlers

    include Origen::Callbacks

  end
end

Note that listeners have to be object instances, so in the example above the listener is only registered when the application creates a new instance of CallbackHandlers. If an instance is never created then the callbacks implemented in that class will never be called.

This is particularly true of any objects that are defined as sub-blocks since the sub-block is not actually instantiated until the point where it is first referenced by an application.

Note! One exception to the above rule is the on_create callback. Since this is commonly used as a delayed version of initialize, Origen will invoke that method at the point when the listener object is instantiated if the on_create callbacks have already been called.

Persistent Listeners

By default the pool of listeners is cleared out before a target load and they will be replaced by whatever objects are instantiated by the new target. In most cases this is the desired behavior and everything in the application will behave as you would expect.

However in some cases it may be desired to setup callback listeners that will persist across target loads so that they keep listening for the entire duration of an Origen thread. This can be achieved by including the PersistentCallbacks module instead:

module NVM
  class PersistentCallbackHandlers

    include Origen::PersistentCallbacks

  end
  # Instantiate an instance of this class immediately when this file is loaded, this object will
  # then listen for the remainder of the Origen thread
  PersistentCallbackHandlers.new
end

A common use case is to use a persistent callback listener that implements on_load_target to implement common target behavior - i.e. implement logic that should run for every target. Most crucially plugins can take full advantage of this to augment all of the targets of their host application.

Implementing a Callback

Implementing a callback is simply a matter of implementing an agreed method name within a listener.

So at each callback point the Origen code is basically:

listeners.each do |listener|
  if listener.respond_to?(callback_x)
    listener.callback_x(arg_x, arg_y)
  end
end  

So any listeners which don’t implement a specific callback are simply ignored.

To enable the above callback our custom listener would be changed to:

module NVM
  class CallbackHandlers

    include Origen::Callbacks

    def callback_x(arg_x, arg_y)
      if arg_x == :ft_pattern
        puts "Final test not supported yet!"
        exit 0
      end
      # Otherwise return to Origen
    end

  end
end

As mentioned the application is already registered as a listener, so the above callback_x method could be added to config/application.rb and it would be called at the appropriate time.

Calling Order

If an application has mutliple listeners for the same callback then they will all get called, however the order that they are called in is undefined unless otherwise specified in the documentation for a particular callback (e.g. startup and shutdown callbacks).

Generally if calling order is important the recommended approach is for the application to implement a single callback and then from there co-ordinate calling any additional application methods that need to be run.

Available Callbacks

There now follows a listing of all available callbacks, these have been split up by function:

  • Environment Setup
  • Environment Teardown
  • Generation
  • Mode Changed
  • Reset
  • Pattern Generation
  • Program Generation
  • Web Compiler
  • Release Process
  • Intializing Models

Environment Setup

before_load_target

This callback is triggered immediately before the target is loaded.

The intended use case is to allow any domain specific clean up that needs to be done when reloading or changing the target during an Origen thread of execution. Origen will take care of ensuring that the top-level model, the tester and all callback listeners are safely removed and/or re-instantiated between target loads, and in the vast majority of cases the application should never need to use this.

on_create

This callback is triggered immediately after the target is loaded.

The intended use case is to allow the application to complete any target object initialization that may be dependent on other target objects. In other words you can think of this like a regular initialize method but one where all objects instaniated by the target are guaranteed to be available.

No return value is expected.

include Origen::Callbacks

def initialize
  # Would be creating a target instantiation order dependency by doing this here
  # tester.do_something
end

def on_create
  # But not here
  tester.do_something
end

on_load_target

This is basically an alias of on_create and it behaves in exactly the same way.

Conceptually though it reflects a different way of using this callback: on_create can be thought of as an enhanced version of initialize at a model level, whereas on_load_target can be thought of as a way to augment all targets with common behavior.

See the section on Persistent Listeners above for some more discussion on this.

on_top_level_instantiated(top_level_object)

This callback is triggered immediately after a top-level object (an object that includes the Origen::TopLevel module, normally an object representing the top-level of the SoC) is instantiated.

No return value is expected.

include Origen::Callbacks

# Automatically instantiate a RAM model whenever a DUT model is instantiated, the size will
# be determined by the ram_size attribute of the DUT
def on_top_level_instantiated(dut)
  $ram = MyPlugin::RAM.new size: dut.ram_size
end

interactive_startup

This will be called immediately before giving control to the user when opening an interactive console session (by running origen i). The target will already be loaded prior to calling.

The intended use case is to give the application a chance to perform a device setup sequence in the case where the environment is connected to an Origen Link compatible tester driver.

# This is called automatically at the start of an interactive session (origen i)
def interactive_startup
  # Run the regular pattern startup method upon opening the console to put the device in test mode
  startup if tester.link?
end

interactive_shutdown

This will be called immediately before shutting down an interactive console session.

The intended use case is to shutdown the device in the case where the environment is connected to an Origen Link compatible tester driver.

# This is called automatically at the end of an interactive session (origen i)
def interactive_shutdown
  # Run the regular pattern shutdown method to put the device in reset
  shutdown if tester.link?
end

Environment Teardown

on_origen_shutdown

This callback is triggered at the very end of an Origen thread of execution and is guaranteed to be called even if the thread crashes.

An example use cases is to ensure that any temporary files are deleted.

Mode Changed

on_mode_changed

This callback is triggered whenever an object changes its current mode. It takes an options hash as an argument with the recently changed mode being passed. It can be used to change other DUT objects, such as clocks and register settings.

def on_mode_changed(options)
  if options[:instance] == self
    case options[:mode]
    when :mode1
      clocks(:coreclk).setpoint = 1.2.Ghz
      clocks(:memclk).setpoint = 600.Mhz
    when :mode2
      clocks(:coreclk).setpoint = 1.0.Ghz
      clocks(:memclk).setpoint = 500.Mhz
    end
  end
end

Generation

before_lsf_submission

This callback is triggered immediately before submitting a batch of jobs to the LSF.

No return value is expected.

before_generate(options)

This callback is triggered immediately before launching a generate operation, that is before starting the current batch of program generation, pattern generation or compile jobs.

No return value is expected.

before_generate_local(options)

As above but only called when running locally.

before_generate_remote(options)

As above but only called when running on a remote LSF machine.

Reset

The reset callbacks will kick in when the reset or reset! method is called on the top-level object.

They will be executed in the following order:

  • before_top_level_reset
  • shutdown (reset! only)
  • on_top_level_reset! (reset! only)
  • on_top_level_reset
  • registers are reset here
  • startup (reset! only)
  • after_top_level_reset

Generally with all reset callbacks the application code is not expected to take care of reseting registers or any other Origen-owned objects. Only state specifically setup by the application code should need to be teared down and re-established.

before_top_level_reset

Called as soon as the reset or reset! method is called on the top-level object and before any other reset activity takes place.

This callback should not be used to generate reset vectors, use the shutdown callback for that.

No return value is expected.

def before_top_level_reset
  @some_state_attribute = nil
end

on_top_level_reset

Called when the reset or reset! method has been called on the top-level object and after the top-level has been shutdown.

No return value is expected.

def on_top_level_reset
  @some_state_attribute = nil
end

on_top_level_reset!

Called only when the reset! method has been called on the top-level object, otherwise the same as reset.

after_top_level_reset

Called at the very end of a reset sequence initiated by calling reset or reset! on the top-level object at which point the top-level has already been re-started.

This callback should not be used to generate reset vectors, use the startup callback for that.

No return value is expected.

def after_top_level_reset
  @some_state_attribute = nil
end

Pattern Generation

startup(options)

Called at the start of a Pattern.create block, this callback provides an opportunity to implement startup vectors.

It will also be called as part of a within-pattern reset sequence initiated by calling reset! on the top-level object.

Any options supplied to Pattern.create are passed in as an argument.

The top-level (DUT) object is guaranteed to be called first for this callback, this enables the common case where the top-level will generate the mode entry vectors from this callback and then child modules can generate any additional vectors safe in the knowledge that mode has already been entered.

No return value is expected.

def startup(options)
  tester.set_timeset("nvmbist", 40)
  dut.pin(:reset).drive!(1)
end

shutdown(options)

Called at the very end of a Pattern.create block, this callback provides an opportunity to implement reset vectors.

It will also be called as part of a within-pattern reset sequence initiated by calling reset! on the top-level object.

Any options supplied to Pattern.create are passed in as an argument.

The top-level (DUT) object is guaranteed to be called last for this callback, this enables the common case where the child modules can insert any shutdown/safe-state vectors before the top-level finally pulls reset.

No return value is expected.

def shutdown(options)
  dut.pin(:reset).drive!(0)
end

before_pattern(pattern_name)

This callback is triggered immediately before running a Pattern.create block.

At this point the target is fully loaded but the pattern is not yet opened - so you can’t generate vectors from here.

The intended use case for this callback is to establish state within your models based on the pattern name. This can be used in conjunction with a pattern name translator to generate variants of your existing patterns without having to create a new pattern source.

No return value is expected.

# If the requested pattern has 'trimmed' in the name then look for the equivalent
# source file without 'trimmed' in the name.
# The output pattern will still contain 'trimmed' in the name.
config.pattern_name_translator do |name|
  if name =~ /trimmed/
    {source: name.gsub("trimmed_", ""), output: name}
  else
    name
  end
end

# Setup the dut model differently if generating a pattern for a trimmed device
def before_pattern(pattern_name)
  if name =~ /trimmed/
    dut.apply_default_trims = false
  end
end

before_pattern_lookup(requested_pattern)

This callback is triggered before Origen searches for the requested pattern source.

The intended use case is to give the application a chance to dispatch the pattern itself, or to decide to withhold it based on some properties of the current target.

If the callback returns a value of false or nil then Origen will abort further processing of this pattern and move onto the next one. Origen will proceed to dispatch the pattern as normal if any other value is returned.

def before_pattern_lookup(requested_pattern)
  if requested_pattern =~ /blk_1/
    # Only proceed with this pattern if the current target has a blk 1
    dut.has_blk1?
  else # Proceed as normal
    requested_pattern
  end
end

pattern_generated(path_to_generated_pattern)

This callback is triggered at the end of every pattern that is generated, the path to the generated file (wrapped in a Pathname) is passed to the listener.

The intended use case is to give plugins a hook to kick off additional operations at the end of a pattern being generated, such as to go and simulate it or to compile it to a binary. Normally this callback would be implemented in a persistent listener within a plugin to have the plugin called after every pattern that is generated.

No return value is expected.

module VirtualTester
  class PersistentCallbackHandlers
    include Origen::PersistentCallbacks

    def pattern_generated(path_to_generated_pattern)
      if $vt_simulation_enabled  # Set this back when the command was launched or however you want to enable
        VirtualTester::Runner.new(path_to_generated_pattern)
      end
    end
  end
  # Instantiate an instance of this class immediately when this file is required, this object will
  # then listen for the remainder of the Origen thread
  PersistentCallbackHandlers.new
end

Program Generation

on_flow_start(options)

Called at the start of a top-level Flow.create block, note that it is not called at the beginning of sub-flows that are included by the top-level flow.

Any options supplied to Flow.create are passed in as an argument.

No return value is expected.

on_flow_end(options)

Called at the very end of a top-level Flow.create block, note that it is not called at the end of sub-flows that are included by the top-level flow.

Any options supplied to Flow.create are passed in as an argument.

No return value is expected.

on_resource_start(options)

Logically equivalent to on_flow_start, except this one will be called when the top level is a Resource.create block instead of a Flow.create block.

on_resource_end(options)

Logically equivalent to on_flow_end, except this one will be called when the top level is a Resource.create block instead of a Flow.create block.

program_generated

This callback is triggered after a test program has been completely generated and all files have been written. No particular arguments are passed in, however the Origen.interface instance for the program that was just generated is still live and the application should be able to retrieve any meta data it might want about the program from there.

No return value is expected.

Web Compiler

before_web_compile(options)

This is called immediately prior to running the requested origen web compile operation and it provides the application with an opportunity to dynamically generate some templates for the compiler to execute.

The command line arguments are decoded and available in the given options hash.

No return value is expected.

after_web_compile(options)

This is called immediately after running the requested origen web compile operation and provides the application with an opportunity to add anything else to the web/output directory.

The command line arguments are decoded and available in the given options hash.

No return value is expected.

after_web_site_compile(options)

Similar to after_web_compile, except that this one will only be called when a request has been made to compile the entire web site, i.e. when origen web compile has been called without a file argument(s).

The command line arguments are decoded and available in the given options hash.

No return value is expected.

Release Process

validate_release

This is called immediately prior to the release (origen rc tag) process and gives the application a chance to do any final checks to authorize that the release can go ahead.

No return value is expected but the callback handler is expected to exit the process if it decides that the release should be aborted.

Typically this hook would be used to launch the application’s test suite and if it fails abort the process, here is an example:

# Ensure that all tests pass before allowing a release to continue
def validate_release
  if !system("origen specs") || !system("origen examples")
    puts "Sorry but you can't release with failing tests, please fix them and try again."
    exit 1
  else
    puts "All tests passing, proceeding with release process!"
  end
end

before_release_tag(identifier, note, type, selector, options)

This callback is triggered immediately before the application is tagged, all release properties are available in the arguments.

No return value is expected.

before_release_gem

This callback is triggered immediately before the gem is built if the application is a plugin. It is not called at all if the application is a top-level app.

It can be used to prepare files to be included in the gem package.

No return value is expected.

after_release_gem

This callback is triggered immediately before the gem is built if the application is a plugin. It is not called at all if the application is a top-level app.

It can be used to clean up after building the gem package.

No return value is expected.

after_release_tag(identifier, note, type, selector, options)

This callback is triggered immediately after the application has been tagged and before the release email has been sent.

If the callback doesn’t return then the release email will not be sent.

No return value is expected.

after_release_email(identifier, note, type, selector, options)

Called at the very end of the release process.

This callback is commonly used to kick off any doc builds or other post release tasks within the application.

No return value is expected.

# Example of automatically deploying documents after a tag
def after_release_email(tag, note, type, selector, options)
  command = "origen web compile --remote --api"
  Dir.chdir Origen.root do
    system command
  end
end

before_deploy_site

Called immediately before a web site is deployed.

This gives the application a chance to add any additional files to the web site before it is deployed.

No return value is expected.

# Generate a test coverage report and add it to the web site
def before_deploy_site
  Dir.chdir Origen.root do
    system "origen specs -c"
    system "mv #{Origen.root}/coverage #{Origen.root}/web/output/coverage"
  end
end

Initializing Models

origen_model_init

Called only when a class or module has a class method called origen_model_init AND when said class mixes in Origen::Model.

This will be called during the class’ instantiation process, when the class has been allocated but before it has been initialized using its own initialize method. This can be used to boot modules or classes using Origen and leaving a module’s included? method alone.

This differs from the pre_initialize callback in that origen_model_init will recurse into the inherited modules and classes.

This method should accept a single argument, which is the allocated class instance that called origen_model_init.

For example:

module A
  def self.origen_model_init(instance_of_caller)
    puts "init module A - called by #{instance_of_caller.class}"
  end
  
  class B
    def self.origen_model_init(instance_of_caller)
      puts "init class B in module A - called by #{instance_of_caller.class}"
    end
  end
end

class Parent
  include Origen::Model
  include A
end

Parent.new
  #=> "init module A - called by Parent"
  #=> "init class B in module A - called by Parent" <= this is called prior to any A::B initialization.
#=> Instance of Parent class

Note that included modules and classes do not need to mix in Origen::Model. Only the class including said modules and classes.

Again, this is for use in booting included classes and modules, not in booting the parent. origen_model_init will NOT be called in following and pre_initialize should be used:


class Parent
  include Origen::Model
  include A
  
  def self.origen_model_init(instance_of_caller)
    puts "origen_model_init in Parent"
  end
  
  def self.pre_initialize
    puts "pre_initialize in Parent"
  end
end

Parent.new
  #=> "init module A - called by Parent"
  #=> "init class B in module A - called by Parent"
  #=> "pre_initialize in Parent"
#=> Instance of Parent class


Comments

Generated with the Origen Semiconductor Developer's Kit

Origen is released under the terms of the MIT license