/* 
    DataPath.h  Macros for the datapath and a MIR-ROM 
    -Chris McClung
*/



Define DataPath mir[31-0] mbr[15-0] Phase[1-4] Reset | 
  R0[15-0] R1[15-0] R2[15-0] R3[15-0] R4[15-0] R5[15-0] 
  R6[15-0] R7[15-0] R8[15-0] R9[15-0] R10[15-0] R11[15-0] 
  R12[15-0] R13[15-0] R14[15-0] R15[15-0] 
  A[15-0] B[15-0] ALatch[15-0] BLatch[16-0] 
  AMUX[15-0] aluOut[15-0] C[15-0] N Z;
   
   
  /* Abus mux */
  Mux-mxn aa R15[15-0] R14[15-0] R13[15-0] R12[15-0] R11[15-0] R10[15-0] 
          R9[15-0] R8[15-0] R7[15-0] R6[15-0] R5[15-0] R4[15-0] 
          R3[15-0] R2[15-0] R1[15-0] R0[15-0] mir[11..8] | A[15..0]; 
      
  /* B-bus Mux */
  Mux-mxn aa R15[15-0] R14[15-0] R13[15-0] R12[15-0] R11[15-0] R10[15-0] 
          R9[15-0] R8[15-0] R7[15-0] R6[15-0] R5[15-0] R4[15-0] 
          R3[15-0] R2[15-0] R1[15-0] R0[15-0] mir[15..12] | B[15..0]; 
      
      
  Not cc Phase[2] notphase2;
      
  /* Here's the latches */
  Register cc A[15..0] notphase2 | ALatch[15..0];
      
  Register cc B[15..0] notphase2 | BLatch[15..0];
      
  /* AMUX selector */
      
  Mux-mxn cc mbr[15..0] ALatch[15..0] mir[31] | AMUX[15..0];         
      
  /* ALU */
  ALU16 cd AMUX[15..0] BLatch[15..0] mir[28..27] | aluOut[15..0] N Z;
      
  /* 16-Bit Shitter */
  SHIFTER16 ce aluOut[15..0] mir[26..25] | C[15..0];

  And ba Phase[4] mir[20] clkAndC;
  Not ba clkAndC decEn; 
  /*Nand the clock and Enable c */
      
  /* 16 bit decoder */
  Dec4x16 aa mir[19...16] decEn  regW[15..0];
      
  /* The Registers */
  ResetableReg16 ac C[15..0] regW[15] Reset | R15[15-0];  
  ResetableReg16 ac C[15..0] regW[14] Reset | R14[15-0];  
  ResetableReg16 ac C[15..0] regW[13] Reset | R13[15-0];  
  ResetableReg16 ac C[15..0] regW[12] Reset | R12[15-0];  
  ResetableReg16 ac C[15..0] regW[11] Reset | R11[15-0];  
  ResetableReg16 ac C[15..0] regW[10] Reset | R10[15-0];  

  /* Constants in R7 -5 */
  SMASK ac | R9[15-0];  
  AMASK ac | R8[15-0];  
      
  /* Constants in R7 -5 */
  MinusOneConst ac | R7[15-0]; 
  OneConst  ac | R6[15-0];
  ZeroConst ac | R5[15-0];
      
  /* Resetable Registers R0-R4 */
  ResetableReg16 ac C[15..0] regW[4] Reset | R4[15..0];
  ResetableReg16 ac C[15..0] regW[3] Reset | R3[15..0];
  ResetableReg16 ac C[15..0] regW[2] Reset | R2[15..0];
  ResetableReg16 ac C[15..0] regW[1] Reset | R1[15..0];
  ResetableReg16 ac C[15..0] regW[0] Reset | R0[15..0];
  
Endef;
   
   

Define ZeroConst | D[15-0];
    Or aa ZERO D[15]; Or aa ZERO D[14]; Or aa ZERO D[13]; Or aa ZERO D[12]; 
    Or aa ZERO D[11]; Or aa ZERO D[10]; Or aa ZERO D[9]; Or aa ZERO D[8];
    Or aa ZERO D[7]; Or aa ZERO D[6]; Or aa ZERO D[5]; Or aa ZERO D[4];
    Or aa ZERO D[3]; Or aa ZERO D[2]; Or aa ZERO D[1]; Or aa ZERO D[0];
Endef;

