• 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

Plugins

Creating a Plugin


Origen plugins are essentially Origen applications themselves. Follow the standard instructions to Create a New Application and choose one of the available plugin templates rather than an application template.

Understanding How Plugins are Loaded

For the purposes of this guide let’s say we are creating a plugin called ATDTest and this would have a top-level lib file called lib/atd_test.rb.

When a plugin is run from its own workspace, we would call this running in standalone or development mode, then it is loaded like any other Origen application. The first thing Origen does in this case is to load the plugin’s gem bundle, defined in its Gemfile, and then boot the plugin by loading config/boot.rb. Normally such a file will look like this:

# config/boot.rb
require 'atd_test'

So by default this simply loads the plugin’s top-level file which in this example is lib/atd_test.rb.

However when the plugin is loaded as part of a parent application, neither the plugin’s Gemfile or its config/boot.rb file will be loaded. Instead the parent application’s Gemfile will be loaded, and this will contain a reference to our plugin. The tool that evaluates the Gemfile, called Bundler, will inspect our plugin’s gemspec file (in this example atd_test.gemspec) and it will ensure that any dependencies listed there are met. Once the gem bundle has been created it will then load our plugin’s top-level file, lib/atd_test.rb.

The take away from this is that the following rules should be observed when creating plugins:

  • Load all of your plugin’s code from it’s top-level file (lib/atd_test.rb), if that requires all of the lib code you wish to share with your users then they will not need to do anything except add your plugin to their Gemfile.
  • The plugin’s config/boot.rb file should only be used for loading any code which is for testing only or for otherwise running your plugin within its own workspace environment.
  • The plugin’s Gemfile should not be used. This should contain a line that calls gemspec which tells Bundler to refer to the plugin’s gemspec file instead, e.g. atd_test.gemspec. This prevents you from having to maintain the plugin’s gem dependencies in two separate locations.
  • The plugin’s gemspec should be used to declare all of its gem dependencies as shown below. Note that plugins must never specify an absolute version of gems in its runtime dependencies.
# atd_test.gemspec

# Declare any dependencies that the plugin will need when it is running within a parent application.
# Never specify an absolute version since that can easily conflict with other plugins if they did the
# same. Instead specify a range, normally just a minimum version that you need.
spec.add_runtime_dependency "origen_jtag", ">= 1.1.0"

# Declare any dependencies that the plugin need when running in standalone/development mode only, a
# very common example is the documentation helpers plugin. This is only required to build the plugins
# web pages, but it is not required at runtime.
# Note that absolute version numbers are allowed here since this does not apply outside of this plugin.
spec.add_development_dependency "origen_doc_helpers"

Sharing Models and Other Lib Code

The plugin’s lib directory will be automatically added to the Ruby load path no special consideration is required to expose lib code to the parent application. In our example the parent application will be able to load any of our code like this:

require 'atd_test/atd_16b'

However as noted above the plugin’s top-level file, lib/atd_test.rb will be automatically loaded, therefore it is the usual convention to have this file require everything else so that the parent application does not need to manually require anything.

Sharing Other IP

To share source files, templates and commands the plugin must define config.shared in its config/application.rb file, here is an example that will share everything:

config.shared = {
  :patterns => "pattern",
  :templates => "templates",
  :programs => "program",
  :command_launcher => "config/shared_commands.rb"
}

Access can be restricted by specifying a sub-directory, or by simply removing the given resource:

# Only share a subset of patterns (those that live within the pattern/shared directory, those
# in pattern/development for example would not be available to the host application)
config.shared = {
  :patterns => "pattern/shared",
#  :templates => "templates",
#  :programs => "program",
#  :command_launcher => "config/shared_commands.rb"
#  :global_launcher => "config/global_commands.rb"
}

Sharing Templates

The host application can reference a template from an added plugin by using the plugin’s name as a pointer to the shared template directory (the directory specified in the plugin’s config.shared[:templates] attribute), and then a relative path from there to the required template.

For example the doc_helpers plugin contains a test flow layout template at templates/shared/test/_flow.md.erb, and an importing application would reference this template via the path doc_helpers/test/_flow.md.erb.

Sharing Pattern and Program Sources

When test pattern and program directories are shared Origen will look within these for the requests patterns/flows whenever the given plugin is designated as the current plugin.

See the Current Plugin for more detail on this.

For example say our plugin is called atd_test and it provides a pattern called atd_ramp.rb, then it could be generated like this from the parent application workspace:

origen pl atd_test
origen g atd_ramp

Alternatively you can override the current plugin at runtime like this, this is equivalent to the above:

origen g atd_ramp --plugin atd_test

Program generation source files work from exactly the same principles.

Note that since there is currently no easy way to view a list of all patterns provided by a plugin, it is conventional for the plugin to provide custom commands to generate a complete set of patterns, e.g. something like this:

origen atd_test:prod_pats   # Generate all production patterns from the ATD plugin
origen atd_test:prod_prog   # Generate the production test program from the ATD plugin

Sharing Application Commands

To share custom commands supply a path to a command definition/launcher file within the plugin as shown in the example above.

This file works very similar to the way that custom commands are added to an application.

Here is an example command launcher file from a real plugin, this adds a custom command, origen atd_test:j750, to the host application and also extends the origen g command by adding an additional option to it.

