JHDL
JHDL Version (___)

| Lab Home Page |


Circuit Visualization Tools

The documentation in this directory deals with the various tools used for circuit visualization

This page contains information on how to use the interactive stimulator.


Tutorial: Using the Interactive Stimulator

PAGE SUMMARY

Overview of the Interactive Stimulator

The interactive stimulator is a tool that can be used with your test bench to interactively (as opposed to programmatically) stimulate the top-level port wires of your design. Without an interactive stimulator, all of the values on the top-level wires must be done with calls to the put method of the Wire class within the clock method. This programmatic approach is usually a more static approach. Programmatic wire stimulation has advantages and disadvantages. On the pro side, programmatic wire stimulation allows for precise and consistent design simulation. On the con side, it hinders experimentation since the test bench usually must be recompiled after every little modification to the sequence of puts.

With the interactive stimulator you don't have to recompile your test bench in order alter the sequence of puts on port wires. The puts can be determined interactively during simulation. And the interactive stimulator also still maintains the precise and consistent advantages of statically programmed stimulation.

This tutorial describes how to the use the interactive stimulator in JHDL. There are two simple steps to using the interactive stimulator:

  1. Setting up the wires to be driven by the interactive stimulator
  2. Interacting with the interactive stimulator

Setting up the Interactive Stimulator in Your TestBench

To set up your JHDL TestBench to use the interactive stimulator, you need to import the Stimulator class. Just include the following at the top of your TestBench file:


            import byucc.jhdl.apps.Stimulator.Stimulator;
    

In addition, if you are using the Properties class to initialize put schedules, you may need to import that, or some other precursor class, as well:


            import java.util.Properties;
    

Use the new operator in Java to instance a Stimulator object. Stimulator is a subclass of Logic and will become a child cell of your testbench along with the design encapsulated by the testbench. There are several constructors available to instance the Stimulator. All constructors require a parent Cell (your TestBench). Nearly all constructors allow you to add your wires to the stimulator in the constructor itself. Several constructors also allow you to designate a Properties object or Properties file. Properties can then be used to associate a wire (indicated by its name) with a schedule sequence. See the Java API documentation for information on using the Properties class or creating a file or input stream that can be used to generate a Properties object.

Wires can be connected to a Stimulator either in the constructor, or separately in calls the addWire method. All wires connected to the Stimulator should be children of the Stimulator's parent. When adding wires to the Stimulator's set of wires, you can also specify the put schedules for those wires.

The following are some examples of creating a Stimulator object and associating wires with it.

This is a basic example that creates a Stimulator and adds two wires to it. The first wire will just have the default schedule of 0. The second wire will have a custom schedule of 0 1 2 2 1. The custom schedule will put the values on the wire, one at a time, one on each clock cycle.


         /* Declare the wires */
         Wire portAIn;
         Wire portBIn;

	 ... /* Bind the wires to the ports */

         /* Make a Stimulator with this TestBench as parent */
         Stimulator stimulator = new Stimulator( this );

         /* Add portAIn with default put schedule: "0" */
         stimulator.addWire( portAIn );

         /* Add portBIn with custom put schedule: 0, 1, 2, 2, 1, 0, 1, 2, 2, 1, etc. */
         stimulator.addWire( portBIn, "0 1 2 2 1" );
    

This example shows the contents of a Properties file and the code from a TestBench that instantiates a Stimulator for some wires. The syntax of java.util.Properties file can be found in the description of the load method of that class.

schedules.props file contents:


         # This file contains the schedules for the inputA and inputB wires of my TestBench
         inputA = 0 1 1 1 0 1 0 15
         inputB :  10 9 8 7 5 4 3 2 1 15
    

Portions of the TestBench class:


         /* Declare the wires */
         Wire inputA;
         Wire inputB;
         Wire inputC;

	 ... /* Bind the wires to the ports */

         /* Put the wires in a Collection object, such as a HashSet */
         java.util.HashSet stimulatorWires = new java.util.HashSet(3);
         stimulatorWires.add( inputA );
         stimulatorWires.add( inputB );

         /* Make a Stimulator with this TestBench as parent */
         /* The wires are passed to it in a Collection object */
         /* The schedules will be loaded from the Properties file given */
         Stimulator stimulator = new Stimulator( this, stimulatorWires, "schedules.props" );

         /* We can still add more wires but we have to specify the 
         schedule if we want a non-default schedule (i.e. the schedules
         in the Properties file are no longer available) */
         stimulator.addWire( inputC, "5 8 1 0 15" );
    