Define OneConst | D[15-0];
    Or aa ZERO D[15]; Or aa ZERO D[14]; Or aa ZERO D[13]; Or aa ZERO D[12]; 
    Or aa ZERO D[11]; Or aa ZERO D[10]; Or aa ZERO D[9]; Or aa ZERO D[8];
    Or aa ZERO D[7]; Or aa ZERO D[6]; Or aa ZERO D[5]; Or aa ZERO D[4];
    Or aa ZERO D[3]; Or aa ZERO D[2]; Or aa ZERO D[1]; Or aa ONE D[0];
Endef;

Define MinusOneConst | D[15-0];
    Or aa ONE D[15]; Or aa ONE D[14]; Or aa ONE D[13]; Or aa ONE D[12]; 
    Or aa ONE D[11]; Or aa ONE D[10]; Or aa ONE D[9]; Or aa ONE D[8];
    Or aa ONE D[7]; Or aa ONE D[6]; Or aa ONE D[5]; Or aa ONE D[4];
    Or aa ONE D[3]; Or aa ONE D[2]; Or aa ONE D[1]; Or aa ONE D[0];
Endef;  

Define AMASK | D[15-0];
    Or aa ZERO D[15]; Or aa ZERO D[14]; Or aa ZERO D[13]; Or aa ZERO D[12]; 
    Or aa ONE D[11]; Or aa ONE D[10]; Or aa ONE D[9]; Or aa ONE D[8];
    Or aa ONE D[7]; Or aa ONE D[6]; Or aa ONE D[5]; Or aa ONE D[4];
    Or aa ONE D[3]; Or aa ONE D[2]; Or aa ONE D[1]; Or aa ONE D[0];
Endef;  

Define SMASK | D[15-0];
    Or aa ZERO D[15]; Or aa ZERO D[14]; Or aa ZERO D[13]; Or aa ZERO D[12]; 
    Or aa ZERO D[11]; Or aa ZERO D[10]; Or aa ZERO D[9]; Or aa ZERO D[8];
    Or aa ONE D[7]; Or aa ONE D[6]; Or aa ONE D[5]; Or aa ONE D[4];
    Or aa ONE D[3]; Or aa ONE D[2]; Or aa ONE D[1]; Or aa ONE D[0];
Endef;  



/* 1-bit Shifter macro. l = bit to left, c = center, r = right, c[1..0] = control
   signals; c[1..0] = [0 0] = Noshift; [0 1] = right shift; [1 0] = left shift
   [1 1] = not used;
*/ 

Define BitShifter l c r c[1..0] | out;
Not aa c[1] b-not;
Not aa c[0] a-not;

And aa b-not a-not c c-out;
And aa b-not c[0] l l-out;
And aa c[1] a-not r r-out;

Or aa c-out l-out r-out out;
Endef;

/* 16-bit shifter ... takes 16 inputs and two control signals c[1..0]
   c[1..0] = 0 0... no shift; = [0 1]... right shift; [1 0]... left shift
   [1 1]... not used;
*/

Define SHIFTER16 a[15..0] c[1..0] | s[15..0];
BitShifter aa a[1] a[0] ZERO c[1..0] | s[0];
BitShifter aa a[2] a[1] a[0] c[1..0] | s[1];
BitShifter aa a[3] a[2] a[1] c[1..0] | s[2];
BitShifter aa a[4] a[3] a[2] c[1..0] | s[3];
BitShifter aa a[5] a[4] a[3] c[1..0] | s[4];
BitShifter aa a[6] a[5] a[4] c[1..0] | s[5];
BitShifter aa a[7] a[6] a[5] c[1..0] | s[6];
BitShifter aa a[8] a[7] a[6] c[1..0] | s[7];
BitShifter aa a[9] a[8] a[7] c[1..0] | s[8];
BitShifter aa a[10] a[9] a[8] c[1..0] | s[9];
BitShifter aa a[11] a[10] a[9] c[1..0] | s[10];
BitShifter aa a[12] a[11] a[10] c[1..0] | s[11];
BitShifter aa a[13] a[12] a[11] c[1..0] | s[12];
BitShifter aa a[14] a[13] a[12] c[1..0] | s[13];
BitShifter aa a[15] a[14] a[13] c[1..0] | s[14];
BitShifter aa ZERO a[15] a[14] c[1..0] | s[15];
Endef;


Define Mux4x2 s[3..0] c[1..0] | o[0];

Not aa c[1] not-a; Not aa c[0] not-b;
And ba not-a not-b s[0] out-0;
And ba not-a c[0]  s[1] out-1;
And ba c[1] not-b s[2] out-2;
And ba c[1] c[0] s[3] out-3;
Or bb out-0 out-1 out-2 out-3 o[0];

