************************************************************************
*** Lab 3, student submission sequence
*** test multiplier
************************************************************************

.include "6004lib/nominal.jsim"
.include "6004lib/stdcell.jsim"
.include "6004lib/lab3_test_mult.jsim"
.include "lib.jsim"
.include "mult32.jsim"
.options plugh2536038 // Magic option to make jsim report checksum

********************************************************************************
*** Boolean ops: use 4 opcode bits as a truth table.
********************************************************************************

.subckt BOOL alufn[3:0] a[31:0] b[31:0] out[31:0]
Xmux a[31:0] b[31:0] alufn0#32 alufn1#32 alufn2#32 alufn3#32 out[31:0] MUX4
.ends

********************************************************************************
*** 32-bit Adder/Subtractor: AddSub32
***
*** addsub = 0:  s = a + b
*** addsub = 1:  s = a - b
***
*** Generates Z, V, N bits
********************************************************************************

.subckt addsub32
+       addsub         // 0 => add, 1 => sub
+       a[31:0]        // 32-bit source operands
+       b[31:0]
+       s[31:0]        // 32-bit result
+       z              // 1 <=> result==0
+       v              // overflow
+       n              // sign bit
Xinv addsub addsubn inverter

Xxr b[31:0] addsubn#32 xb[31:0] xnor2

Xfa a[31:0] xb[31:0] c[31:1] addsub s[31:0] c[32:1] FA

Xz0 s[31:0] za[7:0] nor4
Xz1 za[7:0] zb[1:0] nand4
Xz20 zb0 zb1 z nor2

Xv0 a31 a31n inverter
Xv1 xb31 xb31n inverter
Xv2 s31 s31n inverter
Xv3 a31 xb31 s31n v0 nand3
Xv4 a31n xb31n s31 v1 nand3
Xv5 v0 v1 v nand2

Xn s31n n inverter
.ends

.subckt ARITH alufn[1:0] A[31:0] B[31:0] OUT[31:0] Z V N
xaddsub alufn[0] A[31:0] B[31:0] ADD[31:0] Z V N addsub32

***
*** Heres the optional multipler:
***
Xmul a[31:0] b[31:0] MULT[31:0] mult32

***
*** We mux in in with the add/subtract:
***
Xari alufn1#32 ADD[31:0] MULT[31:0] OUT[31:0] mux2


.ends


********************************************************************************
*** 32-bit barrel shift
********************************************************************************

***
*** left shift:
***
.subckt ls in[31:0] s[4:0] out[31:0]
Xal0 s0#32 in[31:0] in[30:0] 0 ALa[31:0] MUX2
Xal1 s1#32 ALa[31:0] ALa[29:0] 0#2 ALb[31:0] MUX2
Xal2 s2#32 ALb[31:0] ALb[27:0] 0#4 ALc[31:0] MUX2
Xal3 s3#32 ALc[31:0] ALc[23:0] 0#8 ALd[31:0] MUX2
Xal4 s4#32 ALd[31:0] ALd[15:0] 0#16 out[31:0] MUX2
.ends


***
*** right shift.  sign is used to fill vacated bits.
***
.subckt rs in[31:0] s[4:0] out[31:0] sign
Xar0 s0#32 in[31:0] sign in[31:1] ARa[31:0] MUX2
Xar1 s1#32 ARa[31:0] sign#2 ARa[31:2] ARb[31:0] MUX2
Xar2 s2#32 ARb[31:0] sign#4 ARb[31:4] ARc[31:0] MUX2
Xar3 s3#32 ARc[31:0] sign#8 ARc[31:8] ARd[31:0] MUX2
Xar4 s4#32 ARd[31:0] sign#16 ARd[31:16] out[31:0] MUX2
.ends


***
*** Heres the shifter.  It decodes 2 ALU bits to decide
*** between SHL, SHR, and SRA:
***

.subckt shift32 alufn1 alufn0 a[31:0] s[4:0] out[31:0]
Xshl a[31:0] s[4:0] SHL[31:0] ls
Xshr a[31:0] s[4:0] SHR[31:0] 0 rs
Xsar a[31:0] s[4:0] SAR[31:0] a31 rs
Xmux alufn0#32 alufn1#32 SHL[31:0] SHR[31:0] 0#32 SAR[31:0] out[31:0] mux4
.ends


.subckt SHIFT alufn[1:0] A[31:0] B[31:0] OUT[31:0]
xshift alufn[1:0] A[31:0] B[4:0] OUT[31:0] shift32
.ends

********************************************************************************
*** compare32: 32-bit compare logic
********************************************************************************

.subckt CMP alufn3 alufn1 z v n out[31:0]
Xclt n v LT xor2
Xcle LT z LE or2
Xmux alufn3 alufn1 z LE LT 0 out[0] mux4
Xzbit out[31:1] constant0
.ends


*** Here's the top-level ALU framework.
*** We make things work by defining BOOL, SHIFT, ARITH, CMP subckts...
.subckt alu alufn[4:0] a[31:0] b[31:0] out[31:0] z v n

*** Generate outputs from each of BOOL, SHIFT, ARITH, CMP subcircuits:
xbool alufn[3:0] a[31:0] b[31:0] boolout[31:0] BOOL
xshift alufn[1:0] a[31:0] b[31:0] shiftout[31:0] SHIFT
xarith alufn[1:0] a[31:0] b[31:0] arithout[31:0] z v n ARITH
xcmp alufn[3] alufn[1] z v n cmpout[31:0] CMP

*** Combine them, using three multiplexors:
xmux1 alufn[4]#32 nonbool[31:0] boolout[31:0] out[31:0] mux2
xmux2 alufn[2]#32 arithshift[31:0] cmpout[31:0] nonbool[31:0] mux2
xmux3 alufn[3]#32 arithout[31:0] shiftout[31:0] arithshift[31:0] mux2

.ends
