![]() |
CS2200 Intro to Systems and Networks |


a(), b(), and alufunc()
representing the value on wires coming from registers A and B and a
field from the output of the control FSM. Since the functions
representing combinational logic have no state themselves and produce
values that are based on register state that doesn't change during a
clock cycle, they can be safely called in any order during a clock
cycle and will always return the same results. Note that this
programming style may generate a lot of redundant procedure calls
during the execution of the program, but ignore that effect (consider
it the compiler's fault...)
static int alu(void)
{
switch(alufunc())
{
case 0: return(a() + b()); /* ADD */
case 1: return(~(a() & b())); /* NAND */
case 2: return(a() - b()); /* SUB */
case 3: return(a() + 1); /* INC */
default: assert(0);
}
}
curstate structure and the procedure
doclock() in sim-onebus.c


-------------
| |----- halt
8 | |----- LdPC
state --/--| |----- LdA
4 | |----- LdB
opcode --/--| |----- LdMAR
| |----- LdIR
z -----| |----- LdZ
| FSM |----- WrREG
| ROM |----- WrMEM
| |----- DrPC
| |----- DrALU
| |----- DrREG
| |----- DrMEM
| |----- DrOFF
| | 2
| |--/-- alufunc
| | 2
| |--/-- rsel
| | 8
| |--/-- nextstate
| |
-------------
Note that despite being built with one big ROM, Mealy-machine style,
we insist that the FSM follow Moore machine conventions: the outputs
are a function of the current state only:
25: halt halt signal (to the simulator!)
24: LdPC load PC register from the bus
23: LdA load ALU A input
22: LdB load ALU B input
21: LdMAR load memory address register
20: LdIR load instruction register
19: LdZ load zero bit
18: WrREG write register file
17: WrMEM write memory
16: DrPC drive the PC value onto the bus
15: DrALU drive the ALU
14: DrREG drive the register file output
13: DrMEM drive the memory output
12: DrOFF drive the sign-extended IR offset field
11-10: alufunc 0b00 = ADD, 0b01 = NAND, 0b10 = SUB, 0b11 = INC
9-8: rsel 0b00 = RA, 0b01 = RB, 0b10 = RDST
7-0: nextstate these can be a function of inputs also
You can think of a ROM as a block of combinational logic or as a block
of memory. We could specify the contents of the ROM as a block of
memory but it would be really hard to read! Instead, we
specify it symbolically like this:
FSM_LDA | FSM_DRPC /* Drive PC, Load A */ FSM_LDPC | FSM_DRALU | FSM_INC /* Drive ALU, Load PC, alufunc = "increment" */
enum statement to list all the states of the FSM.
The compiler will assign a number to each state symbol, starting
with zero. These symbols are used both to represent the current
state (a ROM input) and the nextstate (a ROM output). Use
symbolic state names of the form ADD1, ADD2, ADD3, etc for the
microcode associated with each instruction you implement. Note
that the number of states here is MORE than you should need!
enum { FETCH1 = 0, FETCH2, FETCH3, FETCH4, FETCH5, FETCH6, FETCH7, FETCH8,
ADD1, ADD2, ADD3, ADD4, ADD5, ADD6, ADD7, ADD8,
NAND1, NAND2, NAND3, NAND4, NAND5, NAND6, NAND7, NAND8,
LW1, LW2, LW3, LW4, LW5, LW6, LW7, LW8,
SW1, SW2, SW3, SW4, SW5, SW6, SW7, SW8,
BEQ1, BEQ2, BEQ3, BEQ4, BEQ5, BEQ6, BEQ7, BEQ8,
JALR1, JALR2, JALR3, JALR4, JALR5, JALR6, JALR7, JALR8,
ADDI1, ADDI2, ADDI3, ADDI4, ADDI5, ADDI6, ADDI7, ADDI8,
HALT1,
NSTATES}; /* NSTATES is the number of states */
fsmstate() in the code) where each case of
the switch is a one line "return" statement containing the
appropriate masks OR'd togther to form the output for that state.
Here's an example taken from the skeleton code:
static int fsm_rom(void)
{
switch (fsmstate())
{
case FETCH1: return(FSM_LDMAR | FSM_DRPC | FETCH2);
case FETCH2: return(FSM_LDIR | FSM_DRMEM | HALT1);
/* ... FIX ME ... */
case HALT1: return(FSM_HALT | HALT1);
default:
printf("bad FSM state %d (0x%02x)\n", fsmstate(), fsmstate());
assert(0);
}
}
The big switch structure above makes it clear that the output of the
ROM depends mostly on the current state. However, in a couple of
places, the next state needs to depend on other inputs as well. So,
one more recommendation:
dispatch()) to compute the next state at this
point. Then in that line of fsm_rom(), you'd OR in
the return value of dispatch() in the place where
you'd ordinarily specify the next state. E.g.:
case FETCH4: return(FSM_LDPC | FSM_DRALU | FSM_INC | dispatch());
fib.s from Homework 1? You may improve your execution
time by modifying the control FSM, but don't modify the datapath. In
other words, we should be able to cut-and-paste your microcode into
our simulator and have our simulator work correctly. Nothing to turn
in for this question (we'll just run your simulator to find out).
| Instruction class | LC-2200 examples | gcc | spice |
|---|---|---|---|
| Arithmetic | add, nand, addi
| 48% | 50% |
| Data transfer | lw, sw
| 33% | 41% |
| Conditional branch | beq
| 17% | 8% |
| Jump | jalr
| 2% | 1% |