<% ENV['RUBYLIB'] = File.join(Dir.pwd, 'lib') # needed to run the example tests require 'lib/ruby-vpi' # local variables for this document mailing_list_url = 'http://rubyforge.org/mailman/listinfo/ruby-vpi-discuss' mailing_list_link = link(mailing_list_url, "project mailing list") pkg_url = File.join(RubyVPI::Project[:website], 'pkg') src_url = File.join(RubyVPI::Project[:website], 'src') ann_url = File.join(RubyVPI::Project[:website], 'ann') dev_url = File.join(RubyVPI::Project[:website], 'dev') log_url = File.join(RubyVPI::Project[:website], 'log') # parameters for the HTML format $title = "Ruby-VPI #{RubyVPI::Project[:version]} user guide" $authors = { 'Suraj N. Kurapati' => 'http://snk.rubyforge.org' } $feeds = { ann_url => :rss } intro_paragraph = <<-EOS.strip Ruby-VPI is a library that lets "Ruby":http://www.ruby-lang.org programs access the entire "IEEE 1364-2005 Verilog VPI":http://ieeexplore.ieee.org/xpl/standardstoc.jsp?isnumber=33945 interface supported by "major Verilog simulators":#setup.reqs.sim today. It also serves as *platform for unit testing*, rapid *prototyping*, and systems *integration* of Verilog modules through Ruby EOS %> <% abstract do %> <%= intro_paragraph %>. p=. <%= xref 'Introduction', '< Continue reading... >' %> <% paragraph "Resources" do %> * "Releases":<%= log_url %> - release notes and project news. "!images/feed-icon-28x28.png(RSS feed)!":<%= ann_url %> * "Downloads":<%= pkg_url %> - obtain the newest release package. * "Source code":<%= src_url %> - obtain via "Darcs 2":http://darcs.net or browse online. * "Reference":api/index.html - API documentation for source code. "!images/feed-icon-28x28.png(RSS feed)!":<%= dev_url %> * "Talks":http://ruby-vpi.rubyforge.org/talks/ - archive of presentations and seminars. * "Papers":http://ruby-vpi.rubyforge.org/papers/ - archive of research and publications. * "Mailing list":<%= mailing_list_url %> - ask questions, get help, and discuss. <% end %> <% end %> <% chapter "Introduction" do %> <%= intro_paragraph %>: * Create complex Verilog test benches easily and wholly in Ruby. * Apply agile software development practices to develop hardware. * Perform "specification-driven functional verification":http://ruby-vpi.rubyforge.org/papers/masters_thesis.html ("PDF version":http://ruby-vpi.rubyforge.org/papers/masters_thesis.pdf). Ruby-VPI is *open source software* (see <%= xref "License" %>) so feel free to contribute your improvements and discuss your ideas in the <%= mailing_list_link %>. See <%= xref "Hacking" %> for details. <% section "Features" do %> <% paragraph "Portable" do %> * Works on Windows, Mac OSX, GNU/Linux, and UNIX. * Supports all <%= xref "setup.reqs.sim", "major Verilog simulators" %> available today. <% end %> <% paragraph "Agile" do %> * Enables "agile practices":http://agilemanifesto.org such as ** "test-driven":http://www.testdriven.com development ** "behavior-driven":http://behaviour-driven.org development ** <%= xref 'usage.tutorial.implement-proto', "rapid prototyping" %> for design exploration * Eliminates unneccesary work: ** <%= xref 'usage.tutorial.specification', "Specifications" %> are executable, portable, and human-readable. ** <%= xref 'usage.tools.generate', "Automated test generator" %> helps you accomodate design changes with minimal effort. ** There is *absolutely no compiling*! <% end %> <% paragraph "Powerful" do %> !>images/ruby/logo-reflection.png(the Ruby logo)! * Employs the "power and elegance":http://www.ruby-lang.org/en/about/ of Ruby: ** *Unlimited length integers* ** Automatic memory management (garbage collection) ** Regular expressions ** Closures for functional programming ** Pure OOP with dynamic typing ** Portable multi-threading (green threads) ** Native system calls and I/O ** Highly readable and maintainable code * Uses "ruby-debug":http://rubyforge.org/projects/ruby-debug/ for <%= xref 'usage.debugger', "interactive debugging" %>. * Uses "rcov":http://eigenclass.org/hiki.rb?rcov for test <%= xref 'usage.runner.env-vars', "coverage analysis and report generation" %>. <% end %> <% end %> <% section "License" do %> <%=h File.read('LICENSE').gsub(/^Copyright.*$/, "\\&\n").para_join %> <% end %> <% section "Appetizers" do %> Here is a tiny sampling of code to whet your appetite. See <%= xref 'usage.tutorial', "the tutorial" %> for more samples. * Assign the value 2^2048^ to a register: # these statements are equivalent your_register.intVal = 2 ** 2048 your_register.put_value 2 ** 2048 * Check if all nets in a module are at high impedance: your_module.all_net? { |your_net| your_net.z? } # or: your_nets = your_module.net_a your_nets.all? { |net| net.z? } * See a register's path, width, and location (file & line number): puts your_register # or: p :path => your_register.fullName p :width => your_register.size p :file => your_register.fileName p :line => your_register.lineNo * Access the first five elements in a memory: # these statements are equivalent your_memory.memoryWord_a.first(5) your_memory.memoryWord_a[0..4] your_memory.memoryWord_a[0...5] your_memory.memoryWord_a[0, 5] * Clear a memory by filling it with zeroes: # these statements are equivalent your_memory.each_memoryWord { |w| w.f! } your_memory.each_memoryWord { |w| w.vpi0! } your_memory.each_memoryWord { |w| w.intVal = 0 } your_memory.each_memoryWord { |w| w.put_value 0 } <% end %> <% section "Applications" do %> Examples of tasks that can be performed with Ruby-VPI are: * From the second edition of "_The Verilog PLI Handbook_":http://www.sutherland-hdl.com/publications.html: ** C language bus-functional models ** Reading test vector files ** Delay calculation ** Custom output displays ** Co-simulation ** Design debug utilities ** Simulation analysis * Adapted from "Pin Hong's":http://embedded.eecs.berkeley.edu/Alumni/pinhong/scriptEDA/ observations: ** Writing hardware models in Ruby ** Dumping or processing netlist data from Verilog database ** Dumping or processing simulation data ** Feeding dynamic simulation stimuli ** Back-annotating delay information ** Interactive logic simulation ** Building a distributed simulation <% end %> <% section "Related works" do %> * "ANVIL":http://anvil.sourceforge.net is a C++ interface to VPI. * "Teal":http://teal.sourceforge.net is a C++ interface to VPI. * "JOVE":http://jove.sourceforge.net is a Java interface to VPI. * "ScriptEDA":http://embedded.eecs.berkeley.edu/Alumni/pinhong/scriptEDA/ is a Perl, Python, and Tcl interface to VPI. * "RHDL":http://rhdl.rubyforge.org is a hardware description and verification language based on Ruby. * "MyHDL":http://myhdl.jandecaluwe.com is a hardware description and verification language based on Python, which features conversion to Verilog and co-simulation. <% paragraph "Ye olde PLI" do %> The following projects utilize the archaic *tf* and *acc* PLI interfaces, which have been officially deprecated in IEEE Std 1364-2005. * "ScriptSim":http://www.nelsim.com is a Perl, Python, and Tcl/Tk interface to PLI. * "Verilog::Pli":http://www.veripool.com/verilog-pli.html is a Perl interface to PLI. <% end %> <% end %> <% end %> <% chapter "Setup", "setup" do %> <% section "Requirements", "setup.reqs" do %> Your system needs the following software to run Ruby-VPI. <% paragraph "Verilog simulator", 'setup.reqs.sim' do %> Ruby-VPI is known to work with the following simulators. However, you should be able to use it with any Verilog simulator that supports VPI. |_. Simulator |_. Notes | | "GPL Cver":http://www.pragmatic-c.com/gpl-cver/ (recommended) | Version 2.11a or newer is acceptable. | | "Synopsys VCS":http://www.synopsys.com/products/simulation/simulation.html | Any version that supports the -load option is acceptable. | | "Mentor Modelsim":http://www.model.com | Any version that supports the -pli option is acceptable. See <%= xref "problem.vsim" %> if you are using Modelsim version 6.2g. | | "Cadence NC-Sim":http://www.cadence.com/products/functional_ver/nc-verilog/ | Any version that supports the +loadvpi option is acceptable for Ruby-VPI versions 20.0.0 or older. See <%= xref "problem.ncsim" %> for details. | | "Icarus Verilog":http://www.geda.seul.org/tools/icarus/index.html | Version 0.8 is _mostly_ acceptable because you *will not* be able to <%= xref "vpi.handles.relatives", "access child handles through method calls" %>. See <%= xref 'problems.ivl.vpi_handle_by_name.absolute-paths' %> for details. | <% end %> <% paragraph "Compilers" do %> |_. Software |_. Notes | | "make":http://en.wikipedia.org/wiki/Make | Any flavor or distribution should be acceptable. | | C compiler | the "GCC(GNU Compiler Collection)":http://www.gnu.org/software/gcc/ is preferred, but any C compiler should be acceptable. | | "SWIG":http://www.swig.org/download.html | Version 1.3.29 or newer is required. | | "Ruby":http://www.ruby-lang.org/en/downloads/ | Version 1.8 or newer, including header and linkable object files for building extensions, is required. You can install Ruby by following "these instructions":http://www.ruby-lang.org/en/downloads/. | <% end %> <% paragraph "Libraries" do %> |_. Library |_. Notes | | "RubyGems":http://rubyforge.org/frs/?group_id=126 | Any recent version should be acceptable. You can install RubyGems by following "these instructions":http://www.rubygems.org/read/chapter/3. | <% end %> <% end %> <% section "Recommendations", "setup.recom" do %> The following software might make your interactions with Ruby-VPI more pleasant. <% paragraph "Text merging tool", "setup.recom.merger" do %> 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 <%= xref "usage.tools.generate", "automated test generator" %>. A handful of the currently available open-source text merging tools are listed below. |_. Software |_. Description | | "kdiff3":http://kdiff3.sourceforge.net/ | A graphical, three-way merging tool for KDE. | | "meld":http://meld.sourceforge.net/ | A graphical, three-way merging tool for GNOME. | | "tkdiff":http://tkdiff.sourceforge.net/ | A graphical, two-way merging tool that uses the cross-platform Tk windowing toolkit. | | "xxdiff":http://furius.ca/xxdiff/ | A graphical, three-way merging tool. | | "imediff2":http://elonen.iki.fi/code/imediff/ | A textual, fullscreen two-way merging tool. It is very useful when you are working remotely via SSH. | <% end %> <% end %> <% section "Installation", "setup.inst" do %> <% tip "Tuning for maximum performance" do %> You can tune your installation of Ruby-VPI for maximum performance by adding your C compiler's optimization flag to the @CFLAGS@ environment variable _before_ you run the installation command (shown below). For example, if your C compiler is GCC, then you can set @CFLAGS@ to -O9 for maximum optimization. <% end %> Once your system has the <%= xref "setup.reqs", "necessary requirements" %>, you can install Ruby-VPI by running the following commands:
    gem install ruby-vpi
    ruby-vpi -v
    
