Ruby-VPI user manual

Suraj N. Kurapati

Mon Dec 18 12:07:24 PST 2006

Terms

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts and no Back-Cover Texts. A copy of the license is included in the the file named LICENSE.

Admonition and navigation graphics are Copyright© 2005, 2006 Tango Desktop Project. They are licensed under these terms.

Introduction

Ruby-VPI is a Ruby interface to Verilog VPI. It lets you create complex Verilog test benches easily and wholly in Ruby.

Features

Applications

Here is a modest sampling of tasks, paraphrased from Pin Hong, that Ruby-VPI can be used to perform.

Appetizers

Here is a modest sampling of code to whet your appetite.

some_register.intVal = 2 ** 2048

some_module.all_net? { |net| net.z? }

puts some_register

15.times { relay_verilog }

License

Ruby-VPI is free software ; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation ; either version 2 of the License, or (at your option) any later version.

Related works

Ye olde PLI

The following projects utilize the archaic tf and acc PLI interfaces, which have been officially deprecated in IEEE Std 1364-2005.

Background

Ruby-VPI is a bench which lets you test Verilog modules using the Ruby language.

Methodology

Ruby-VPI presents an open-ended interface to VPI. Thus, you can use any methodology you wish when writing tests. However, being an agile language, Ruby makes it very easy to use agile development practies such as TDD and BDD.

Terminology

note

Note:

Have a look at the glossary for definitions of terms used in this manual.

As a newcomer into the world of Verilog, I often heard the term test bench: “I ran the test bench, but it didn’t work!” or “Are you crazy?!! You still haven’t written the test bench?”, for example. I poured through my textbook for a definition of the term, but it was to no avail. Instead, it nonchalantly employed the term throughout its being, as if mocking my ignorance of what seems to be universal knowledge.

Defeated, I turned to my inner faculties to determine the answer. Let’s see, the term test bench has the word test—so it has something to do with testing—and it has the word bench—so maybe it’s referring to a table where the testing should occur. This reasoning grew increasingly familiar as my mind rummaged through towering stores of obsolescence and ultimately revealed dreaded memories of sleepless anguish: debugging electronics in the robotics laboratory.

Aha! I exclaimed, hesitantly, rushing to dismiss the past. The term has its roots in the testing of electronic devices, where an engineer would sit at a bench in an electronics laboratory and verify that an electronic component satisfies some criteria. The bench would be furnished with tools of measurement and manipulation—such as oscilloscopes, voltmeters, soldering irons, and so on—which help the engineer to verify the electronic component or locate the sources of defects in the component.

Alright, now I remember what a laboratory bench is, but how does that compare with the term test bench? Surely they cannot have the same meaning, because it doesn’t make sense to run a laboratory bench or to write one. Thus, to avoid propagating such confusion into this manual, I have attempted to clarify the terminology by simplifying and reintroducing it in a new light.

Organization

Figure 1. Overall organization of a test

As the figure named “Overall organization of a test” shows, a test is composed of a bench, a design, and a specification.

To extend the analogy of an electronics laboratory, the bench acts as the laboratory bench which provides measurement and manipulation tools. The design acts as the electronic component being verified by the engineer. And the specification acts as the engineer who measures, manipulates, and verifies the electronic component.

Interface to VPI

Figure 2. Detailed organization of a test

In the figure named “Detailed organization of a test”, Ruby-VPI acts as the bench, a Verilog simulator encapsulates the design, and a Ruby interpreter encapsulates the specification.

Notice that Ruby-VPI encapsulates all communication between the Ruby interpreter and VPI. This allows the specification, or any Ruby program in general, to access VPI using nothing more than the Ruby language! Thus, Ruby-VPI removes the burden of having to write C programs in order to access VPI.

Furthermore, Ruby-VPI presents the entire IEEE Std 1364-2005 VPI interface to the Ruby interpreter, but with the following minor changes.

The reason for this limitation is that some C compilers have trouble with pointers to the va_list type. For these compilers, the second line in the code shown below causes a “type mismatch” error.

void foo(va_list ap) {
  va_list *p = ≈
}

VPI utility layer

From a user’s perspective, the VPI utility layer (see the figure named “Detailed organization of a test”) greatly enhances the ability to interact with handles. One simply invokes a handle’s methods, which are carefully named in the following manner, to access either (1) its children or (2) its VPI properties.

