Contents

Overview

MicroTiger is a graphical microcode simulator with a reconfigurable datapath. The datapath editor window, the main application window, allows for datapath creation and simulation. In addition, several other dialog windows are provided to aid in creating the datapath. The microprogram editor window allows for microprogram and aids in simulation. The ISA code is externally edited and can be viewed in the ISA code viewer window. The simulation controls are available in the main application window. The expression language is available for ALUs and custom components to customize the evaluation of these components.

Creating Datapaths

The datapath editor window is the main application window and is always available. The editor resembles other circuit editors in that the user can move components and wires, and configure the properties of components. The editor provides a set of common datapath elements that are easy to configure for many different purposes.

The File menu allows the datapath to be loaded and saved. The File menu also allows the microprogram and ISA code to be loaded. The File menu also allows the application to be exited.

The Edit menu allows highlighted components to be cleared, all the components to be selected, the default signal size for the datapath to be edited, and the RAM to use for the ISA code to be specified.

The View menu allows the microprogram editor window, ISA code viewer window, signal list window, control properties window, and datapath macros window to be opended. The View menu also allows the toolbar, statusbar, and datapath grid to toggled. By default, the toolbar and statusbar are enabled and the grid is disabled. The View menu also allows the datpath to be zoomed between 30% and 150% with increments of 10%. The default zoom level is 100%. The zoom can also be changed using the keyboard keys. The '-' key is used to decrement the zoom level and '+' key is used to increment the zoom level. The View menu also allows access to the datapath properties window that reports information about the number of components, signals, control fields, and vertices.

The Draw menu allows several components to be added including Adders, Adder / Subtractors, Alus, Comparators, Custom components, Demultiplexers (Demuxes), Multiplexers (Muxes), Pipeline Registers, RAMs, Registers, Register Files, and Sign Extenders. The Draw menu also provides a message component to comment the datpath. The datapath components and wires can be moved by using the left mouse button to drag the components to new locations and tries to intelligently move any attached wires with the component. Components can be deleted by using the delete key or Edit menu's Clear item. Both datapath components and messages can be configured by right clicking on the component. For messages, the message text can be configured. For other components, the signals can be modified (added and removed if there are variable number of signals for the component) and the expression for configurable components can be modified. The expression language for ALUs and custom components is described later in the Expression Language section.

The Draw menu also provides a wire drawing mode. The wire drawing mode waits for a first left mouse click which specifies the first end point of the wire. Until the second left mouse click is encountered, a dotted line is drawn between the first wire end point and the current mouse location. The wire can be drawn when the second left mouse click is encountered. The wire mode then continues waiting for another first left mouse click to specify another wire.

The Simulate menu provides several simulation controls and are described in the Simulating It All section.

The Help menu provides this user documentation, a number converter for different numeric bases, and information about the application.

Creating MicroPrograms

The microprogram editor provides a integrated text editor for writing and compiling the microprogram for the simulator. When simulating, the microprogram editor highlights the current operation in the microprogram making debug easier. Also, breakpoints can be defined to further aid in debugging. The format of the microprogram language is describe in the MicroProgram Language section.

The File menu allows the microprogram to loaded and saved. The File menu also allows the microprogram editor to be closed. Also, the microprogram can be loaded from the main application's File menu.

The Edit menu allows control field mnemonics to be inserted from the control properties window and allows for standard text editing features.

The View menu allows the control properties window and the datapath macros window to be brought up. The View menu can also toggle the statusbar and the syntax highlighting during simualtion.

The Build menu allows the microprogram to be compiled and present an error dialog when the microprogram has parsing problems.

The Breakpoints menu allows breakpoints to be set, breakpoints to be cleared, and all breakpoints to be cleared.

The Help menu provides this user documentation and information about the application.

Control Fields Specification

The control fields are created and modified using the control properties window. The control properties window is accessible through both the datpath editor's (main window) and microprogram editor's View menu. The control properties dialog allows control fields to added, edited, and removed. Once a control field is selected, its properties can be edited. The editable properties included the signal length, the overflow control field to store the overflow of this control field (for more advanced microprogram formats), and the assigning of control field mnemonics. Also there is a button to insert a selected control field mnemonic into the microprogram editor window.

Datapath Macros