Alternatively, if you do not wish to use RubyGems: # Download the newest tar.gz release package from "the project download area":<%= pkg_url %>. # Extract the release package anywhere you want on your system. # Go inside the extracted directory and run the following commands:
    rake build
    ruby bin/ruby-vpi -v
    
If the installation was successful, then you will see output like this:
<%=h `ruby bin/ruby-vpi -v` %>
Otherwise, you can ask for help in the <%= mailing_list_link %>. <% section "Installing on Windows", "setup.inst.windows" do %> 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, this is not the case in Windows because we "cannot compile a shared object file with references to undefined symbols in Windows":http://sourceware.org/ml/cygwin/2001-12/msg01293.html. One solution to this problem 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. # Install "Cygwin":http://www.cygwin.com, the Linux-like environment for Windows. # Search for object files whose names end with .so, .o, or .dll in your Verilog simulator's installation directory. # Determine which object files, among those found in the previous step, contain symbols whose names begin with "_vpi" by running the following command in Cygwin:
for x in *.{o,so,dll}; do nm $x | grep -q '[Tt] _vpi' && echo $x; done
** If you are using Mentor Modelsim, the desired object file can be found at a path similar to C:\Modeltech\win32\libvsim.dll. ** If you are using GPL Cver, the desired object file can be found at a path similar to C:\gplcver\objs\v_vpi.o. # Assign the path of the object file (determined in the previous step) to the @LDFLAGS@ environment variable. For example, if the object file's path is /foo/bar/vpi.so, then you would run the following command in Cygwin:
export LDFLAGS=/foo/bar/vpi.so
# You may now install Ruby-VPI by running the following command in Cygwin:
gem install ruby-vpi
<% end %> <% end %> <% section "Maintenance", "setup.maintenance" do %> You can upgrade to the latest release of Ruby-VPI by running the following command: pre. gem update ruby-vpi You can uninstall Ruby-VPI by running the following command: pre. gem uninstall ruby-vpi Learn more about using RubyGems in "the RubyGems user guide":http://www.rubygems.org. <% end %> <% section "Manifest", "setup.manifest" do %> Now that Ruby-VPI is installed on your system, let us examine its installation directory. * If you installed Ruby-VPI manually, then you already know the location of its installation directory. * If you installed Ruby-VPI using RubyGems, then run
ruby-vpi -v
and select the right-most item in the output--that is the path of Ruby-VPI's installation directory. Inside Ruby-VPI's installation directory, you will see (among other things) the following items: * bin/ - contains executable programs (see <%= xref "usage.tools" %>). * doc/ - contains user documentation in various formats. * ref/ - contains reference API documentation in HTML format. * examples/ - contains example Ruby-VPI tests (see <%= xref "usage.examples" %>). * ext/ - contains source code, written in the C language, for the <%= xref "organization", "core of Ruby-VPI" %>. * lib/ - contains Ruby libraries provided by Ruby-VPI. <% end %> <% end %> <% chapter "Background", "organization" do %> Ruby-VPI is a bridge between IEEE 1364-2005 Verilog VPI and the Ruby language. It enables Ruby programs to use VPI either (1) in the same, verbose way that C programs do, or (2) in a simpler, higher level way. <% figure "Where does Ruby-VPI fit in?", "fig:organization.detail" do %> !figures/organization_detailed.png! <% end %> As <%= xref "fig:organization.detail" %> shows, Ruby-VPI is composed of two complementary parts: one interacts with VPI through the C language, while the other interacts with an executable specification written in the Ruby language. The former is complied during installation to produce dynamically loadable C libraries---each tailored to accommodate the quirks of its respective Verilog simulator. The latter is not compiled because Ruby programs are interpreted dynamically. <% section "Motivation" do %> If you would like to know why Ruby-VPI developed, please read this "motivation section":http://ruby-vpi.rubyforge.org/papers/masters_thesis.html#tth_sEc5.2 of my masters thesis. <% end %> <% section "Tests", "organization.tests" do %> In Ruby-VPI, the process of functional verification is neatly packaged into self-contained, executable tests. As <%= xref "fig:organization" %> illustrates, a test is composed of a *bench*, a *design*, and a *specification*. <% figure "Organization of a test in Ruby-VPI", "fig:organization" do %> !figures/organization.png! <% end %> *The bench* is Ruby-VPI. It defines the environment in which functional verification takes place. This is analogous to a workbench in an electronics laboratory that is furnished with tools of measurement and manipulation such as oscilloscopes, voltmeters, soldering irons, and so on which enable engineers to verify electronic components and locate the source of defects within those components. *The design* is an instantiated Verilog module. To extend the analogy of the electronics laboratory, it corresponds to the electronic component that is verified by an engineer. *The specification* is a Ruby program. In the electronics laboratory analogy, it corresponds to the engineer who inspects, manipulates, and verifies the electronic component. In terms of specification-driven functional verification, it corresponds to the executable specification. <% end %> <% end %> <% chapter "Usage", "usage" do %> <% section "Theory of operation", 'usage.theory' do %> When you run a Ruby-VPI test, the following chain reaction occurs. <% paragraph "Rake (via the Rakefile)" do %> # Specifies a user-defined Ruby script that will be loaded by Ruby-VPI once the simulator has been launched. # Determines where all necessary Verilog modules & Verilog libraries are and launches the Verilog simulator with this knowledge. <% end %> <% paragraph "Verilog simulator" do %> # Launches the Ruby interpreter and loads Ruby-VPI into it. <% end %> <% paragraph "Ruby-VPI" do %> # Establishes the <%= xref 'vpi', "basic verification environment" %> (the nice library for <%= xref 'vpi.handles', "working with VPI handles" %>, and so on). # Loads the user-defined Ruby script that was specified by Rake. <% end %> <% paragraph "User-defined Ruby script" do %> # Determines what Verilog modules are going to be tested. # Determines what Ruby files are going to do the testing. # Associates them together and starts the simulation. For example, consider this user-defined Ruby script: designHandle = vpi_handle_by_name("whatever", nil) testFiles = Dir['path/to/files/*.whatever'] RubyVPI.load_test( designHandle, testFiles ) Here, the @RubyVPI.load_test@ method will: # Create a temporary module (a sandbox). # Define a constant named @DUT@ inside the sandbox. # Load all the test files into the sandbox. In this manner, we can (1) load as many tests into the simulation as we wish and (2) use any files we want (and organize them however we like) to perform the testing. <% end %> <% section "Test files" do %> Ruby-VPI tests (when produced by the <%= xref "usage.tools.generate", "automated test generator" %>) are typically composed of the following files. * runner.rake ** Launches the Verilog simulator, loads Ruby-VPI into it, and executes the user-defined Ruby script. * design.rb ** Defines convenience methods on the @DUT@ object. ** May define other data structures to aid the testing. * proto.rb ** Uses the <%= xref 'usage.concurrency', "concurrency model" %> to emulate the design under test's Verilog implementation. * spec.rb ** Does some tests on the @DUT@ object. ** If you want to test multiple Verilog objects, then simply use the @vpi_handle_by_name()@ function to get access to the Verilog objects you want and proceed as usual. * loader.rb ** The user-defined Ruby script which loads the test. Note that because the user-defined Ruby script (loader.rb among the files above) decides what files to load, you are free to organize your tests however you like. As a result, the files presented above are a mere convention that you can _choose_ to follow. <% end %> <% end %> <% section "Interacting with the Verilog simulator", "overview.relay" do %> In a typical VPI application written in C, the _Verilog simulator_ is in charge. Verilog code temporarily transfers control to C by invoking C functions, which return control to Verilog when they finish. In contrast, Ruby-VPI puts the _specification_ in charge. The specification temporarily transfers control to the Verilog simulator by invoking the @advance_time@ method, which returns control to the specification after a given number of time steps. This process is illustrated in <%= xref "fig:ruby_relay" %>. You can also use the @wait@ method, which is just an alias to the @advance_time@ method, if you prefer. Ruby-VPI's approach is the same as any software testing framework, where the _specification_ drives the design under test. In contrast, the VPI & C approach is literally _backwards_ because the design under test drives the specification. <% figure "Interaction between Ruby and Verilog", "fig:ruby_relay" do %> !figures/ruby_relay.png! # The current simulation time is _X_. # The specification invokes the @advance_time@ method with parameter _Y_, which specifies the number of simulation time steps to be simulated. # The Verilog simulator is now in control (temporarily). # The current simulation time has _not_ changed; it is still _X_. # The Verilog simulator simulates _Y_ simulation time steps. # The current simulation time is now _X + Y_. # The Verilog simulator returns control back to the specification. <% end %> Another means of transferring control from the specification to the Verilog simulator is the <%= xref "vpi.callbacks", "VPI callback" %>. <% end %> <% section "VPI in Ruby", "vpi" do %> Ruby-VPI provides the _entire_ IEEE Std 1364-2005 VPI interface to Ruby. This section will show you how to make use of it. <% note "Constants are capitalized in Ruby" do %> In the remainder of this guide, you may be surprised to see that VPI constants such as @vpiIntVal@ are written with a captialized name, as @VpiIntVal@. The reason for this discrepancy is that in Ruby, the names of constants are capitalized. However, keep in mind that Ruby-VPI provides all VPI constants in both (1) their original, uncapitalized form and (2) their capitalized Ruby form. You may use either version according to your preference; they are functionally equivalent. <% end %> <% section "Handles", "vpi.handles" do %> A *handle* is a reference to an object (such as a module, register, wire, and so on) inside the Verilog simulation. Handles allows you to inspect and manipulate the design under test and its internal components. They are instances of the @VPI::Handle@ class (see "reference documentation":api/ruby/classes/VPI/Handle.html for details) in Ruby-VPI. Handles have various *properties*, listed in the second column of <%= xref "tbl:accessors" %>, which provide different kinds of information about the underlying Verilog objects they represent. These properties are accessed through the VPI functions listed in the last column of <%= xref "tbl:accessors" %>. Handles are typically obtained through the @vpi_handle_by_name@ and @vpi_handle@ functions. These functions are hierarchical in nature, as they allow you to obtain new handles that are related to existing ones. For example, to obtain a handle to a register contained within a module, one would typically write: @your_reg = vpi_handle( VpiReg, your_handle )@ <% paragraph "Shortcuts for productivity" do %> Given a handle, Ruby-VPI allows you to access (1) its relatives and (2) its properties simply by invoking methods on the handle. If a handle's relative happens to have the same name as one its properties, then the relative is given priority because a handle's properties can always be accessed explicitly through the @handle.get_value@ and @handle.put_value@ methods. <% end %> <% section "Accessing a handle's relatives", "vpi.handles.relatives" do %> Imagine that the design under test, say _foo_, instantiated a Verilog module named _bar_, which in turn contained a register named _baz_. To access baz from Ruby, one could employ VPI idioms by writing: foo = vpi_handle_by_name( "foo", nil ) bar = vpi_handle_by_name( "bar", foo ) baz = vpi_handle_by_name( "baz", bar ) or by writing: baz = vpi_handle_by_name( "foo.bar.bar", nil ) These idioms seem excessively verbose in a higher level language such as Ruby, so Ruby-VPI allows you to access a handle's relative by simply invoking the relative's name as a method on the handle: foo.bar.baz <% end %> <% section "Accessing a handle's properties" do %> Imagine that the design under test, say _foo_, contained a register named _bar_. To access the integer value of _bar_ in Ruby-VPI, one could employ VPI idioms by writing: wrapper = S_vpi_value.new wrapper.format = VpiIntVal vpi_get_value( foo.bar, wrapper ) result = wrapper.value.integer or, if _bar_ is capable of storing more than 32 bits, one would convert a string representation of bar's integer value into a limitless Ruby integer by writing: wrapper = S_vpi_value.new wrapper.format = VpiHexStrVal vpi_get_value( foo.bar, wrapper ) result = wrapper.value.str.to_i( 16 ) These idioms seem excessively verbose in a higher level language such as Ruby, so Ruby-VPI allows you to access a handle's properties by simply invoking property names, using the special naming format shown in <%= xref "fig:method naming format" %>, as methods on the handle: result = foo.bar.intVal <% end %> <% figure "Method naming format for accessing a handle's properties", "fig:method naming format" do %> |_. Operation |_. _ |_. Property |_. _ |_. Accessor |_. Addendum | |\2. optional | required |\3. optional | * *Operation* suggests a method that should be invoked in the context of the *Property* parameter. All methods in "Ruby's @Enumerable@ module":http://www.ruby-doc.org/core/classes/Enumerable.html are valid operations. * *Property* suggests a VPI property that should be accessed. The "vpi" prefix, which is common to all VPI properties, can be omitted if you wish. For example, the VPI property "vpiFullName" is considered equivalent to "fullName" and "FullName", but not equivalent to "full_name". * *Accessor* suggests a VPI function that should be used in order to access the VPI property. When this parameter is not specified, Ruby-VPI will attempt to _guess_ the value of this parameter. <%= xref "tbl:accessors" %> shows a list of valid accessors and how they influence the means by which a property is accessed. * When *Addendum* is an equal sign (=), it suggests that the specified VPI property should be written to. When it is a question mark (?), it suggests that the specified VPI property should be accessed as a boolean value. This suggestion is the same as specifying "b" as the *Accessor*. <% end %> <% table "Possible accessors and their implications", "tbl:accessors" do %> |_. 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@ | | a | array | @vpi_iterate@ | <% end %> <% table "Examples of accessing a handle's properties", "ex:properties" do %> |_/2. Ruby expression |_\6. Method naming format |_/2. Description | |_. Operation |_. _ |_. Property |_. _ |_. Accessor |_. Addendum | | @handle.vpiIntVal@ |   |   | vpiIntVal |   |   |   |/4. Obtain 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 |   |   | = |/4. Assign the integer 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 |   |   |   |/4. Obtain 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 |   |   |   |/6. Obtain 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 |   |   |   |/4. Obtain 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 |   |   |   |/4. Obtain 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 |   |   |   |/2. Use the @each@ operation to 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 |   |   |   |/2. Use the @all?@ operation to check whether all @VpiReg@ objects associated with the handle are capable of storing only one bit of information. | | handle.all_reg? {|reg| reg.size == 1} | all? | _ | reg |   |   |   | | handle.select_vpiNet {|net| net.x?} | select | _ | VpiNet |   |   |   |/2. Use the @select@ operation to obtain a list of @VpiNet@ objects whose _logic value_ is unknown (x).| | handle.select_net {|net| net.x?} | select | _ | net |   |   |   | <% end %> <% end %> <% section "Callbacks", "vpi.callbacks" do %> A _callback_ is a mechanism that makes the Verilog simuluator execute a block of code (known as a "callback handler") when some prescribed event occurs in the simulation. Callbacks are added using the @vpi_register_cb@ function and removed using the @vpi_remove_cb@ function. However, instead of storing the address of a C function in the @cb_rtn@ field of the @s_cb_data@ structure (as you would do in C) you pass a block of code to the @vpi_register_cb@ method in Ruby. This block will be executed whenever the callback occurs. <% example "Using a callback for value change notification", "ex:callback" do %> This example shows how to use a callback for notification of changes in a handle's @VpiIntVal@ property. When you no longer need this callback, you can tear it down using @vpi_remove_cb@. In this example, the handle being monitored is the @Counter.count@ signal from <%= xref "fig:counter.v_decl" %>. time = S_vpi_time.new time.type = VpiSimTime time.low = 0 time.high = 0 value = S_vpi_value.new value.format = VpiIntVal alarm = S_cb_data.new alarm.reason = CbValueChange alarm.obj = Counter.count alarm.time = time alarm.value = value alarm.index = 0 vpi_register_cb( alarm ) do |info| time = info.time.integer count = info.value.value.integer puts "hello from callback! time=#{time} count=#{count}" end Append this code to the RSpec/counter_spec.rb file (provided in <%= xref "usage.examples" %> and discussed in <%= xref "usage.tutorial.specification" %>) and run the <%= xref "usage.tutorial", "counter_RSpec test" %> <% end %> <% end %> <% end %> <% section "Concurrency", "usage.concurrency" do %> Ruby-VPI provides a concurrency model that allows you to run blocks of code in parallel. These blocks of code are known as _concurrent processes_ and they are equivalent to the "initial", "always" and "forever" blocks in Verilog. Ruby-VPI's concurrency model imposes two important constraints, which are inspired by "GPGPU and fragment/vertex shader programming":http://en.wikipedia.org/wiki/GPGPU, in order to avoid race conditions and to make parallel programming simpler. First, *all processes execute in the _same_ time step*. That is, we only advance the _entire_ simulation to the next time step when _all_ processes are finished with the current time step. In this manner, we avoid race conditions where a process advances the entire simulation to a future time step but the other processes still think they are executing in the original time step (because they were not notified of the advancement). Second, *all processes see the _same_ input* (the state of the simulation database at the start of the current time step) while executing in a time step. That is, when a process modifies the simulation database, say, by changing the logic value of a register, the modification only takes effect at the _end_ of the current time step. In this manner, we avoid race conditions where one process modifies the simulation midflight but some/all of other processes are unaware of that modification (because they were not notified of its occurence). Note that these constraints are automatically enforced by Ruby-VPI. As a user, you need not do anything extra to implement or support these constraints. <% caution "Assignments inside processes are non-blocking" do %> As a result of the constraints described above, all assignments inside processes are treated like Verilog's *non-blocking assignments*. Think about it: blocking assignments allow a process to make changes to simulation values (possibly) before other processes read those values. Since the second constraint forces all processes to see the _same_ input while they are executing, it is impossible to support blocking assignments inside processes. <% end %> <% section "Creating a concurrent process" do %> You can create a concurrent proceess by passing a block of code to the @process@ method. Once the process finishes executing this block of code, it will disappear automatically. This behavior mimics the "initial" blocks of the Verilog language. You can create concurrent processes that _loop forever_ by passing a block of code to the @always@ and @forever@ methods, which mimic the "always" and "forever" blocks, respectively, of the Verilog language. <% example 'An edge-triggered "always" block' do %> Suppose you have the following Verilog code: always @(posedge clock1 and negedge clock2) begin foo <= foo + 1; bar = bar + 5; // treated as NON-blocking in prototype end In Ruby-VPI, this code would be written as: always do wait until clock.posedge? and clock2.negedge? foo.intVal += 1 bar.intVal += 5 # this is a NON-blocking assignment! end <% end %> <% example 'A change-triggered (combinational) "always" block' do %> Suppose you have the following Verilog code: always @(apple, banana, cherry, date) begin $display("Yum! Fruits are good for health!"); end In Ruby-VPI, this code would be written as: always do wait until apple.change? or banana.change? or cherry.change? or date.change? puts "Yum! Fruits are good for health!" end Or, if you are lazy like I am, you can express the sensitivity list programatically: always do wait until [apple, banana, cherry, date].any? {|x| x.change?} puts "Yum! Fruits are good for health!" end <% end %> <% end %> <% end %> <% section "Prototyping", "usage.prototyping" do %> Ruby-VPI enables you to rapidly prototype your designs in Ruby without having to do full-scale implementations in Verilog. This lets you explore and evaluate different design choices quickly. The prototyping process is completely transparent: there is absolutely no difference, in the eyes of your executable specification, between a real Verilog design or its Ruby prototype. In addition, the prototyping process is completely standard-based: Ruby prototypes emulate the behavior of real Verilog designs using _nothing more_ than the VPI itself. For example, compare the Verilog design shown in <%= xref "fig:counter.v_impl" %> with its Ruby prototype shown in figure <%= xref "fig:counter_proto.rb" %>. The prototype uses only VPI to (1) detect changes in its inputs and (2) manipulate its outputs accordingly. In addition, notice how well the prototype's syntax reflects the intended behavior of the Verilog design. This similarity facilitates rapid translation of a prototype from Ruby into Verilog later in the design process. <% section "Creating a prototype" do %> # Start with a <%= xref "usage.tutorial.declare-design", "Verilog module declaration" %> for your design. # <%= xref "usage.tutorial.generate-test", "Generate a test" %> using that module declaration. # <%= xref "usage.tutorial.implement-proto", "Implement the prototype" %> in the generated proto.rb file. # <%= xref "usage.tutorial.test-proto", "Verify the prototype" %> against its specification. Once you are satisfied with your prototype, you can proceed to <%= xref "usage.tutorial.implement-design", "implement your design in Verilog" %>. This process is often a simple translation your Ruby prototype into your Verilog. At the very least, your prototype serves as a reference while you are implementing your Verilog design. Once your design has been implemented in Verilog, you can use the _same_ specification, which was originally used to verify your prototype, to verify your Verilog design (see <%= xref "usage.runner" %> for details). <% end %> <% end %> <% section "Interactive debugging", "usage.debugger" do %> The "ruby-debug project":http://www.datanoise.com/articles/category/ruby-debug serves as the interactive debugger for Ruby-VPI. # Enable the debugger by activating the @DEBUGGER@ environment variable (see <%= xref "usage.runner" %> for details). # Put the @debugger@ command in your code -- anywhere you wish to activate an interactive debugging session. These commands are automatically ignored when the debugger is disabled; so you can safely leave them in your code, if you wish. <% section "Advanced initialization", "usage.debugger.init" do %> By default, Ruby-VPI enables the debugger by invoking the @Debugger.start@ method. If you wish to perform more advanced initialization, such as having the debugger accept remote network connections for interfacing with a remote debugging session or perhaps with an IDE (see "the ruby-debug documentation":http://www.datanoise.com/articles/category/ruby-debug for details), then: # Deactivate the @DEBUG@ environment variable. # Put your own code, which initializes the debugger, at the top of your test's spec.rb file. <% end %> <% end %> <% section "Test runner", "usage.runner" do %> A test runner is a file, generated by the <%= xref "usage.tools.generate", "automated test generator" %> whose name ends with .rake. It helps you run generated tests -- you can think of it as a _makefile_ if you are familiar with C programming in a UNIX environment. When you invoke a test runner without any arguments, it will show you a list of available tasks:
% rake -f your_test_runner.rake

    <%= `rake -f examples/counter/RSpec/counter_runner.rake` %>