You can also create multiple Stimulators. This is especially handy if you want to have wires on different clock schedules. To associate a Stimulator with a different clock schedule, simply set the default clock before instantiating the stimulator:


         /* Declare the wires */
         Wire portAIn;
         Wire portBIn;
	 Wire clockA, clockB;

	 ... /* Bind the wires to the ports and create the clocks */

         /* Make a Stimulator with this TestBench as parent */
         setDefaultClock( clockA );
         Stimulator stimulator = new Stimulator( this );

         /* Add portAIn with default put schedule: "0" */
         stimulator.addWire( portAIn );

         /* Make a different Stimulator on clock schedule B */
         setDefaultClock( clockB );
         stimulator = new Stimulator( this );

         /* Add portBIn with custom put schedule: 0, 1, 2, 2, 1, 0, 1, 2, 2, 1, etc. */
         stimulator.addWire( portBIn, "0 1 2 2 1" );
    

In some situations, it is important to excercise great care with setting and using clocks with Stimulators. See the section on using clocks with Stimulators for more information.

For information on special considerations when using Stimulators on tri-state buses, see the tri-state section.

NOTE: When creating your wires, it may be useful to give them a specific name so that you will know for sure how to access them through the command-line interface.


Clocks and the Interactive Stimulator

It is important to note that Stimulators are themselves merely JHDL circuit elements; in fact Stimulators are just instances of the class byucc.jhdl.Logic.Logic. As a Logic, Stimulators are clockable. Therefore, even if your entire design is purely combinational, if you have Stimulators driving your design, you will have a clock in the system. By default, the Stimulators simply use the current default clock. Stimulators are by default rising-edge triggered; currently, there is no support for making a Stimulator falling-edge triggered.