Note the use of Origen.root! and Origen.app! to refer to the plugin’s own root and application instance rather than that of the host application.

Also note that the command has been called atd_test:j750 instead of just j750, this is to ensure that there is no naming collision with commands that could be added by other plugins. In future Origen will automatically apply a plugin specific prefix to the commands like this, but until then all plugin developers are expected to be good citizens and add this manually.

# config/shared_commands.rb

# The requested command is passed in here as @command
case @command

when "atd_test:j750"
  require "#{Origen.root!}/lib/commands/j750"
  # Important to exit when a command has been fulfilled or else Origen core will try and execute it
  exit 0

# Add an additional option to the standard generate command, important to have no exit here
when "generate"
  @application_options << ["--md5", "Apply an MD5 checksum to pattern names"]
  Origen.app!.md5 = true if ARGV.include?("--md5")

# Always leave an else clause to allow control to fall back through to the Origen command handler.
# You probably want to also add the command details to the help shown via 'origen -h',
# you can do this bb adding the required text to @plugin_commands before handing control back to
# Origen.
else
  @plugin_commands << <<-EOT
 atd_test:j750 Generate the ATD test program for J750
  EOT

end

Sharing Global Commands

The above allows you to share commands when running from within an application instance. But what if we want to share commands regardless of whether we are running in an application? In this way, Origen can be even further utilized as a tool distribution platform and but allow all of our non-application specific functionality to still be used. E.g., LSF manager, authentication, revision control APIs, etc.

Adding shared global commands is very similiar to adding shared application commands, as shown above. The global_launcher option in the config.shared definition points to a file containing the global commands. This file, call it config/global_commands.rb, for example, is analogous to the config/shared_commands.rb file from the above and looks about the same, with the exception that the @plugin_commands variable is now @global_commands. An example is below:


case @command

# Print the current version notes of the atd_test module.
when "atd_test:version_notes"
  require "#{Origen.root!}/lib/commands/version_notes"
  exit 0

else
  @global_commands << <<-EOT
 atd_test:version_notes             Checks the dPDM BOM versus the DS HREFs
                                    -h for a full description
  EOT

end

Danger! Global commands are a bit more involved and require some extra setup outside of the plugin itself. When inside an application, these commands will behave as Shared commands, but outside of an application, the plugin must be brought in as a dependency either through User Installs or Tool Repo Installs, or must be added to the system gems. For a refresher on what this means, please see the Invocation Considerations Guide. For even more details please see the Advanced Topic On Invocations.
Danger! Global commands behave slightly differently when run from an application versus running without one. Origen does provide a 'standalone' application which gives all the functionality, but this application cannot be customized. If you find yourself requiring application-specific behavior, your command is better suited to be a Shared command.
Danger! Although Global and Shared commands may have differences in the application behavior, they do not have any differences, from an Origen perspective, when invoked either by a Tool Repo Install or User Install setup versus a System Level setup. Bundler makes it easier to develop Global commands than using Gem natively, so it is recommended that you use a User Install when developing Global commands. You can read up on this is and how to set it up in the Advanced Topic On Invocations.

Command Sharing Considerations

Due to the way that Origen acknowledges shared, global, and application commands, a pitfall exists where user-defined commands can step on each other (known as command clobbering). This has the implication that you may not be running the command you think you are running.

Consider a plugin, called my_plugin_1 that adds and implements a shared command my_command. This command will be available to any application which contains my_plugin_1 as a dependency. Now, consider a second plugin, my_plugin_2 which is also a dependency of the application. my_plugin_2 also adds and implements the command my_command. Both plugins are adding the same command and are clobbering the command listing. The behavior will be dependent on the load order and can be difficult to predict.

For example, if my_plugin_1 is listed before my_plugin_2 in the application’s Gemfile, then my_plugin_1 will be loaded and evaluated first and my_command in my_plugin_1 will be run. However, that is not all the consideration needed. If my_plugin_1 actually lists my_plugin_2 as its dependency, then my_plugin_2 will be loaded before my_plugin_1 regardless of the load order in the application’s Gemfile. Now, my_command in my_plugin_2 will be run. This means that it can be difficult to track which one of the commands will be run in the case of command clobbering between plugins. You can use the bundle command to see what the final load order is and track down which version of the command will be run.

The solution to this is to add namespacing to each of the plugins, as shown in the Sharing Application Commands section above. However, this is up to the plugin developers to abide by. Origen does not guarantee nor enforce this behavior and is none the wiser to plugins stepping on each other. No warnings or errors are generated in the event of command clobbering.

Regarding global commands, the same pitfall exists. However, an additional issue is that a shared command can now clobber a global command. In the current Origen implementation, shared commands take precedence over global commands. Meaning, if my_plugin_1 implements my_command as a global command and, for one reason or another, it implements my_command as a shared command, then when running in an application the shared version of my_command will be used. However, external to an application, the global version of my_command will be run. Like shared command clobbering, no warnings or errors are generated, Origen is completely oblivious to this behavior, and it is up to the plugin developers to ensure this does not occur.

This is a known issue which has been registerd with the core team. For tracking this issue’s status, please see the Cascading Commands Issue on Github.


Comments

Generated with the Origen Semiconductor Developer's Kit

Origen is released under the terms of the MIT license