The children of a handle are simply the handles that are immediately contained within it in. For example, suppose that you had a Verilog module that contains some registers. The children of a handle to that module would be handles to that module’s registers.

In the event that a child handle has the same name as a VPI property, the child is given priority. However, you can always access VPI properties explicitly via the Vpi::Handle.get_value and Vpi::Handle.put_value methods.

Figure 3. Parts of speech for accessing a handle’s VPI properties

Operation _ Property _ Accessor Addendum
optional required optional

Table 1. Possible accessors and their implications

Accessor Kind of value accessed VPI functions used to access the value
d delay vpi_get_delays, vpi_put_delays
l logic vpi_get_value, vpi_put_value
i integer vpi_get
b boolean vpi_get
s string vpi_get_str
h handle vpi_handle

Example 1. Examples of accessing a handle’s VPI properties

Ruby expression Parts of speech Description
Operation _ Property _ Accessor Addendum
handle.vpiIntVal     vpiIntVal       These expressions access the logic value of the handle’s vpiIntVal property.
handle.vpiIntVal_l     vpiIntVal _ l  
handle.intVal     intVal      
handle.intVal_l     intVal _ l  
handle.vpiIntVal = 15     vpiIntVal     = These expressions assign the number 15 to the logic value of the handle’s vpiIntVal property.
handle.vpiIntVal_l = 15     vpiIntVal _ l =
handle.intVal = 15     intVal     =
handle.intVal_l = 15     intVal _ l =
handle.vpiType     vpiType       These expressions access the integer value of the handle’s vpiType property.
handle.vpiType_i     vpiType _ i  
handle.type     type      
handle.type_i     type _ i  
handle.vpiProtected     vpiProtected       These expressions access the boolean value of the handle’s vpiProtected property.
handle.vpiProtected_b     vpiProtected _ b  
handle.vpiProtected?     vpiProtected     ?
handle.protected     protected      
handle.protected_b     protected _ b  
handle.protected?     protected     ?
handle.vpiFullName     vpiFullName       These expressions access the string value of the handle’s vpiFullName property.
handle.vpiFullName_s     vpiFullName _ s  
handle.fullName     fullName      
handle.fullName_s     fullName _ s  
handle.vpiParent     vpiParent       These expressions access the handle value of the handle’s vpiParent property.
handle.vpiParent_h     vpiParent _ h  
handle.parent     parent      
handle.parent_h     parent _ h  
handle.each_vpiNet {|net| puts net.fullName} each _ vpiNet       These expressions print the full name of each vpiNet object associated with the handle.
handle.each_net {|net| puts net.fullName} each _ net      
handle.all_vpiReg? {|reg| reg.size == 1} all? _ vpiReg       These expressions check if all registers associated with the handle are capable of storing only one bit.
handle.all_reg? {|reg| reg.size == 1} all? _ reg      
handle.select_vpiNet {|net| net.x?} select _ VpiNet       These expressions return a list of nets whose logic value is unknown or “don’t care” (x).
handle.select_net {|net| net.x?} select _ net      

Running a test

Unlike an engineer who can verify an electronic component in real-time, the Verilog simulator and the Ruby interpreter (see the figure named “Detailed organization of a test”) take turns working with handles when a test is run. In particular, they take turns manipulating the Verilog design and transfer control to each other when appropriate.

The situation is similar to a pair of friends playing catch. One friend throws a ball to the other, and the other throws it back. Either is able to inspect and modify the ball, but only when it is in hand.

Initialization

A test is first initialized before it is executed. This process is illustrated by the figure named “Initialization of a test”.

Figure 4. Initialization of a test

  1. The Verilog simulator initializes the Ruby interpreter by invoking the $ruby_init; system task/function, whose parameters represent the command-line invocation of the Ruby interpreter. For example, one would specify $ruby_init("ruby", "-w"); in Verilog to achieve the same effect as running
    ruby -w
    at a command-prompt.
  2. The Verilog simulator is paused and the Ruby interpreter is initialized with the arguments of the $ruby_init; system task/function.
  3. When the Ruby interpreter invokes the Vpi::relay_verilog method, it is paused and the Verilog simulator is given control.

Execution

After a test is initialized, it is executed such that the design is verified against the specification. This process is illustrated by the figure named “Execution of a test”.

Figure 5. Execution of a test

  1. The Verilog simulator transfers control to the Ruby interpreter by invoking the $ruby_relay; system task/function.
  2. The Verilog simulator is paused and the Ruby interpreter is given control.
  3. When the Ruby interpreter invokes the Vpi::relay_verilog method, it is paused and the Verilog simulator is given control.

