CPU requirements manual CPSC / ECE 3710, Fall 2006

Each project group must design a CPU as per specifications here. While all attempts have been made to keep these specifications consistent, changes will invariably arise. You will be notified of these changes in a timely manner.

The CPU after which our's is adapted from is described at
http://www.national.com/appinfo/compactrisc/files/prog_16c.pdf.
A class taught at the University of Michigan (EECS 427) produced a nice set of handouts describing our adaptation. Past instructors, Profs. Brunvand and Kalla, have created other helpful material. Sean Curtis (a former student who took 3710) created an Excel sheet containing the instruction set descriptions. All these are available from the Fall 2004 webpage of 3710, which is linked on our class webpage. I've checked what I say below against the information contained in these pages, but cannot vouch for their accuracy. The best descriptions I have found are in the documents entitled ``EECS 427 RISC processor'' which you will find among the documents linked off in ``Prof. Brunvand's CS 3710 page from Fall'02'' linked above. I am not duplicating the information contained in the above pages. Instead, I am stating the CPU's spec in my own words and style, below. Please also note the FAQ pages in my Fall 2004 webpage for 3710 mentioned above. I've tried to incorporate all the above FAQs in what I say below.

1  Overview of your CPUs

Your CPU will evolve in three installments. The first will be called MCR16-ts for Micro CR-16, thin slice. The second will be called MCR16-bl (bl standing for ``baseline'') and finally MCR16-ex (ex standing for ``extended.'')

All these processors will be 16-bit machines, meaning they will have 16-bit data paths. A 16-bit quantity will be called a word. We will assume 16-bit addresses also, thus providing an address range of 0000 to FFFF. By `word size' we will mean `size of a word,' or equivalently, 16 bits.

The ts version will have at least the following instructions implemented:
  LUI   -- Load Upper Immediate -- load a byte into the upper byte of a word
  ORI   -- OR a register with an immediate data item
  LOAD  -- Load from a memory address into a register
  ADD   -- Add the contents of two registers, storing the result into a third
  STOR  -- Store a register into memory
The bl version will have at least the following instructions implemented:
ADD, ADDI, SUB, SUBI, CMP,  CMPI,  AND,   ANDI, OR, ORI, XOR, XORI, MOV, MOVI,
LSH, LSHI, LUI, LOAD, STOR, BCOND, JCOND, JSL
The ex version will have one or more of these features: You will receive extra points for adding these features, depending on the level of creativity as well as the quality of documentation.

1.1  Memory Map

The following memory map is recommended for all your processors. Differences are acceptable. Please document the memory map finally chosen.


FFFF  vvvvvvv

        I/O

C000  ^^^^^^^
BFFF  vvvvvvv

        code

8000  ^^^^^^^
7FFF  vvvvvvv
        stack
          |
          v
          
4000  ^^^^^^^
3FFF  vvvvvvv

       data
       
0000  ^^^^^^^  

2  Semantics