<% section "Environment variables", "usage.runner.env-vars" do %> Test runners support the following _environment_ variables, which allow you to easily change the behavior of the test runner. * @PROTOTYPE@ enables the Ruby prototype for the design under test so that the prototype, rather than the real Verilog design, is verified by the specification. * @COVERAGE@ enables code coverage analysis and generation of code coverage reports. * @PROFILER@ enables the "ruby-prof":http://ruby-prof.rubyforge.org Ruby code profiler, which collects statistics on the runtime usage of the source code. This data allows you to identify performance bottlenecks. * @DEBUGGER@ enables the <%= xref "usage.debugger", "interactive debugger" %> in its "post-mortem debugging mode":http://www.datanoise.com/articles/2006/12/20/post-mortem-debugging. To activate these variables, simply assign the number 1 to them. For example, @DEBUGGER=1@ activates the @DEBUGGER@ variable. To deactivate these variables, simply assign a different value to them or *unset* them in your shell. For example, both @DEBUGGER=0@ and @DEBUGGER=@ dectivate the @DEBUGGER@ variable. <% section "Variables as command-line arguments" do %> You can specify variable assignments as arguments to the *rake* command. For example,
rake DEBUGGER=1
is equivalent to
        DEBUGGER=1
        export DEBUGGER
        rake
        