Setup

Manifest

When you extract a release package, the following is what you would expect to find.

Requirements

The following software is necessary in order to use Ruby-VPI.

tip

Tip: Add support for your Verilog simulator

Write a support request for your simulator, while providing a sample transcript of the commands you use to run a test with your simulator, and we will add support for your simulator in the next release!

* make – any distribution should be acceptable.

Recommendations

The following software may make your interactions with Ruby-VPI more pleasant.

Text merging tool

An interactive text merging tool can greatly simplify the process of transferring wanted changes from one file to another. In particular, such tools are especially beneficial when using the automated test generator. A handful of the currently available open-source text merging tools are listed below.

Installation

Once you have satisfied the necessary requirements, you can install Ruby-VPI by running the

gem install ruby-vpi
command. RubyGems will install Ruby-VPI into the system gem directory, whose path can be determined by running the
gem env gemdir
command. Within this directory, there is a “gems” subdirectory which contains the Ruby-VPI installation, as illustrated below.

$ gem env gemdir
/usr/lib/ruby/gems/1.8

$ ls -d /usr/lib/ruby/gems/1.8/gems/ruby-vpi*
/usr/lib/ruby/gems/1.8/gems/ruby-vpi-7.0.0/

Installing on Windows

note

Note: Undefined symbols in Windows

After Ruby-VPI is compiled, it is linked to symbols whose names begin with _vpi. In GNU/Linux and similar operating systems, these symbols are allowed to be undefined. However, one cannot compile a shared object file with references to undefined symbols in Windows.

One solution is to supply the Verilog simulator’s VPI object file, which contains definitions of all VPI symbols, to the linker. The following steps illustrate this process.

* Search for object files whose names end with .so, .o, or .dll in your Verilog simulator’s installation directory.

Maintenance

note

Note:

Learn more about using and manipulating RubyGems in the RubyGems user manual.

Usage

Tools

The bin directory contains various utilities which ease the process of writing tests. Each tool provides help and usage information invoked with the --help option.

Automated test generation

The automated test generator (generate_test.rb) generates tests from Verilog 2001 module declarations, as demonstrated in the tutorial. A generated test is composed of the following parts:

The reason for dividing a single test into these parts is mainly to decouple the design from the specification. This allows you to focus on writing the specification while the remainder is automatically generated by the tool. For example, when the interface of a Verilog module changes, you would simply re-run this tool and incorporate those changes (using a text merging tool) into the test without diverting your focus from the specification.

tip

Tip: Using kdiff3 with the automated test generator.

  1. Create a file named merge2 with the following content:
    #!/bin/sh
    # args: old file, new file
    kdiff3 --auto --output "$2" "$@" 
    
  2. Make the file executable by running the
    chmod +x merge2
    command.
  3. Place the file somewhere accessible by your PATH environment variable.
  4. Assign the value “merge2” to the MERGER environment variable using your shell’s export or setenv command.

From now on, kdiff3 will be invoked to help you transfer your changes between generated files. When you are finished transferring changes, simply issue the “save the file” command and quit kdiff3. Or, if you do not want to transfer any changes, simply quit kdiff3 without saving the file.

Verilog to Ruby conversion

The header_to_ruby.rb tool can be used to convert Verilog header files into Ruby. You can try it by running the

header_to_ruby.rb --help
command.