The meaning (semantics) of the CR-16 instructions are described in earlier handouts. Here I shall attempt a condensed description at a slightly more formal level. Clearly, careful reviews are needed before bugs (I'm sure many are present) are removed from these descriptions -- hence, do ask me questions via email. I shall present the baseline instructions in the order in which MCR16-bl instructions are listed in the EECS 427 handout. See those handouts for an exact bit-level layout of the instructions. Also, while I shall use the assembly language syntax and mnemonics in what follows, the exact assembly syntax you have to employ in your assembler will be specified in a separate document. Here, the focus is on what your CPU -- and hence, your simulator -- must implement.

I shall introduce notations as needed, and flag each such notation for easy reference by using the boldface word Notation.

2.1  CPU state elements

Your CPU consists of the PC, flags F, L, C, N, Z, a register file RF, and a memory MEM. One or more of these state elements gets updated by each instruction of the CPU. The CPU semantic specification simply consists of describing these updates. Our notation for writing this description follows shortly. Notation: Armed with these notations, we can begin describing some of the instructions. We will introduce more notation to progressively describe the remaining instructions.

2.2  add Rsrc, Rdst

The machine encoding is as follows:
  0000 Rdst 0101 Rsrc
Instruction semantics:
let vd    = RF[Rdst]
let vs    = RF[Rsrc]                           
let va    = vd + vs                            
let carry = cb(vd+vs)                       
let ovflo = if (msb(vd) XOR msb(vs)) then 0 -- recall that this is how 
            else (msb(vs) XOR msb(va))      -- overflow is computed 

then

RF'  = (RF[ Rdst ] := va),
F'   = ovflo,
C'   = carry,
PC'  = PC + 0x0001
Notice that the flags L, N, Z are unaffected.

Example: Let the CPU state be such that register r0 contains 1000_0000_0000_0000 while r1 contains 1111_1111_1111_1111. Then, with PC at FFFE (writing in hex), and this address containing instruction
add r0, r1,
we obtain as the new CPU state
  RF' = (RF[r1] := 0111_1111_1111_1111)
  F'  = 1
  C'  = 1
  PC' = FFFF
Additional notations used:

2.3  addi Imm, Rdst

The machine encoding is as follows:
  0101 Rdst Immhi Immlo
The only thing to point out is that we are treating the immediate values as signed 2's complement values (-128 through +127). Since my ``+'' denotes 16-bit addition, I have to sign extend the immediate value before addition.

Instruction semantics:
let vd = RF[Rdst]                           
and vs = sex(Imm) -- recall that this sign extends a byte to fill a 16-bit word
and va = vd + vs                            
and carry = cb(vd+vs)                       
and ovflo = if (msb(vd) XOR msb(vs)) then 0
            else (msb(vs) XOR msb(va))      

RF'  = (RF[ Rdst ] := va),
F'   = ovflo,
C'   = carry,
PC'  = PC + 0x0001

2.4  sub Rsrc, Rdst

The machine encoding is as follows:
  0000 Rdst 1001 Rsrc
Note that the opcode extension is what distinguishes this operation from add.

Instruction semantics:

let vd = RF[Rdst]                             
and vs = RF[Rsrc]                             
and va = vd - vs                              
and carry = cb(vd-vs)                         
and ovflo = if (msb(vd) XNOR msb(vs)) then 0
            else (msb(vs) XNOR msb(va))       

RF'  = (RF[ Rdst ] := va),
F'   = ovflo,
C'   = carry,
PC'  = PC + 0x0001

2.5  Alternative sub Rsrc, Rdst using adders

Suppose your CPU only has adders. How do we then carry out sub? We can do so using 2's complement arithmetic.

[ Note: such alternatives might be needed for other operations also. I've not shown those. Those are left for you to derive.]
ALTERNATIVE sub Rsrc, Rdst

let vd = RF[Rdst]                             
and vs = twos_complement(RF[Rsrc])                      
and va = vd + vs                              
and carry = cb(vd+vs)                         
and ovflo = if (msb(vd) XOR msb(vs)) then 0
            else (msb(vs) XOR msb(va))        

RF'  = (RF[ Rdst ] := va),
F'   = ovflo,
C'   = carry,
PC'  = PC + 0x0001

2.6  subi Imm, Rdst

The machine encoding is as follows:
  1001 Rdst Immhi Immlo
Instruction semantics:
let vd = RF[Rdst]                             
and vs = sex(Imm)
and va = vd - vs                              
and carry = cb(vd-vs)                         
and ovflo = if (msb(vd) XNOR msb(vs)) then 0
            else (msb(vs) XNOR msb(va))       

RF'  = (RF[ Rdst ] := va),
F'   = ovflo,
C'   = carry,
PC'  = PC + 0x0001

2.7  cmp Rsrc, Rdst

The machine encoding is as follows:
  0000 Rdst 1011 Rsrc
Instruction semantics:
let vd = RF[Rdst]                             
and vs = RF[Rsrc]                             
and va = vd - vs                              
and carry = cb(vd-vs)                         
and neg   = carry XOR msb(vd) XOR msb(vs)     
and zero  = if (va = zex(0x00)) then 1 else 0 -- clearer writing

L'   = carry
N'   = neg
Z'   = zero
PC'  = PC + 0x0001

2.8  cmpi Imm, Rdst

The machine encoding is as follows:
  1011 Rdst Immhi Immlo
Instruction semantics:
let vd = RF[Rdst]                             
and vs = sex(Imm)
and va = vd - vs                              
and carry = cb(vd-vs)                         
and neg   = carry XOR msb(vd) XOR msb(vs)     
and zero  = if (va = zex(0x00)) then 1 else 0

L'   = carry
N'   = neg
Z'   = zero
PC'  = PC + 0x0001

2.9  and Rsrc, Rdst

The machine encoding is as follows:
  0000 Rdst 0001 Rsrc
Instruction semantics:
let vd = RF[Rdst]                             
and vs = RF[Rsrc]                             
and va = bv_and(vd,vs)                        

RF'  = (RF[Rdst] := va)
PC'  = PC + 0x0001

2.10  andi Imm, Rdst

The machine encoding is as follows:
  0001 Rdst Immhi Immlo
Instruction semantics:
let vd = RF[Rdst]                             
and vs = zex(Imm)                         
and va = bv_and(vd,vs)                        

RF'  = (RF[Rdst] := va)
PC'  = PC + 0x0001

2.11  or Rsrc, Rdst

The machine encoding is as follows:
  0000 Rdst 0010 Rsrc
Instruction semantics:
let vd = RF[Rdst]                             
and vs = RF[Rsrc]                             
and va = bv_or(vd,vs)                         

RF'  = (RF[Rdst] := va)
PC'  = PC + 0x0001

2.12  ori Imm, Rdst

The machine encoding is as follows:
  0010 Rdst ImmHi ImmLo
Instruction semantics:
let vd = RF[Rdst]                            
and vs = zex(Imm)                        
and va = bv_or(vd,vs)                        

RF'  = (RF[Rdst] := va)
PC'  = PC + 0x0001

2.13  xor Rsrc, Rdst

The machine encoding is as follows:
  0000 Rdst 0011 Rsrc
Instruction semantics:
let vd = RF[Rdst]                             
and vs = RF[Rsrc]                             
and va = bv_xor(vd,vs)                        

RF'  = (RF[Rdst] := va)
PC'  = PC + 0x0001

2.14  xori Imm, Rdst

The machine encoding is as follows:
  0011 Rdst ImmHi ImmLo
Instruction semantics:
let vd = RF[Rdst]                             
and vs = zex(Imm)                         
and va = bv_xor(vd,vs)                        

RF'  = (RF[Rdst] := va)
PC'  = PC + 0x0001

2.15  mov Rsrc, Rdst

The machine encoding is as follows:
  0000 Rdst 1101 Rsrc
Instruction semantics:
let vs = RF[Rsrc]                             

RF'  = (RF[Rdst] := vs)
PC'  = PC + 0x0001

2.16  movi Imm, Rdst

The machine encoding is as follows:
  1101 Rdst ImmHi ImmLo
Instruction semantics:
let vs = zex(Imm)                         

RF'  = (RF[Rdst] := vs)
PC'  = PC + 0x0001

2.17  lsh Ramount, Rdst

The machine encoding is as follows:
  1000 Rdst 0100 Ramount
This instruction is well defined only for values of 'vamount' (contained in register Ramount) in the range +15 to -15. These values are expressed in sign-magnitude form (to be consistent with the immediate case -- lshi -- that follows). This may be a deviation from the original CR-16.

In other words, It is highly recommended that you implement this instruction last. Even so, you may wish to implement only the vamount=1 case first. Thus: This is a logical shift instruction - i.e. zero-fill hapens (see below)

Instruction semantics:
let vd = RF[Rdst]
and amount = RF[Ramount]  -- a 16-bit quantity
and sign   = if (bv_and(0x0010, amount) = 0x0000) then 0 else 1
                    -- 0 means left, and 1 means right
and magnitude = unsigned2decimal( bv_and(0x000F, amount) ) -- get magnitude of shift

RF'  = (RF[Rdst] := if sign = 0 then bv_lshift(vd, magnitude)
                                else bv_rshift(vd, magnitude)
       )     
PC'  = PC + 0x0001

2.18  lshi Imm, Rdst

The machine encoding is as follows:
  1000 Rdst 000s ImmLo  
Again, it is highly recommended that you implement only the +1 / -1 cases first.

If s=0, then we take it to be a left shift. So if s=1, treat it as a right shift.

Instruction semantics:
let vd = RF[Rdst]                             
and vamount = unsigned2decimal(ImmLo)                        

RF'  = (RF[Rdst] := if s=0
                     then bv_lshift(vd, vamount)
                     else bv_rshift(vd, vamount)    
       )              