Sometimes a user design uses explicit clocks or needs to have a unique clock schedule (the pattern, including duty cycle, etc. of a clock wire's driver). If your design uses explicit clocks or if it sets the default clock, then you must also make sure that you set up the clock for the Stimulator. JHDL does not allow designs to mix explicit with implicit clocks. The Stimulator just uses the default clock available to it at build time; if the clock hasn't been set prior to building the Stimulator, it uses the global default clock made available by the HWSystem. But if your design uses explicit clocks, you must make sure that you set the default clock before you instance a Stimulator. (Just call the setDefaultClock method of Logic, giving it a wire driven by a clock driver.) Make sure that all of your clocks have the same length of schedule.

Stimulators should typically only be clocked by wires that are the outputs of a clock driver. (i.e. avoid using gated clocks and other unusual clock wires for Stimulators.) Also, to avoid problems with clocking Stimulators, it is a good idea to build the Stimulators last. By making sure that the TestBench builds your design and any other circuitry before instancing a Stimulator, you help to ensure that the Stimulator will be properly clocked.

Summary of using clocks with Stimulators:


Using Stimulators With Tri-State Buses

In order to be allowed to drive a tri-state bus wire, a JHDL cell must implement the TriStateDriver interface. When a tri-state bus wire is added to a Stimulator, a new Stimulator that implements the TriStateDriver interface is created to handle that wire. That one Stimulator is then responsible for only that one wire. In order to ensure that the Stimulator recognizes that a wire is a tri-state bus, it is essential that the wire is connected to another TriStateDriver, a pullup, or a pulldown before it is added to a Stimulator. Alternatively, you can instance a TriStateStimulator directly. (The constructor for a TriStateStimulator takes a parent Node, the Wire, and a String for the schedule, in that order.)

If at any time a tri-state bus Wire being driven by a Stimulator is to let the wire float or allow some other device to drive it, the schedule for that wire at that point should issue a "Z". That is, if you use the standard ValueForcers to generate the value sequence for the wire, indicate a high impedance output with "Z" in your schedule string. For custom ValueForcers (see the section on function generators), make sure the underlying ValueProvider properly implements the isDrivingOutput() method appropriately. See the API documentation for more information.


Interacting with the Interactive Stimulator

If the put scheudules placed on the wires in the TestBench are what you want to simulate in JHDL, you do not need to do anything else with the interactive stimulator. You may simply execute the simulation normally.

If yo do want to interactively update the schedules on the wires, you can use the JHDL command-line interface (CLI). The interactive stimulator registers two commands in the JHDL CLI. It is through these commands that you interact with the stimulator.

PUTLIST COMMAND. The putlist command is used to display the names of the wires that are currently registered with any Stimulator object.

PUT COMMAND. The put command is used to create or update a custom schedule for a given wire. The syntax is:
          put wire_name value|schedule
    
A value is a decimal, hexadecimal, octal, or binary value (prefix 0x, 0o, or 0b for hexadecimal, octal, or binary). A value may also be Z. (Useful for inout ports.) A schedule is a space-separated list of values. A schedule may also be the name of a custom function generator object along with appropriate arguments for it. See the advanced section for more information on custom schedules.

The following are examples of calls to the put command:

put myWire1 0b110
This command tells the interactive stimulator to drive the wire myWire1 with the value 6 on every clock cycle.
put myWire2 0b110 0x10 8 0o12
This command tells the interactive stimulator to drive the wire myWire2 with the sequence of values 6, 16, 8, and 10. On the first clock cycle, the stimulator will drive the wire with a 6, on the second, with a 16, on the third, an 8, on the fourth, a 10. Then the process repeats so that on the fifth cycle, the stimulator will drive the wire with a 6, and so forth.

Examples Using the Interactive Stimulator

The following files contain a full JHDL example that uses the interactive stimulator. With the JHDL classes or JHDL.jar in your classpath, compile AndNReg and tbAndNRegStimulator. Then execute tbAndNRegStimulator with the -gui option:

         javac tbAndNReg3BitStimulator.java AndNReg3Bit.java
         java tbAndNReg3BitStimulator -gui
   

AndNReg3Bit.java This is the design that is wrapped by the TestBench
tbAndNReg3BitStimulator.java The TestBench for this example. This is where the Stimulator is created.
sched.props This is a Properties file that is used by this example

The following files contain a another example that uses the interactive stimulator. With the JHDL classes or JHDL.jar in your classpath, compile CustomClockCell and tbCustomClockCell. Then execute tbCustomClockCell:

         javac tbCustomClockCell.java CustomClockCell.java
         java tbCustomClockCell
   

CustomClockCell.java This is the design that is wrapped by the TestBench
tbCustomClockCell.java The TestBench for this example. This is where the Stimulator is created. This TestBench uses custom, user-defined clocks and a tri-state Stimulator. This TestBench is not as full-featured as tbAndNReg3BitStimulator; it is meant to show how to deal with user-defined clocks and tri-state wires.



Advanced Used of Stimulators: Function Generators

The Stimulator also allows you to create your own custom function generator to provide the values to put on an input wire. To create a custom function generator, simply create a class that implements one of the sub-interfaces of byucc.jhdl.apps.Stimulator.ValueProvider. Then, to apply your function generator to a wire during simulation, use the put command.

The put command has the following syntax:
       put  value|schedule|ValueProvider_arguments

Where ValueProvider_arguments are arguments that will create your custom ValueProvider. In the JHDL viewer command line field, type help put for more information on the syntax of the arguments to create a ValueProvider. Use this same syntax when creating a ValueProvider for the Wire from withing the TestBench. The example at the end of this section demonstrates how to do this.

There are four different sub-interfaces of the ValueProvider interface. These interfaces, which are also in the byucc.jhdl.apps.Stimulator package, are BooleanValueProvider, IntegerValueProvider, LongValueProvider, and BVValueProvider. These interfaces are designed so that, if necessary, you can implement all four, or any combination. Having four different interfaces is desirable to allow you to select the interface that most closely matches your design. For one-bit wires, the BooleanValueProvider interface is sufficient; but for wires up to 32 bits wide, you should probably use the IntegerValueProvider. Likewise, LongValueProvider is adequate for wire widths up to 64 bits and BVValueProvider can be used for arbitrary-width wires.

Each ValueProvider interface requires you to implement two versions of the method public String getForceSchedule(...). One getForceSchedule method takes an int to be used as a radix. The other takes a String to be used as a BV format string. Use these methods to output a String that will represent the series of values or the function that your ValueProvider generates.

Each ValueProvider interface also requires you to implement the methods public [return_type] getNext[ReturnType]Value() and public [return_type] getReset[ReturType]Value(), where return_type is one of boolean, int, long, or BV, and ReturnType is Boolean, Integer, Long, or BV respectively. Use the getNext[ReturnType]Value method to provide successive values of your function for each clock cycle. Use the getReset[ReturnType]Value method to provide the value that the wire should have at system reset.

Once you have written and compiled your function generator, you can apply it to your wire using the put command from the command line in the circuit visualization window of JHDL. The put command has been overloaded to allow you to either put a single value or series of values (as described above) or to instance a ValueProvider and associate it with a wire. Run the command help put to view the syntax and other helpful information. The syntax of this use of the put command allows you to specify which (public) constructor of your ValueProvider class (if it happens to have more than one constructor) and which of the ValueProvider interfaces you wish it to act as during simulation (if it happens to implement more than one). You may also provide arguments to the constructor of your ValueProvider to set up any parameters it may have.

The following files contain a full JHDL example that uses the interactive stimulator and a custom function generator. With the JHDL classes or JHDL.jar in your classpath, compile AndNRegNBit, tbAndNReg32Function, and Cosine. Then execute tbAndNReg32Function with the -gui option:

         javac tbAndNReg32Function.java AndNRegNBit.java Cosine.java
         java tbAndNReg32Function -gui
   

AndNRegNBit.java This is the design that is wrapped by the TestBench.
tbAndNReg32Function.java The TestBench for this example. This is where the Stimulator is created and a custom function generator is associated with the wires.
Cosine.java A custom function generator that will output a cosine function.
CustomCosineView.java A custom viewer to watch wires with cosine values on them.



| Lab Home Page |

JHDL

Copyright (c) 1998-2002 Brigham Young University. All rights reserved.
Reproduction in whole or in part in any form or medium without express permission of Brigham Young University is prohibited.

Documentation Revision: $Date: 2002/04/05 $