By converting Verilog header files into Ruby, your test can utilize the same `define constants that are used in the Verilog design.

Tutorial

  1. Declare the design, which is a Verilog module, using Verilog 2001 syntax.
  2. Generate a test for the design using the automated test generator tool.
  3. Identify your expectations for the design and implement them in the specification.
  4. (Optional) Implement the prototype of the design in Ruby.
  5. (Optional) Verify the prototype against the specification.
  6. Implement the design in Verilog once the prototype has been verified.
  7. Verify the design against the specification.

Start with a design

First, we need a design to verify. In this tutorial, the example named “Declaration of a simple up-counter with synchronous reset” will serve as our design. Its interface is composed of the following parts:

Example 2. Declaration of a simple up-counter with synchronous reset

module counter #(parameter Size = 5) (
  input clock,
  input reset,
  output reg [Size - 1 : 0] count
);
endmodule

important

Important: Before we continue…

Save the source code shown in the example named “Declaration of a simple up-counter with synchronous reset” into a file named counter.v.

Generate a test

Now that we have a design to verify, let us generate a test for it using the automated test generator. This tool allows us to implement our specification in either rSpec, xUnit, or our very own format.

Each format represents a different software development methodology:

note

Note:

Both rSpec and xUnit formats are presented in this tutorial.

Once we have decided how we want to implement our specification, we can proceed to generate a test for our design. This process is illustrated by the example named “Generating a test with specification in rSpec format” and the example named “Generating a test with specification in xUnit format”.

Example 3. Generating a test with specification in rSpec format

$ generate_test.rb counter.v --rspec --name rspec

  module  counter
  create  counter_rspec_runner.rake
  create  counter_rspec_bench.v
  create  counter_rspec_bench.rb
  create  counter_rspec_design.rb
  create  counter_rspec_proto.rb
  create  counter_rspec_spec.rb

Example 4. Generating a test with specification in xUnit format

$ generate_test.rb counter.v --xunit --name xunit

  module  counter
  create  counter_xunit_runner.rake
  create  counter_xunit_bench.v
  create  counter_xunit_bench.rb
  create  counter_xunit_design.rb
  create  counter_xunit_proto.rb
  create  counter_xunit_spec.rb

Specify your expectations

So far, the test generation tool has created a basic foundation for our test. Now we must build upon this foundation by identifying our expectation of the design. That is, how do we expect the design to behave under certain conditions?

Here are some reasonable expectations for our simple counter:

Now that we have identified a set of expectations for our design, we are ready to implement them in our specification. This process is illustrated by the example named “Specification implemented in rSpec format” and the example named “Specification implemented in xUnit format”.

Example 5. Specification implemented in rSpec format

# This file is a behavioral specification for the design under test.

# lowest upper bound of counter's value
LIMIT = 2 ** Counter.Size.intVal

# maximum allowed value for a counter
MAX = LIMIT - 1

context "A resetted counter's value" do
  setup do
    Counter.reset!
  end

  specify "should be zero" do
    Counter.count.intVal.should == 0
  end

  specify "should increment by one count upon each rising clock edge" do
    LIMIT.times do |i|
      Counter.count.intVal.should == i
      relay_verilog # increment the counter
    end
  end
end

context "A counter with the maximum value" do
  setup do
    Counter.reset!

    # increment the counter to maximum value
    MAX.times {relay_verilog}
    Counter.count.intVal.should == MAX
  end

  specify "should overflow upon increment" do
    relay_verilog # increment the counter
    Counter.count.intVal.should == 0
  end
end

Example 6. Specification implemented in xUnit format

# This file is a behavioral specification for the design under test.

# lowest upper bound of counter's value
LIMIT = 2 ** Counter.Size.intVal

# maximum allowed value for a counter
MAX = LIMIT - 1

class ResettedCounterValue < Test::Unit::TestCase
  def setup
    Counter.reset!
  end

  def test_zero
    assert_equal 0, Counter.count.intVal
  end

  def test_increment
    LIMIT.times do |i|
      assert_equal i, Counter.count.intVal
      relay_verilog # increment the counter
    end
  end
end

class MaximumCounterValue < Test::Unit::TestCase
  def setup
    Counter.reset!

    # increment the counter to maximum value
    MAX.times {relay_verilog}
    assert_equal MAX, Counter.count.intVal
  end

  def test_overflow
    relay_verilog # increment the counter
    assert_equal 0, Counter.count.intVal
  end
end

important

Important: Before we continue…

  1. Replace the contents of the file named counter_rspec_spec.rb with the source code shown in the example named “Specification implemented in rSpec format”.
  2. Replace the contents of the file named counter_xunit_spec.rb with the source code shown in the example named “Specification implemented in xUnit format”.
  3. Replace the contents of the files named counter_rspec_design.rb and counter_xunit_design.rb with the following code.
    # This is a Ruby interface to the design under test.
    
    # This method resets the design under test.
    def Counter.reset!
      # assert the reset signal for five clock cycles
      reset.intVal = 1
      5.times {relay_verilog}
      reset.intVal = 0
    end
    

Implement the prototype

Now that we have a specification against which to verify our design, let us build a prototype of our design. By doing so, we exercise our specification, experience potential problems that may arise when we later implement our design in Verilog, and gain confidence in our work. The result of this proceess is illustrated by the example named “Ruby prototype of our Verilog design”.

Example 7. Ruby prototype of our Verilog design

def Counter.simulate!
  if reset.intVal == 1
    count.intVal = 0
  else
    count.intVal += 1
  end
end

important

Important: Before we continue…

Replace the contents of the files named counter_rspec_proto.rb and counter_xunit_proto.rb with the source code shown in the example named “Ruby prototype of our Verilog design”

Verify the prototype

Now that we have implemented our prototype, we are ready to verify it against our specification by running the test. This process is illustrated by the example named “Running a test with specification in rSpec format” and the example named “Running a test with specification in xUnit format”.

Example 8. Running a test with specification in rSpec format

$ rake -f counter_rspec_runner.rake cver PROTOTYPE=1

Ruby-VPI: prototype has been enabled for test "counter_rspec" 

A resetted counter's value
- should be zero
- should increment by one count upon each rising clock edge

A counter with the maximum value
- should overflow upon increment

Finished in 0.018199 seconds

3 specifications, 0 failures

Example 9. Running a test with specification in xUnit format

$ rake -f counter_xunit_runner.rake cver PROTOTYPE=1

Ruby-VPI: prototype has been enabled for test "counter_xunit" 

Loaded suite counter_xunit_bench
Started
...
Finished in 0.040668 seconds.

3 tests, 35 assertions, 0 failures, 0 errors
In these examples, the PROTOTYPE environment variable is assigned a non-empty value while running the test so that, instead of our design, our prototype is verified against our specification. You can also assign a value to PROTOTYPE before running the test, by using your shell’s export or setenv command. Finally, the GPL Cver simulator, denoted by cver, is used to run the simulation.

tip

Tip: What can the test runner do?

If you invoke the test runner (1) without any arguments or (2) with the --tasks option, it will show you a list of tasks that it can perform for you.

Implement the design

Now that we have implemented and verified our prototype, we are ready to implement our design. This is often quite simple because we translate existing code from Ruby (our prototype) into Verilog (our design). The result of this process is illustrated by the example named “Implementation of a simple up-counter with synchronous reset”.

Example 10. Implementation of a simple up-counter with synchronous reset

/**
  A simple up-counter with synchronous reset.

  @param    Size     Number of bits used to represent the counter's value.
  @param    clock    Increments the counter's value upon each positive edge.
  @param    reset    Zeroes the counter's value when asserted.
  @param    count    The counter's value.
*/
module counter #(parameter Size = 5) (
  input clock,
  input reset,
  output reg [Size - 1 : 0] count
);
  always @(posedge clock) begin
    if (reset)
      count <= 0;
    else
      count <= count + 1;
  end
endmodule

important

Important: Before we continue…

Replace the contents of the file named counter.v with the source code shown in the example named “Implementation of a simple up-counter with synchronous reset”

Verify the design

Now that we have implemented our design, we are ready to verify it against our specification by running the test. the example named “Running a test with specification in rSpec format” and the example named “Running a test with specification in xUnit format” illustrate this process.

Example 11. Running a test with specification in rSpec format

$ rake -f counter_rspec_runner.rake cver

A resetted counter's value
- should be zero
- should increment by one count upon each rising clock edge

A counter with the maximum value
- should overflow upon increment

Finished in 0.005628 seconds

3 specifications, 0 failures

Example 12. Running a test with specification in xUnit format

$ rake -f counter_xunit_runner.rake cver

Loaded suite counter_xunit_bench
Started
...
Finished in 0.006766 seconds.

3 tests, 35 assertions, 0 failures, 0 errors
In these examples, the PROTOTYPE environment variable is not specified while running the test, so that our design, instead of our prototype, is verified against our specification. You can also achieve this effect by assigning an empty value to PROTOTYPE, or by using your shell’s unset command. Finally, the GPL Cver simulator, denoted by cver, is used to run the simulation.

tip

Tip: Running multiple tests at once.

Create a file named Rakefile containing the following line.

require 'ruby-vpi/runner_proxy'

Now you can invoke all test runners in the current directory simply by executing

rake cver
(where cver denotes the GPL Cver simulator).

Examples

The samp directory contains several example tests which illustrate how Ruby-VPI can be used. Each example has an associated Rakefile which simplifies the process of running it. Therefore, simply navigate into an example directory and run the

rake
command to get started.

Hacking

Building release packages

In addition to the normal requirements, you need the following software to build release packages:

Once you have satisfied these requirements, you can run

rake release
to build the release packages. Also, see the output of
rake -T
for more build options.

Known problems

This chapter presents known problems and possible solutions. In addition, previously solved problems have been retained for historical reference.

Ruby

SystemStackError

note

Note: Fixed in 2.0.0.

This problem was fixed in release 2.0.0 (2006-04-17).

If a “stack level too deep (SystemStackError)” error occurs during the simulation, then increase the system-resource limit for stack-size by running the
ulimit -s unlimited
command before starting the simulation.

test/unit

note

Note: Fixed in 2.0.0.

This problem was fixed in release 2.0.0 (2006-04-17).

If your specification employs Ruby’s unit testing framework, then you will encounter an error saying “[BUG] cross-thread violation on rb_gc()”.

Icarus Verilog

Vpi::vpi_handle_by_name

Give full paths to Verilog objects

In version 0.8 and snapshot 20061009 of Icarus Verilog, the vpi_handle_by_name function requires an absolute path (including the name of the bench which instantiates the design) to a Verilog object. In addition, vpi_handle_by_name always returns nil when its second parameter is specified.

For example, consider the example named “Part of a bench which instantiates a Verilog design”. Here, one must write vpi_handle_by_name("TestFoo.my_foo.clk", nil) instead of vpi_handle_by_name("my_foo.clk", TestFoo) in order to access the clk input of the my_foo module instance.

Example 13. Part of a bench which instantiates a Verilog design

module TestFoo;
  reg clk_reg;
  Foo my_foo(.clk(clk_reg));
endmodule

Registers must be connected

In version 0.8 of Icarus Verilog, if you want to access a register in a design, then it must be connected to something (either assigned to a wire or passed as a parameter to a module instantiation). Otherwise, you will get a nil value as the result of vpi_handle_by_name method.

For example, suppose you wanted to access the clk_reg register, from the bench shown in the example named “Bad design with unconnected registers” If you execute the statement clk_reg = vpi_handle_by_name("TestFoo.clk_reg", nil) in a specification, then you will discover that the vpi_handle_by_name method returns nil instead of a handle to the clk_reg register.

The solution is to change the design such that it appears like the one shown in the example named “Fixed design with wired registers” where the register is connected to a wire, or the example named “Part of a bench which instantiates a Verilog design” where the register is connected to a module instantiation.

Example 14. Bad design with unconnected registers

module TestFoo;
  reg clk_reg;
endmodule

Here the clk_reg register is not connected to anything.

Example 15. Fixed design with wired registers

module TestFoo;
  reg clk_reg;
  wire clk_wire;
  assign clk_wire = clk_reg;
endmodule

Here the clk_reg register is connected to the clk_wire wire.

Vpi::reset

The vpi_control method was removed in release 3.0.0 (2006-04-23). Please use Vpi::vpi_control(VpiReset) instead.

In version 0.8 of Icarus Verilog, the vpi_control(vpiReset) VPI function causes an assertion to fail inside the simulator. As a result, the simulation terminates and a core dump is produced.

Mentor Modelsim

ruby_run();

note

Note: Fixed in 2.0.0.

This problem was fixed in release 2.0.0 (2006-04-17).

Version 6.1b of Mentor Modelsim doesn’t play nicely with either an embedded Ruby interpreter or POSIX threads in a PLI application. When Ruby-VPI invokes the ruby_run function (which starts the Ruby interpreter), the simulator terminates immediately with an exit status of 0.

Glossary

Bench

An environment in which a design is verified against a specification. Often, it is used to emulate conditions in which the design will be eventually deployed.

Behavior driven development (BDD)

An agile software development methodology which emphasizes thinking in terms of behavior when designing, implementing, and verifying software.

See the official wiki for more information.

Design

A Verilog module that is verified against a specification in order to ensure correctness or soundness of its being. In other words, it is the thing being checked: does it work or not?

Expectation

The desired response to some stimulus.

Handle

A reference to an object inside the Verilog simulation that was obtained through the vpi_handle_by_name function.

Rake

Rake is a build tool, written in Ruby, using Ruby as a build language. Rake is similar to make in scope and purpose.

Rake documentation

rSpec

The BDD framework for Ruby.

See the rSpec website and tutorial for more information.

Specification

A set of expectations which define the desired behavior of a design when it is subjected to certain stimulus.

Test driven development (TDD)

An agile software development methodology which emphasizes (1) testing functionality before implementing it and (2) refactoring.

See this introductory article for more information.

Test

Something that checks if a design satisfies a specification.

Test bench

An allusion to a bench in an electronics laboratory, or so it seems.