The datapath macros window allows the macros to be defined in the datapath file and therefore are accessible by any microprogram using the datapath to reduce reduncancy in microprogram macros. It provides a simple text editor to write the datapath macros. When either OK or Apply buttons are pressed, the datapath macros are compiled and any parsing errors are presented to the user and saved if compiled correctly. When either the OK or Cancel buttons are pressed, the window closes.

Simulating It All

The simulator is accessed through the Simulation menu of the datapath editor window and the optional toolbar in the datpath editor window. It provides different running options like stepping on different code levels, running to halt and reseting.

The Simulation menu items are only available to use when a valid datapath exists and a microprogram is compiled. The menu provides functions to reset, to step backwards, to step forward, to step to the last or next ISA instruction (using the isa label in the microprogram), to step to the next or last iteration that has the same MPC, to step to the next or last iteration with a user specified MPC, a facility to provide an animation of the simulation.

Also, the Simulation menu provides the ability to calculate the CPI of the current simulation run. The CPI calcuation uses the microinstruction labeled isa to determine the first isa iteration, last isa iteration and the number of isa iterations executed. The CPI is calculated using the following equation:

   (last_isa_iter - first_isa_iter) / (isa_iter - 1)

ISA Language

The ISA language is very simple. The ISA language is used to input ISA files for the RAM and Register File and is used to save the state of memory. When saving the memory state, the simple, Intel hex and S-Record formats can be used for the output file.

Comments

Comments can start with either (C++ style) or # (Perl style). Comments end at the end of line. These are the same commenting style as the microprogram language described in the Microprogram Language section and the expression language described in Expression Language. Additionally a semi-colon can specify a comment (this was to provide compatibility with the AMISS simulator memory file format). For example:

   #  this is a comment just like those in Perl
   // this is a comment just like those in C++
   ;  this is comment just like those in AMISS

Simple Numbers

The simple format accepts only hex numbers and each number corresponds to a single memory location regardless of the size of the hex number. When using this format, memory values start at memory address zero and increment the memory address for each memory value. For example:

   # this store in the first and second memory addresses
   4D A0
   # next value stores in third memory address
   FF
   # this long number will be truncated to the element size
   74BA897894CAB347892A80001A

Intel Hex Format

The Intel hex format is also an acceptable input for ISA language. See other documentation on the actual Intel hex format specification. An example Intel hex format input is:

   # sbn primes.isa => intel hex format
   :200000006D006B00030066006600060066006D00090066006D000C006A006A000F006A002B
   :200020006600120067006700150067006A00180067006B001B0067006B001E0067006B00CD
   :200040004E006A006A0024006A0067002700680068002A0068006A002D0068006D00300064
   :2000600068006D0033006A006A0036006A0066003900690069003C0069006A003F006900DC
   :2000800068004B0069006B00090069006D0048006D006C003F006D006C001E006A006A00CF
   :2000A00051006A00660054006E006E0057006E006A005A0054006D005D0055006D00600026
   :2000C00057006D0063006D006C000900170011000D0059000700010000000000FF02000080
   :00000001FF

SRecord Hex Format

The SRecord format is also an acceptable input for ISA language. See other documentation on the actual SRecord format specification. An example SRecord format input is:

   # sbn primes.isa => srecord hex format
   S325000000006D006B00030066006600060066006D00090066006D000C006A006A000F006A0025
   S325000000206600120067006700150067006A00180067006B001B0067006B001E0067006B00C7
   S325000000404E006A006A0024006A0067002700680068002A0068006A002D0068006D0030005E
   S3250000006068006D0033006A006A0036006A0066003900690069003C0069006A003F006900D6
   S3250000008068004B0069006B00090069006D0048006D006C003F006D006C001E006A006A00C9
   S325000000A051006A00660054006E006E0057006E006A005A0054006D005D0055006D00600020
   S325000000C057006D0063006D006C000900170011000D0059000700010000000000FF0200007A
   S9030000FC

Microprogram Language

Comments

Comments can start with either (C++ style) or # (Perl style). Comments end at the end of line. These are the same commenting style as the expression language described in the Expression Language section. For example:

   #  this is a comment just like those in Perl
   // this is a comment just like those in C++

Microinstruction Format

To specify the control field values to assign, either the control field mnemonic can be used, or the control field can be named and be assigned a numeric value or microinstruction address. The values are seperated by commas and each microinstruction ends with a semi-colon.