PC'  = PC + 0x0001

2.19  lui Imm, Rdst

The machine encoding is as follows:
  1111 Rdst ImmHi ImmLo
Instruction semantics:
let va = bv_lshift(zex(Imm), 8)           

RF'  = (RF[Rdst] := va)
PC'  = PC + 0x0001

2.20  load Rdst, Raddr

The machine encoding is as follows:
  0100 Rdst 0000 Raddr
Instruction semantics:
let va = MEM [ RF[Raddr] ]                     

RF'  = (RF[Rdst] := va)
PC'  = PC + 0x0001

2.21  stor Rsrc, Raddr

The machine encoding is as follows:
  0100 Rsrc 0100 Raddr
Instruction semantics:
let vd = RF[Raddr]                             
and vs = RF[Rsrc]                             

MEM' = (MEM [ vd ] := vs)                
PC'  = PC + 0x0001

2.22  bcond Disp, Cond

The machine encoding is as follows:
  1100 Cond DispHi DispLo
Instruction semantics:
let cond_met = branch(Cond,F,L,C,N,Z) ; Consult Table 1 of the EE 427 handout
                                      ; and see if the branch condition is met
PC'  = if cond_met
          then PC + sex(Disp) -- branch taken. Disp = DispHi_DispLo
          else PC + 0x0001    -- not taken; PC increments normally by 1

