NB. Models of Computer (MIPS subset)` discussed in Section 5.4 of NB. Computer Organization & Design by Patterson and Hennessy (page 307) NB. Figure 5-17 / 5-19 NB. Some definitions used below require'circuits.ijs' copy =: # base =: #. rep =: #: take =: {. drop =: }. amend =: } from =: { NB. signed_value of a list of bits signed_value =: monad define digits =. # y. if. 1 = 1 take y. do. ((digits copy 2) base x: y. ) - 2^ x: digits else. base x: y. end. ) NB. sign extend a list of bits sign_extend=: dyad def'((0 >. x. - # y.) copy 1 take y.) , y.' NB. 32 bit binary representation binary_32 =: (32#2) & rep NB. Non-circuit based 32-bit ALU alu_32 =: monad define NB. a and b are each 32-bit arguments NB. the result is 32-bits 'a b' =. y. op =. base x: ALUc if. 2 = op do. ALU_result [ Zero =: -. +./ ALU_result =: binary_32 (base x: a) + base x: b elseif. 6 = op do. ALU_result [ Zero =: -. +./ ALU_result =: binary_32 (base x: a) - base x: b elseif. 0 = op do. ALU_result [ Zero =: -. +./ ALU_result =: a *. b elseif. 1 = op do. ALU_result [ Zero =: -. +./ ALU_result =: a +. b elseif. 7 = op do. ALU_result [ Zero =: -. +./ ALU_result =: binary_32 (signed_value x: a) < signed_value x: b end. ) NB. Some alu_32 tests. NB. a = _2, b = 2 NB. a =: (31#1),0 NB. b=: (30#0), 1 0 NB. add NB. ALUc =: 0 1 0 NB. alu_32 a;b NB. subtract NB. ALUc =: 1 1 0 NB. alu_32 a;b NB. set NB. ALUc =: 1 1 1 NB. alu_32 a;b NB. alu_32 b;a NB. and NB. ALUc =: 0 0 0 NB. alu_32 a ; b NB. or NB. ALUc =: 0 0 1 NB. alu_32 a;b NB. Modeling Memory as an array mem NB. For now, 32K 32-bit words of 0 mem =: 32768 # 0 NB. Certain wires have some value initially. Write_data =: binary_32 0 NB. Establish the memory access signals NB. MemRead =: 1 NB. MemWrite =: 1 NB. Instruction memory fetches. i_access =: monad define Instruction =: binary_32 (base y.) from mem ) NB. test instruction access NB. mem =: (10) 4 amend mem NB. PC =: binary_32 4 NB. i_access PC NB. Data memory accesses and writes. d_access =: monad define 'Address Write_data' =. y. if. MemRead do. Read_Data =: binary_32 (base Address) from mem end. if. MemWrite do. mem =: (base Write_data) (base Address) amend mem end. ) NB. data access tests NB. mem =: 32768 # 0 NB. mem =: (100) 2 amend mem NB. MemRead =: 1 NB. MemWrite =: 0 NB. d_access (binary_32 2); binary_32 100 NB. MemRead =: 0 NB. MemWrite =: 1 NB. d_access (binary_32 2); binary_32 1000 NB. Modeling Register Memory NB. Initially each register and RegWrite are zero NB. register =: 32 # 0 NB. RegWrite =: 0 r_access =: monad define 'read_r1 read_r2 write_r write_data' =. y. Read_data =: > (binary_32 (base read_r1) from register) ; binary_32 (base read_r2) from register if. RegWrite do. register =: (signed_value write_data) (base write_r) amend register else. register end. ) NB. register access test NB. register =: _2 16 (2 3 amend) register NB. r_access 0 0 0 1 0 ; 0 0 0 1 1 ; 0 0 0 0 1 ; binary_32 0 NB. Note that r_access does not inhibit writing NB. to register zero NB. register write test NB. register =: 32 # 0 NB. RegWrite =: 1 NB. r_access 0 0 0 0 0 ; 0 0 0 0 1 ; 0 0 0 0 1 ; a NB. The adder to increment the PC add4 =: monad def'(32#2) rep (base x: y.) + 4x' NB. add4 test NB. add4 a NB. add4 b NB. The adder for computing relative branch addresses adder =: monad define 'a b' =. y. binary_32 (base x: a) + base x: b ) NB. adder tests NB. adder a ; b NB. adder 10 ; _4 NB. a multiplexor mux =: monad define 'selector inputs' =. y. selector from inputs ) NB. increment the PC inc_PC =: monad define new_PC =: add4 PC PC =: > mux PCSrc ; < (adder new_PC ; y.) ; new_PC ) NB. PC increment tests NB. PCSrc =: 0 NB. PC =: a NB. inc_PC (28#0), 1 0 1 0 NB. signed_value PC NB. PCSrc =: 1 NB. PC =: a NB. inc_PC (28#0), 1 0 1 0 NB. signed_value PC NB. left shift 2 shift_left_2 =: monad def'(2 drop y.) , 0 0' NB. left shift 2 tests NB. shift_left_2 b NB. shift_left_2 a NB. proc (execute one machine cycle) proc =: monad define whilst. y. do. i_access PC r_access (21 22 23 24 25 from Instruction);(16 17 18 19 20 from Instruction);(> mux RegDst ; <(11 12 13 14 15 from Instruction); 16 17 18 19 20 from Instruction) ; Write_data alu_32 (0 from Read_data) ; > mux ALUSrc ; < (32 sign_extend (i. 16) from Instruction) ; 1 from Read_data inc_PC shift_left_2 32 sign_extend (i. 16) from Instruction d_access ALU_result ; 1 from Read_data Write_data =: > mux MemtoReg ; < ALU_result ; Read_Data r_access (21 22 23 24 25 from Instruction);(16 17 18 19 20 from Instruction);(> mux RegDst ; <(11 12 13 14 15 from Instruction); 16 17 18 19 20 from Instruction) ; Write_data end. ) NB. Establish the memory access signals NB. MemRead =: 1 NB. MemWrite =: 1 NB. PCSrc =: 0 NB. mem =: 32768 # 0 NB. proc tests NB. PC =: binary_32 4 NB. mem =: (2^16) 4 amend mem NB. proc '' NB. PCSrc =: 1 NB. PC =: binary_32 4 NB. proc '' NB. RegDst =: 0 NB. PC =: binary_32 4 NB. mem =: (base 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0) 4 amend mem NB. register =: 32 # 0 NB. register =: (7 8 9) 1 2 3 amend register NB. Mem_data =: binary_32 1 NB. proc '' NB. ALU_control ALU_control =: monad define 'F ALUop' =. y. ALUc =: (bitOr (0 from ALUop) , bitAnd (1 from ALUop) , 1 from F) , (bitOr (bitNot 1 from ALUop), bitNot 2 from F) , bitAnd (1 from ALUop) , bitOr 0 3 from F ) NB. Multi-input and gate multiAnd =: *. / NB. Multi-input or gate multiOr =: +. / NB. Control Control =: monad define ALUOp1 =: RegDst =: R_format =. multiAnd -. y. MemtoReg =: MemRead =: lw =. multiAnd (5 1 0 from y.) , -. 4 3 2 from y. MemWrite =: sw =. multiAnd (5 3 1 0 from y.) , -. 4 2 from y. ALUOp0 =: Branch =: beq =. (2 from y.) , -. 5 4 3 1 0 from y. ALUSrc =: bitOr lw , sw RegWrite =: R_format , lw RetDst,ALUSrc,MemtoReg,RegWrite,MemRead,MemWrite,Branch,ALUOp1,ALUOp0 )