Microinstructions can optionally be labeled by prepending the microinstruction with the label name and a colon. Additionally a microinstruction can be labeled with a number to indicate the microinstruction address of the instruction. If the address is larger than the current microinstruction address, empty microinstructions are inserted between the previous microinstruction and the current microinstruction to place the current microinstruction at the specified microinstruction address.

An example of this microinstruction format is:

# negbranch label
# uses mnemonics: memtox, zerotoy, ztopc, jmpalways
# assigns microinstruction address isa to jmpaddr
negbranch: memtox, zerotoy, ztopc,
           jmpalways, jmpaddr=isa;

Simple Microinstruction Format

A simpler microinstruction format is one that is a sequence of numeric values that are ordered by the control field names sorted in alphabetic order. The values are only seperated by whitespace and the microinstruction ends with a semi-colon. These microinstructions use the same microinstruction labels as the regular microinstruction format (described above). This allows both the simple microinstruction format and the regular microinstruction format to be used within the same microprogram.

# the same microinstruction as the last example
# just uses the simple microinstruction format instead
negbranch: 1 2 0 0 0 0 2 3;

Macro Format

The macro format is the same format as the microinstruction (without the microinstruction label) and are appended with @macro and the macro name. Macros can then be used in exactly the same manner as a control field mnemonic but provide several control fields assignation in a single phrase.

# defines a macro as the same microinstruction as before
@macro mymicro memtox, zerotoy, ztopc,
               jmpalways, jmpaddr=isa;

# use the macro to implement a microinstruction
negbranch: mymicro;

Expression Language

The expression language is mainly based on the C++ programming language with modifications to simplify certain bit level operations such as bit indexing and bit rotation.

Comments

Comments can start with either (C++ style) or # (Perl style). Comments end at the end of line. These are the same commenting style as the expression language described in the MicroProgram Language section. For example:

   #  this is a comment just like those in Perl
   // this is a comment just like those in C++

Defining Constants

By default, constants use the default signal size of the architecture. If the constant requires more bits than the default signal size, then the signal is created using as many bits is required to contain the unsigned integer being represented. Also, the number of bits can be specified by appending the size in bits in parenthesis. For example:

   # this defines a 20 bit constant with the value 27
   27(20)

   # this defines a 1 bit constant
   # so the value becomes 1 rather than 255
   255(1)

Different bases can be specified based on how different bases can be specified in C++ and some assemblers. The binary base is specified inserting ``0b'' or ``0B'' before the constant. The decimal base can also be specified by inserting ``0d'' or ``0D'' before the constant. The octal base is specified inserting ``0o'' or ``0O'' before the constant. The hexadecimal base is specified inserting ``0x'', ``0X'', or ``$'' before the constant. Additionally, a number string can be specified using B, D, O, or H to specify the base to interpret the string as. For example:

   987210   # this is a decimal number
   0b1100   # this is a binary number
   0B1100   # this is a binary number
   B'101'   # this is a binary number
   0d9810   # this is a decimal number
   0D1190   # this is a decimal number
   D'095'   # this is a decimal number
   0o1700   # this is a octal number
   0O1170   # this is a octal number
   O'073'   # this is a octal number
   0xfA90   # this is a hexadecimal number
   0XFa90   # this is a hexadecimal number
   $fA910   # this is a hexadecimal number
   $Fa910   # this is a hexadecimal number
   H'BA3'   # this is a hexadecimal number

Signal Names

Signal names must start with a letter or underscore and can contain any combination of letters, numbers, and underscores. If a name is not defined when used in an expression, it is cast to the default signal size. For example:

   # this uses the signal aluOutput
   aluOutput

   # even really long names are acceptable
   reallyLongSignalNameWithNumbersandUnderscoresLike_123

   # make a local variable with a certain size
   tempIndex(8)

Operations

All expressions use a syntax similar to that used by many languages like C++, Java and Perl.