2.23  jcond Cond, Rtarget

The machine encoding is as follows:
  0100 Cond 1100 Rtarget
Instruction semantics:
let vt = RF[Rtarget]                          
and cond_met = branch(Cond,F,L,C,N,Z)         
                                                 
PC'  = if cond_met
          then vt          -- jump taken
          else PC + 0x0001 -- jump not taken

2.24  jal Rlink, Rtarget

The machine encoding is as follows:
  0100 Rlink 1000 Rtarget
Instruction semantics:
vt = RF[Rtarget]                          

RF'  = (RF [ Rlink ] := PC + 0x0001)
PC'  = vt

3  Exercises -- as well as ``thin-slice'' defined

In order to reliably build your CPU, you must know its machine semantics well. Here are exercises that help you practice your knowledge.
  1. What does this program do?
      lui 0xBF r1
      ori 0xFF r1
      load  r1 r1
      lui 0xC0 r2
      load  r2 r2
      add   r1 r2
      lui 0xC0 r3
      ori 0x01 r3
      stor  r2 r3    
      
    Note: The instructions in this program constitute MCR16-ts, the thin-slice version of MCR16.

  2. Calculate the state changes caused by each instruction of the following program. Assume suitable initial values for the memory locations involved in this program. Hex numbers are entered starting with 0x.

This document was translated from LATEX by HEVEA.