// ************************************************************************** // // // // eses eses // // eses eses // // eses eseses esesese eses Embedded Systems Group // // ese ese ese ese ese // // ese eseseses eseseses ese Department of Computer Science // // eses eses ese eses // // eses eseses eseseses eses University of Kaiserslautern // // eses eses // // // // ************************************************************************** // // ---------------------------------------------------------------------------- // opcodes of the instructions // ---------------------------------------------------------------------------- macro ADD = 0b000000; macro ADDU = 0b000001; macro ADDI = 0b000010; macro ADDIU = 0b000011; macro SUB = 0b000100; macro SUBU = 0b000101; macro SUBI = 0b000110; macro SUBIU = 0b000111; macro MUL = 0b001000; macro MULU = 0b001001; macro MULI = 0b001010; macro MULIU = 0b001011; macro DIV = 0b001100; macro DIVU = 0b001101; macro DIVI = 0b001110; macro DIVIU = 0b001111; macro SLT = 0b010000; macro SLTU = 0b010001; macro SLE = 0b010010; macro SLEU = 0b010011; macro SEQ = 0b010100; macro SNE = 0b010101; macro AND = 0b010110; macro OR = 0b010111; macro NAND = 0b011000; macro NOR = 0b011001; macro LD = 0b011010; macro ST = 0b011011; macro LVWS = 0b011100; macro SVWS = 0b011101; macro LL = 0b011110; macro SC = 0b011111; macro MOV = 0b100000; macro MOVU = 0b100001; macro BEZ = 0b100010; macro BNZ = 0b100011; macro JMP = 0b100100; macro J = 0b100101; macro SYNC = 0b100111; // note that this group of instructions share the same macro OVF = 0b100111; // opcode, and differ in the additional function code macro MVTM = 0b100111; // listed below macro MVFM = 0b100111; macro MVTL = 0b100111; macro MVFL = 0b100111; macro fn_SYNC = 0b0000000; macro fn_OVF = 0b0000001; macro fn_MVTM = 0b0000010; macro fn_MVFM = 0b0000011; macro fn_MVTL = 0b0000100; macro fn_MVFL = 0b0000101; // -------------------------------------------------------------------------- // special macros for this stage // -------------------------------------------------------------------------- macro DataWidth = 8; // bit-width of registers macro One = {true::DataWidth}; // bitvector consisting of 1s macro Zero = {false::DataWidth}; // bitvector consisting of 0s // -------------------------------------------------------------------------- // operations of the ALU: there are always two bitvector inputs of length // DataWidth and the result is always of size 2*DataWidth // -------------------------------------------------------------------------- macro ALUADDS(x1,x2) = int2bv(bv2int(x1) + bv2int(x2),2*DataWidth); macro ALUSUBS(x1,x2) = int2bv(bv2int(x1) - bv2int(x2),2*DataWidth); macro ALUMULS(x1,x2) = int2bv(bv2int(x1) * bv2int(x2),2*DataWidth); macro ALUDIVS(x1,x2) = int2bv(bv2int(x1) % bv2int(x2), DataWidth) @ int2bv(bv2int(x1) / bv2int(x2), DataWidth); macro ALUADDU(x1,x2) = nat2bv(bv2nat(x1) + bv2nat(x2),2*DataWidth); macro ALUSUBU(x1,x2) = nat2bv(bv2nat(x1) - bv2nat(x2),2*DataWidth); macro ALUMULU(x1,x2) = nat2bv(bv2nat(x1) * bv2nat(x2),2*DataWidth); macro ALUDIVU(x1,x2) = nat2bv(bv2nat(x1) % bv2nat(x2), DataWidth) @ nat2bv(bv2nat(x1) / bv2nat(x2), DataWidth); macro ALUSLTS(x1,x2) = Zero@(bv2int(x1) < bv2int(x2)?One:Zero); macro ALUSLTU(x1,x2) = Zero@(bv2nat(x1) < bv2nat(x2)?One:Zero); macro ALUSLES(x1,x2) = Zero@(bv2int(x1) <= bv2int(x2)?One:Zero); macro ALUSLEU(x1,x2) = Zero@(bv2nat(x1) <= bv2nat(x2)?One:Zero); macro ALUSEQ(x1,x2) = Zero@(x1 == x2?One:Zero); macro ALUSNE(x1,x2) = Zero@(x1 != x2?One:Zero); macro ALUAND(x1,x2) = Zero@(x1 & x2); macro ALUOR(x1,x2) = Zero@(x1 | x2); macro ALUNAND(x1,x2) = Zero@(!(x1 & x2)); macro ALUNOR(x1,x2) = Zero@(!(x1 | x2)); // -------------------------------------------------------------------------- // execute stage of the pipeline // -------------------------------------------------------------------------- module Execute( bv{6} ?opc_EX, // opcode of instruction bv{7} ?fnc_EX, // constant operand of S-type instructions bv{10} ?adr_EX, // jump address of J-type instruction nat{8} ?rd_EX, // register destination index bv{DataWidth} ?opS_EX, // value to be stored in case of store op. bv{DataWidth} ?opL_EX,?opR_EX, // ALU operands bv{6} !opc_MA, // opcode of instruction bv{7} !fnc_MA, // constant operand of S-type instructions bv{10} !adr_MA, // jump address of J-type instruction nat{8} !rd_MA, // register destination index bv{DataWidth} !opS_MA, // value to be stored in case of store op. bv{2*DataWidth} alu_EX,alu_MA, // ALU results (immediate and delayed) bool cnd_EX,cnd_MA // result of branch condition ) { case // ---------------------------------------------------------------- // arithmetic instructions // ---------------------------------------------------------------- (opc_EX{5:4}==0b00) do { case (opc_EX{3:2}==0b00 & opc_EX{0}) do alu_EX = ALUADDS(opL_EX,opR_EX); (opc_EX{3:2}==0b00 & !opc_EX{0}) do alu_EX = ALUADDU(opL_EX,opR_EX); (opc_EX{3:2}==0b01 & opc_EX{0}) do alu_EX = ALUSUBS(opL_EX,opR_EX); (opc_EX{3:2}==0b01 & !opc_EX{0}) do alu_EX = ALUSUBU(opL_EX,opR_EX); (opc_EX{3:2}==0b10 & opc_EX{0}) do alu_EX = ALUMULS(opL_EX,opR_EX); (opc_EX{3:2}==0b10 & !opc_EX{0}) do alu_EX = ALUMULU(opL_EX,opR_EX); (opc_EX{3:2}==0b11 & opc_EX{0}) do alu_EX = ALUDIVS(opL_EX,opR_EX); (opc_EX{3:2}==0b11 & !opc_EX{0}) do alu_EX = ALUDIVU(opL_EX,opR_EX); default nothing; } // ---------------------------------------------------------------- // comparison instructions // ---------------------------------------------------------------- (opc_EX==SLT) do alu_EX = ALUSLTS(opL_EX,opR_EX); (opc_EX==SLTU) do alu_EX = ALUSLTU(opL_EX,opR_EX); (opc_EX==SLE) do alu_EX = ALUSLES(opL_EX,opR_EX); (opc_EX==SLEU) do alu_EX = ALUSLEU(opL_EX,opR_EX); (opc_EX==SEQ) do alu_EX = ALUSEQ(opL_EX,opR_EX); (opc_EX==SNE) do alu_EX = ALUSNE(opL_EX,opR_EX); // ---------------------------------------------------------------- // logic instructions // ---------------------------------------------------------------- (opc_EX==AND) do alu_EX = ALUAND(opL_EX,opR_EX); (opc_EX==OR) do alu_EX = ALUOR(opL_EX,opR_EX); (opc_EX==NAND) do alu_EX = ALUNAND(opL_EX,opR_EX); (opc_EX==NOR) do alu_EX = ALUNOR(opL_EX,opR_EX); // ---------------------------------------------------------------- // load and store instructions // ---------------------------------------------------------------- (opc_EX==LD | opc_EX==LL | opc_EX==ST | opc_EX==SC | opc_EX==SYNC & fnc_EX==fn_SYNC) do alu_EX = ALUADDU(opL_EX,opR_EX); // ---------------------------------------------------------------- // moving constants to registers // ---------------------------------------------------------------- (opc_EX==MOV) do alu_EX = ALUADDS(opL_EX,opR_EX); (opc_EX==MOVU) do alu_EX = ALUADDU(opL_EX,opR_EX); // ---------------------------------------------------------------- // branch and jump instructions // ---------------------------------------------------------------- (opc_EX==BEZ | opc_EX==BNZ | opc_EX==JMP | opc_EX==J) do { alu_EX = ALUADDS(opL_EX,opR_EX); if(opc_EX==BEZ) cnd_EX = opL_EX==Zero; if(opc_EX==BNZ) cnd_EX = opL_EX!=Zero; } // ---------------------------------------------------------------- // move content of overflow register to destination register rd // ---------------------------------------------------------------- (opc_EX==OVF & fnc_EX==fn_OVF) do alu_EX = ALUADDS(opL_EX,opR_EX); // ---------------------------------------------------------------- default nothing; // ------------------------------------------------------------------------ // forward the immediate results of the ALU to the memory access stage // ------------------------------------------------------------------------ next(opc_MA) = opc_EX; next(fnc_MA) = fnc_EX; next(adr_MA) = adr_EX; next(rd_MA) = rd_EX; next(opS_MA) = opS_EX; next(alu_MA) = alu_EX; next(cnd_MA) = cnd_EX; }