All signals are by default treated as unsigned integers and can be represented by as many bits (such as using a single signal to represent an all the values for memory). Additionally signals can be treated as a signed integer, floating point number or a double-precision floating point number (using the machine's float and double C++ types) by casting like in C++. Most operations treat the signal as unsigned array of bits, except the comparison operators and mathematical operators. If operation has parameters of unequal types, the double type has highest priority, then float, signed and finally unsigned.

The order of operations are shown in Table ([*]). All the operators that are in the C++ language use the same order that the C++ language uses for the operators. Added operators go in the most obvious locations relative to the similarity to C++ operators. The operators located near the top of the table have a higher precendence, meaning that they are evaluated first. For example in the expression ``b = 1 + 2'', the assignment operator is evaluated first so that we have ``b'' being assigned ``1+2'' which needs to be evaluated using the order of operations.


Table: Order of Operations With Higher Precendence At The Top
Operation Description
, combine expression together
= assignment operator
?: ternary operator for conditions
|| logical inclusive or
^^ logical exclusive or
&& logical and
| boolean inclusive or
^ boolean exclusive or
& boolean and
== equality
!= inequality
< less than
<= less than or equal
> greater than
>= greater than or equal
<< shift left
>> shift right
<<< rotate left
>>> rotate right
+ addition
- subtraction
. catenation
* multiplication
/ division
% modulus
- negation
! logical not
~ boolean not
(unsigned) cast to unsigned
(signed) cast to signed
(float) cast to float
(double) cast to double
[x] get the x bit
[x:y] get the bits from x to y
[carry] return 1 if the signal has a carry
[overflow] return 1 if the signal has a overflow
[negative] return 1 if the signal is negative
[zero] return 1 if the signal is zero

Examples of various operations:

   # simple addition
   12 + 28;

   # lots of operations
   1 + 3 < 5 && 2 * 6 == 12 - 0 || (23 % 6) << 5 > 37;

   # casting
   (signed)89 == (unsigned)--89;

   # bit and flag retrival
   aluOutput[carry] . aluOutput[negative] . aluOutput[1:0];

Assignment

On the left side of the assignment operator, ``='', must either me a name, a name[x] or name[x:y]. The name must be a valid signal name. The name[x] assignment assigns a particular bit in the signal. The name[x:y] assignment assigns a range of bits in the signal.

   # simple assignment
   output = 32;

   # assign a bit
   setMy3rdBit[2] = 1;

   # assign a range of bits
   setMy2ndByte[8:15] = 0x72;

Programming Language Statements

For, While, and Do

Provides the three loop types with the same syntax as C++. The for keyword provides a starting expression, a looping condition (which is also tested before the loop begins), and an expression to evaluate at the end of each loop. The while keyword provides a looping condition which is also tested before entering the loop. The do keyword provides a looping condition which is not tested until one iteration of the loop is completed. Examples:

   # for loop
   for ( index = 0; index < 5; index++ ) {
      output[index*5] = input[index];
   }

   # while loop
   while ( counter > 0 ) {
      output[counter] = counter % 2;
      counter--;
   }

   # do loop
   do {
     output = output >> 1;
   } while ( output != 1 );

If and Else

Provides a conditional statement with the same syntax as C++ using the if and else keywords.

   # if example
   if ( output[carry] ) {
      error = 1;
   } else {
      error = 0;
   }

Case

The case keyword is provided to make it easier to execute several different blocks of code depending on a certain value. Any valid arithmetic expression can be tested. Each expression will have one or more numbers associated with it that will be executed if any of those numbers are equal to the expression specified. The numbers are followed by colons. Expressions can be any valid expression (including block statements, lists of expressions with semi colons or just simple expressions). At the end of the case statement is an optional default expression that gets executed if there are no matching numbers for the expression.

It is similar in function to the switch statement in C++ except there are no break statements and execution does not go into the next block.

   # case example
   # any valid arithmetic expression can be used
   case ( aluOutput-lastAluOutput ) {
   0:
     # case are specified by numbers followed by colons
     0;
   1: 2: 3:
     # multiple values can be specified
     1;
   default:
     # complex statements can be used,
     # and case statements can be nested
     case ( aluOutput ) {
       0:
         2;
       1: 2: 3:
         3;
       default:
         4;
     }
   }

About

This tool was developed by Brian G VanBuren under a thesis at the Rochester Institute of Technology entitled Graphical Microcode Simulator with a Reconfigurable Datapath. Dr. Muhammad Shaaban was the primary thesis advisor with Dr. Roy Czernikowski and Dr. Greg P. Semeraro as secondary advisors. The goal was to create a versatile microcode simulator with a side goal of replacing the existing microcode simulator used for RIT's Computer Organization class.



Hosted by: SourceForge.net Logo