in Bourne shell or
        setenv DEBUGGER 1
        rake
        
in C shell. <% end %> <% example "Running a test with environment variables" do %> Below, we enable the prototype and code coverage analysis:
rake -f your_test_runner.rake PROTOTYPE=1 COVERAGE=1
Below, we _disable_ the prototype and enable the code coverage analysis. These invocations are equivalent if the @PROTOTYPE@ environment variable is unset.
        rake -f your_test_runner.rake PROTOTYPE=0 COVERAGE=1
        rake -f your_test_runner.rake PROTOTYPE=  COVERAGE=1
        rake -f your_test_runner.rake COVERAGE=1
        
<% end %> <% end %> <% end %> <% section "Tools", "usage.tools" do %> The *ruby-vpi* command serves as a front-end to the tools provided by Ruby-VPI. You can see its help information (reproduced below) by simply running the command without any arguments.
<%= `ruby bin/ruby-vpi` %>
<% section "Automated test generation", "usage.tools.generate" do %> The *generate* tool generates scaffolding for Ruby-VPI tests from Verilog module declarations (written in either Verilog 2001 or Verilog 95 style). A Ruby-VPI test is composed of the following files: * runner.rake runs the test by starting a Verilog simulator and loading Ruby-VPI into it. * spec.rb is the executable specification for the design under test. * design.rb is an optional file that provides convenience methods for controlling the design under test. * proto.rb is an optional file that defines a Ruby prototype of the design under test. * loader.rb is a user-defined Ruby script which loads the test (see <%= xref 'usage.theory' %>). * Rakefile is an optional file that recursively executes all runner.rake files found immediately within or beneath the current directory. It lets you simply run
rake ...
instead of having to write
rake -f runner.rake ...
every time. As <%= xref "fig:generate-test.RSpec" %> shows, the name of each generated file is prefixed with the name of the Verilog module for which the test was generated. This convention helps organize tests within the file system, so that they are readily distinguishable from one another. <% caution "Do not rename generated files" do %> Ruby-VPI uses the convention described above to dynamically create a direct Ruby interface to the design under test, so _do not_ rename the generated files arbitrarily. <% end %> By producing multiple files, the automated test generator physically decouples the various parts of a test. As a result, when the interface of a Verilog module changes, you can simply regenerate the test to incorporate those changes without diverting your focus from the task at hand. Furthermore, the incorporation of changes can be catalyzed by interactive text merging tools, which allow you to selectively accept or reject the merging of changes into your source code. Fully automated text merging tools may also be used for this purpose. You can try this tool by running the
ruby-vpi generate --help
command. <% tip "Using *kdiff3* with the automated test generator." do %> # Create a file named merge2 with the following content: #!/bin/sh # args: old file, new file kdiff3 --auto --output "$2" "$@" # Make the file executable by running the
chmod +x merge2
command. # Place the file somewhere accessible by your @PATH@ environment variable. # 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. <% end %> <% end %> <% section "Verilog to Ruby conversion", "usage.tools.convert" do %> The *convert* tool can be used to convert Verilog header files into Ruby. You can try it by running the
ruby-vpi convert --help
command. By converting Verilog header files into Ruby, your test can utilize the same @`define@ constants that are used in the Verilog design. <% end %> <% end %> <% section "Tutorial", "usage.tutorial" do %> # <%= xref "usage.tutorial.declare-design", "Declare a design" %> using Verilog 2001 syntax. # <%= xref "usage.tutorial.generate-test", "Generate a test" %> for the design using the <%= xref "usage.tools.generate", "automated test generator" %> tool. # <%= xref "usage.tutorial.specification", "Identify your expectations" %> for the design and implement them in the specification. # (Optional) <%= xref "usage.tutorial.implement-proto", "Implement the prototype" %> of the design in Ruby. # (Optional) <%= xref "usage.tutorial.test-proto", "Verify the prototype" %> against the specification. # <%= xref "usage.tutorial.implement-design", "Implement the design" %> in Verilog once the prototype has been verified. # <%= xref "usage.tutorial.test-design", "Verify the design" %> against the specification. <% section "Start with a Verilog design", "usage.tutorial.declare-design" do %> First, we need a Verilog design to test. In this tutorial, <%= xref "fig:counter.v_decl" %> will serve as our design under test. Its interface is composed of the following parts: * @Size@ defines the number of bits used to represent the counter's value. * @clock@ causes the @count@ register to increment whenever it reaches a positive edge. * @reset@ causes the @count@ register to become zero when asserted. * @count@ is a register that contains the counter's value. <% example "Declaration of a simple up-counter with synchronous reset", "fig:counter.v_decl" do %> module counter #(parameter Size = 5) ( input clock, input reset, output reg [Size-1 : 0] count ); endmodule <% end %> Before we continue, save the source code shown in <%= xref "fig:counter.v_decl" %> into a file named counter.v. <% end %> <% section "Generate a test", "usage.tutorial.generate-test" do %> Now that we have a Verilog design to test, we shall use the <%= xref "usage.tools.generate", "generate" %> tool to generate some scaffolding for our test. This tool allows us to implement our specification using RSpec, xUnit, or any other format. Each format represents a different software development methodology: * RSpec represents <%= xref "glossary.BDD", "BDD" %> * xUnit represents <%= xref "glossary.TDD", "TDD" %> * our own format can represent another methodology In this tutorial, you will see how both RSpec and xUnit formats are used. So let us make separate directories for both formats to avoid generated tests from overwriting each other:
      mkdir RSpec xUnit
      cp counter.v RSpec
      cp counter.v xUnit
      
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 <%= xref "fig:generate-test.RSpec" %> and <%= xref "fig:generate-test.xUnit" %>. <% example "Generating a test with specification in RSpec format", "fig:generate-test.RSpec" do %>
        $ ruby-vpi generate counter.v --RSpec

          module  counter
          create  counter_runner.rake
          create  counter_design.rb
          create  counter_proto.rb
          create  counter_spec.rb
          create  Rakefile
        
<% end %> <% example "Generating a test with specification in xUnit format", "fig:generate-test.xUnit" do %>
        $ ruby-vpi generate counter.v --xUnit

          module  counter
          create  counter_runner.rake
          create  counter_design.rb
          create  counter_proto.rb
          create  counter_spec.rb
          create  Rakefile
        
<% end %> <% end %> <% section "Specify your expectations", "usage.tutorial.specification" do %> So far, the test generation tool has created a basic foundation for our test Now we must build upon this foundation by identifying our <%= xref "glossary.expectation", "expectation" %> of the design under test. That is, how do we expect the design to _behave_ under certain conditions? Here are some reasonable expectations for our simple counter: * A resetted counter's value should be zero. * A resetted counter's value should increment by one count upon each rising clock edge. * A counter with the maximum value should overflow upon increment. 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 <%= xref "fig:RSpec/counter_spec.rb" %> and <%= xref "fig:xUnit/counter_spec.rb" %>. <% example "Specification implemented in RSpec format", "fig:RSpec/counter_spec.rb" do %> <%= File.read('examples/counter/RSpec/counter_spec.rb') %> <% end %> <% example "Specification implemented in xUnit format", "fig:xUnit/counter_spec.rb" do %> <%= File.read('examples/counter/xUnit/counter_spec.rb') %> <% end %> Before we continue, # Replace the contents of the file named RSpec/counter_spec.rb with the source code shown in <%= xref "fig:RSpec/counter_spec.rb" %>. # Replace the contents of the file named xUnit/counter_spec.rb with the source code shown in <%= xref "fig:xUnit/counter_spec.rb" %>. <% end %> <% section "Implement the prototype", "usage.tutorial.implement-proto" do %> 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 <%= xref "fig:counter_proto.rb" %>. <% example "Ruby prototype of our Verilog design", "fig:counter_proto.rb" do %> <%= File.read('examples/counter/RSpec/counter_proto.rb') %> <% end %> Before we continue, replace the contents of the files named RSpec/counter_proto.rb and xUnit/counter_proto.rb with the source code shown in <%= xref "fig:counter_proto.rb" %>. <% end %> <% section "Verify the prototype", "usage.tutorial.test-proto" do %> 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 <%= xref "fig:test-proto.RSpec" %> and <%= xref "fig:test-proto.unit-test" %>. In these examples, the @PROTOTYPE@ environment variable is assigned the value 1 while running the test so that, instead of our design, our prototype is verified against our specification (see <%= xref "usage.runner.env-vars" %> for details). Also, the <%= xref "setup.reqs", "GPL Cver simulator" %> denoted by _cver_, is used to run the simulation. <% example "Running a test with specification in RSpec format", "fig:test-proto.RSpec" do %>
        $ cd RSpec
        $ rake cver PROTOTYPE=1

        Ruby-VPI: prototype is enabled
        ...

        Finished in 0.05106 seconds

        3 examples, 0 failures
        cd -
        
<% end %> <% example "Running a test with specification in xUnit format", "fig:test-proto.unit-test" do %>
        $ cd xUnit
        $ rake cver PROTOTYPE=1

        Ruby-VPI: prototype is enabled
        Loaded suite counter
        Started
        ...
        Finished in 0.043859 seconds.

        3 tests, 35 assertions, 0 failures, 0 errors
        
<% end %> <% tip "What can the test runner do?" 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. <% end %> <% end %> <% section "Implement the design", "usage.tutorial.implement-design" do %> 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 <%= xref "fig:counter.v_impl" %>. <% example "Implementation of a simple up-counter with synchronous reset", "fig:counter.v_impl" do %> <%= File.read('examples/counter/counter.v') %> <% end %> Before we continue, replace the contents of the files named RSpec/counter.v and xUnit/counter.v with the source code shown in <%= xref "fig:counter.v_impl" %> <% end %> <% section "Verify the design", "usage.tutorial.test-design" do %> Now that we have implemented our design we are ready to verify it against our specification by running the test <%= xref "fig:test-design.RSpec" %> and <%= xref "fig:test-design.unit-test" %> illustrate this process. 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 <%= xref "setup.reqs", "GPL Cver simulator" %> denoted by _cver_, is used to run the simulation. <% example "Running a test with specification in RSpec format", "fig:test-design.RSpec" do %>
        $ cd RSpec
        $ rake cver

        ...

        Finished in 0.041198 seconds

        3 examples, 0 failures
        
<% end %> <% example "Running a test with specification in xUnit format", "fig:test-design.unit-test" do %>
        $ cd xUnit
        $ rake cver

        Loaded suite counter
        Started
        ...
        Finished in 0.040262 seconds.

        3 tests, 35 assertions, 0 failures, 0 errors
        
<% end %> <% end %> <% section "More examples", "usage.examples" do %> The examples directory ("browse it online":<%= src_url %>/examples/) 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. <% end %> <% end %> <% end %> <% chapter "Hacking", "hacking" do %> <% section "Building from source code", "hacking.build" do %> Obtain the source code from the project "Darcs":http://darcs.net repository: darcs get http://ruby-vpi.rubyforge.org/src ruby-vpi Go inside the obtained directory and run the following commands: rake build ruby bin/ruby-vpi -v If the commands were successful, then you will see output like this:
<%=h `ruby bin/ruby-vpi -v` %>
Otherwise, you can ask for help in the <%= mailing_list_link %>. <% end %> <% section "Installing without really installing" do %> After successfully building from source (see <%= xref "hacking.build" %>), set the @RUBYLIB@ environment variable to the path where you checked out the source code _plus_ the lib/ directory. For example, if you checked out the source code into /home/foo/ruby-vpi/ then you would set the value of the @RUBYLIB@ environment variable to /home/foo/ruby-vpi/lib/. Afterwards, any Ruby-VPI tests you run will use the checked-out source code directly. <% end %> <% section "Editing this guide", "hacking.guide" do %> The doc/guide.erb file contains the source code of this guide. You must install "Gerbil":http://gerbil.rubyforge.org before you can run the
rake doc
command to automatically generate the HTML documentation you are currently viewing. <% end %> <% section "Building release packages", "hacking.release-packages" do %> In addition to the <%= xref "setup.reqs", "normal requirements" %> you need the following software to build release packages: * "Gerbil":http://gerbil.rubyforge.org - extensible document generator Once you have satisfied these requirements, you can run the following command to build the release packages:
rake release
For more build options, see below:
$ rake -T
    <%=h `rake -T` %>
<% end %> <% end %> <% chapter "Known problems", "problems" do %> This chapter presents known problems and possible solutions. <% section "Icarus Verilog", "problem.ivl" do %> The following sections describe problems that occur when Icarus Verilog is used with Ruby-VPI. <% section "Give full paths to Verilog objects", "problems.ivl.vpi_handle_by_name.absolute-paths" do %> 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 <%= xref "ex:TestFoo" %>. 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 "Part of a bench which instantiates a Verilog design", "ex:TestFoo" do %> module TestFoo; reg clk_reg; Foo my_foo(.clk(clk_reg)); endmodule <% end %> <% end %> <% section "Registers must be connected", "problems.ivl.vpi_handle_by_name.connect-registers" do %> 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 <%= xref "ex:TestFoo_bad" %> 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 <%= xref "ex:TestFoo_fix" %> where the register is connected to a wire, or <%= xref "ex:TestFoo" %> where the register is connected to a module instantiation. <% example "Bad design with unconnected registers", "ex:TestFoo_bad" do %> Here the @clk_reg@ register is not connected to anything. module TestFoo; reg clk_reg; endmodule <% end %> <% example "Fixed design with wired registers", "ex:TestFoo_fix" do %> Here the @clk_reg@ register is connected to the @clk_wire@ wire. module TestFoo; reg clk_reg; wire clk_wire; assign clk_wire = clk_reg; endmodule <% end %> <% end %> <% section "VPI::reset", "problems.ivl.vpi_reset" do %> 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. <% end %> <% end %> <% section "Cadence NC-Sim", "problem.ncsim" do %> <% paragraph "Problem" do %> Using RubyVPI 21.0.0 (or a newer version) to test a real Verilog module (as opposed to a <%= xref "usage.prototyping", "Ruby prototype of a Verilog module" %>) with the 64-bit Cadence NC-Verilog 05.83-s003 causes the simulator to crash. <% end %> <% paragraph "Solution" do %> Use RubyVPI 20.0.0 or an older version. <% end %> <% paragraph "Discussion" do %> The problem is most likely an interaction issue with Ruby's threads implementation because *ncsim* worked fine with the "POSIX threads (pthreads)":http://en.wikipedia.org/wiki/Pthreads based Ruby-VPI 20.0.0. <% end %> <% end %> <% section "Mentor Modelsim", "problem.vsim" do %> <% paragraph "Problem" do %> The <%= xref "fig:RSpec/counter_spec.rb", "example RSpec-based up-counter test" %> sometimes fails randomly when run under the 64-bit Mentor Modelsim 6.2g. <% end %> <% paragraph "Solution" do %> By adding a zero-delay null statement at the beginning of the edge-triggered always block in <%= xref "fig:counter.v_impl", "the Verilog source code for the up-counter" %>, the problem goes away and the test always passes: always @(posedge clock) begin #0; // zero-delay null statement /* rest of the code */ end <% end %> <% paragraph "Discussion" do %> I think the problem is a faulty implementation of the cbAfterDelay callback in Modelsim 6.2g, where the callback sometimes takes you to the _middle_ of a time-step (after some events in the time-step have already been executed) rather than taking you to the _top_ of a time-step (before any events in that time-step have been executed). See http://rubyforge.org/pipermail/ruby-vpi-discuss/2007-October/000083.html <% end %> <% end %> <% end %> <% chapter "Glossary", "glossary" do %> <% section "Test", "glossary.test" do %> Something that checks if a <%= xref "glossary.design", "design" %> satisfies a <%= xref "glossary.specification", "specification" %> <% end %> <% section "Design", "glossary.design" do %> A Verilog module that is verified against a <%= xref "glossary.specification", "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? <% end %> <% section "Specification", "glossary.specification" do %> A set of <%= xref "glossary.expectation", "expectations" %> which define the desired behavior of a <%= xref "glossary.design", "design" %> when it is subjected to certain stimulus. <% end %> <% section "Expectation", "glossary.expectation" do %> The desired response to some stimulus. <% end %> <% section "Handle", "glossary.handle" do %> A reference to an object inside the Verilog simulation. See <%= xref "vpi.handles" %> for usage instructions. <% end %> <% section "Rake", "glossary.rake" do %> bq. Rake is a build tool, written in Ruby, using Ruby as a build language. Rake is similar to *make* in scope and purpose. p>. --"Rake documentation":http://docs.rubyrake.org <% end %> <% section "RSpec", "glossary.RSpec" do %> The <%= xref "glossary.BDD", "BDD" %> framework for Ruby. See the "RSpec website":http://rspec.rubyforge.org and "tutorial":http://rspec.rubyforge.org/documentation/index.html for more information. <% end %> <% section "Test driven development", "glossary.TDD" do %> An "agile software development methodology":http://agilemanifesto.org/ which emphasizes (1) testing functionality before implementing it and (2) refactoring. See "this introductory article":http://www.agiledata.org/essays/tdd.html for more information. <% end %> <% section "Behavior driven development", "glossary.BDD" do %> An "agile software development methodology":http://agilemanifesto.org/ which emphasizes thinking in terms of behavior when designing, implementing, and verifying software. See the "official wiki":http://behaviour-driven.org/ for more information. <% end %> <% end %>