Endef;

Define ALU16 a[15..0] b[15..0] c[1..0] | s[15..0] n z;
 
/* Adder big */

Full_Adder aa ZERO b[0] a[0]   | c0 sum0;
Full_Adder aa c0 b[1] a[1]   | c1 sum1;
Full_Adder aa c1 b[2] a[2]   | c2 sum2;
Full_Adder aa c2 b[3] a[3]   | c3 sum3;
Full_Adder aa c3 b[4] a[4]   | c4 sum4;
Full_Adder aa c4 b[5] a[5]   | c5 sum5;
Full_Adder aa c5 b[6] a[6]   | c6 sum6;
Full_Adder aa c6 b[7] a[7]   | c7 sum7;
Full_Adder aa c7 b[8] a[8]   | c8 sum8;
Full_Adder aa c8 b[9] a[9]   | c9 sum9;
Full_Adder aa c9 b[10] a[10] | c10 sum10;
Full_Adder aa c10 b[11] a[11] | c11 sum11;
Full_Adder aa c11 b[12] a[12] | c12 sum12;
Full_Adder aa c12 b[13] a[13] | c13 sum13;
Full_Adder aa c13 b[14] a[14] | c14 sum14;
Full_Adder aa c14 b[15] a[15] | c15 sum15;

/* AND section */

And ab b[0] a[0] and0; 
And ab b[1] a[1] and1; 
And ab b[2] a[2] and2; 
And ab b[3] a[3] and3; 
And ab b[4] a[4] and4; 
And ab b[5] a[5] and5; 
And ab b[6] a[6] and6; 
And ab b[7] a[7] and7; 
And ab b[8] a[8] and8; 
And ab b[9] a[9] and9; 
And ab b[10] a[10] and10; 
And ab b[11] a[11] and11; 
And ab b[12] a[12] and12; 
And ab b[13] a[13] and13; 
And ab b[14] a[14] and14; 
And ab b[15] a[15] and15; 

Not ac a[0] not-a0; 
Not ac a[1] not-a1;
Not ac a[2] not-a2;
Not ac a[3] not-a3;
Not ac a[4] not-a4;
Not ac a[5] not-a5;
Not ac a[6] not-a6;
Not ac a[7] not-a7;
Not ac a[8] not-a8;
Not ac a[9] not-a9;
Not ac a[10] not-a10;
Not ac a[11] not-a11;
Not ac a[12] not-a12;
Not ac a[13] not-a13;
Not ac a[14] not-a14;
Not ac a[15] not-a15;

Mux4x2 bb not-a0 a[0] and0 sum0 c[1] c[0] | s[0]; 
Mux4x2 bb not-a1 a[1] and1 sum1 c[1] c[0] | s[1]; 
Mux4x2 bb not-a2 a[2] and2 sum2 c[1] c[0] | s[2]; 
Mux4x2 bb not-a3 a[3] and3 sum3 c[1] c[0] | s[3]; 
Mux4x2 bb not-a4 a[4] and4 sum4 c[1] c[0] | s[4]; 
Mux4x2 bb not-a5 a[5] and5 sum5 c[1] c[0] | s[5]; 
Mux4x2 bb not-a6 a[6] and6 sum6 c[1] c[0] | s[6]; 
Mux4x2 bb not-a7 a[7] and7 sum7 c[1] c[0] | s[7]; 
Mux4x2 bb not-a8 a[8] and8 sum8 c[1] c[0] | s[8]; 
Mux4x2 bb not-a9 a[9] and9 sum9 c[1] c[0] | s[9]; 
Mux4x2 bb not-a10 a[10] and10 sum10 c[1] c[0] | s[10]; 
Mux4x2 bb not-a11 a[11] and11 sum11 c[1] c[0] | s[11]; 
Mux4x2 bb not-a12 a[12] and12 sum12 c[1] c[0] | s[12]; 
Mux4x2 bb not-a13 a[13] and13 sum13 c[1] c[0] | s[13]; 
Mux4x2 bb not-a14 a[14] and14 sum14 c[1] c[0] | s[14]; 
Mux4x2 bb not-a15 a[15] and15 sum15 c[1] c[0] | s[15];

/* A little boolean algebra saves a lot of repetition
   -a + -b + -c... = - (a v b v c)  */
  
Or ba s[15..0] one;
Not ba one z;

And bb s[15] ONE n;

Endef;

