References: EE380 The Simple Processor Architecture Simulator

In case you had not guessed, the simulator allows you to test arbitrary control sequences like we've described. However, it does not allow a single function unit's execution to span clock cycles (after all, we told you that trick was prone to glitches, etc.).

A specification for the simulator consists of delay and when specifications, control states, and initial/final values for registers and memory locations. There should be an example pre-loaded in the form. Play with it. Enjoy. Let me know if there are problems.... Here's a bit more detail about the simulator's input.

General Input Syntax

The simulator input is line-oriented, with the end-of-line serving as a separator between commands. Alternatively, multiple commands can be specified on a single line using semicolon (;) as a separator. Comments can be parts of a line or even multi-line using the conventional C comment style (start with /* and end with */), or can be until the end of the line using either -- or //. Because some people like commas between signal names, commas are treated just like spaces.

Integer values can be specified using most of the usual C expression notation. Supported binary operators include: |, &, ^, <, <=, >, >=, ==, !=, <<, >>, +, -, *, /, and %. Supported unary operators include: !, -, ~, and field constructor functions op(expr), rs(expr), rt(expr), rd(expr), shamt(expr), funct(expr), addr(expr), and immed(expr). The field constructors shift and mask their arguments to fit them into the bitfields of the same names within the MIPS instruction format. Constants can be specified as hexadecimal (prefixed by 0x), decimal (the default), octal (0 followed by octal digits), or even binary (prefixed by 0b). For example, the value ten could be written as 0xa, 0xA, 10, 012, or 0b1010.

New for Spring 2006, the simulator understands the basic MIPS assembly language constructs and can treat a MIPS instruction as an integer value. The notation encloses the MIPS assembly language instruction in braces; e.g., {add $t0,$23,$ra} is equivalent to 0x02ff4020. Note that this processing of MIPS assembly language does not associate an address with the instruction, so there are no labels and the encoding of jumps and branches requires integer values for the address and offset fields. The MIPS instruction names and field macros also can be used without additional arguments to identify the "basic" bit patterns; for example, when op()+shamt()+funct() {add} Add would specify the decoding of a MIPS add instruction.

Delay Specifications

As of Spring 2005, the simulator supports specification of signal delays and automatic computation of critical path delays and minimum allowable clock period. The delays are tracked as integer values, which one might typically interpret as either microseconds or nanoseconds. The specification syntax is straightforward: delay expr list_of_signals. All the signal names defined can have integer delays specified. In addition, SEL can be used to specify the time to be used for all selects, OUT for all outputs, IN for all inputs, and ALU for all ALU operations. These delay specifiations are processed in order, thus, delay 5 SEL; delay 10 SELrd; is valid shorthand for delay 5 SELrs SELrt; delay 10 SELrd;. Signal delays not specified default to a value of 0.

The delay specification also allows the WWW interface-specified memory read latency in clock cycles to be overridden with a clock cycle count computed from the raw memory read delay and the computed critical path delay. The memory read delay is reprsented by MEM in a delay specification. For example, if the minimum allowable clock period is found to be 35, then delay 100 MEM; would cause all memory reads to take 3 clock cycles; a minimum allowable clock period of 10 would make the same specification result in a 10 clock cycle latency for a memory read.

When Specifications

As suggested, when specifications are used to decode instructions when JUMPonop is triggered. A when x y z; means go to state z next when (IR&x)==y. Like delay specications, when specifications are processed in the order specified; the result is that ambiguous specifications always use earliest specified when that is satisfied. If no when is satisfied, JUMPonop becomes a null operation and the next state in sequence is the next state.

State Specfications

Really no surprises here; just list the signals you want in each state. A state may be prefixed by a symbolic labels followed by a colon, e.g., the start state begins with Start:. The parser does simple checks for illegal combinations of control signals within a state, so it can warn of such things even if no simulation is performed.

Initial/Final Condition Specifications

Testing that your state machine does what you want requires simulating execution of some instructions. For this purpose, the simulator allows you to specify arbitrary initial and final states for any of the registers and memory locations.

The registers are IR, PC, MAR, MDR, Y, Z, and $expr; the last notation is used to specify a register number, 0-31. Registers that don't have initial values specified are set to a default initial value of 0. Memory locations work differently -- memory locations literally do not exist until you initialize them or your program stores into them. Each memory location is four byte addresses long and must be aligned on a multiple of four boundary. Thus, the first memory word is MEM[0] and the second is MEM[4]. However, you need not access or define memory locations in sequence; any MEM[expr] can be initialized in any sequence.

Initializing a register or memory location is done using something closely resembling an assignment statement allowing an expression on the right side. For example, PC=7+1; sets the PC to initially have the value 8.

However, the simulator also allows specification of final values. These values are intended primarily for the TA to use in grading assignments... after all, it is difficult to consistently grade code without using functional tests. Thus, each final value specification looks a lot like an initialization with three differences: the # symbol is used instead of =, there are two expressions on the right hand side instead of just one, and memory locations are handled specially. The second expression is used to specify how many points to take off if the specified value does not match. For example, PC#12 10; would say that having the final value of the PC equal to 12 is worth 10 points. The final score is reported as a weighted percentage match for all stated final conditions followed by a list of which values were incorrect.

Final values for memory locations are specified using MEM[expr]#expr;, with only one argument on the right side. The cost weighting for a mismatch is specified for all memory locations using MEM#expr to set the cost for all memory mismatches. This is done because one of the most common types of memory mismatch is changing the value of a memory location that shouldn't have been involved... points are taken off for such differences without you having to enumerate all the possible memory locations an errant simulation might corrupt.


EE380 Computer Organization and Design.