// monitor.v // // Navtej Sadhal // EECS Dept., UC Berkeley // Created Oct 12 2003 // Modified Jul 20 2004 // // This monitor was originally created for the pipelined MIPS processor in // cs152 during the Fall of 2003. It has been modified to work with the // MIPS processor project for CS61C in the Summer of 2004. All of the // stall/hazard logic has been removed and now the monitor works only with // a simple pipeline. It still has support for many more instructions than // are implemented in the CS61C project, however. // // Instructions are printed when they reach the MEM stage but data is drawn // from all the other stages (except WB) in the pipeline. The monitor keeps // its own internal pipeline so it can match the CPU's pipeline. To make this // monitor work with stalls or bubbles, the monitor will have to know when // each pipeline register gets disabled or reset. module monitor(clk,rst, address,instruction,regOut1,regOut2,regWriteData); input clk,rst; input [31:0] address; // from IF input [31:0] instruction; // from IF input [31:0] regOut1; // from EX input [31:0] regOut2; // from EX input [31:0] regWriteData; // from MEM wire [15:0] immed; wire [4:0] rd; wire [4:0] rs; wire [4:0] rt; wire [4:0] shamt; wire [5:0] opcode; wire [5:0] func; wire [25:0] jimmed; wire [19:0] breakcode; reg rstDone=1'b0; // to see if the whole system has been reset yet. // registers for keeping track of stuff until MEM stage reg [31:0] IDinstruction, EXinstruction, MEMinstruction; reg [31:0] MEMregOut1, MEMregOut2; reg [31:0] IFaddress, IDaddress, EXaddress, MEMaddress; // these wires make referring to parts of the instruction easier. wire [31:0] inst, reg1Data, reg2Data, addr; // use these assigns to control which stage the monitor reads from the DP assign inst = MEMinstruction; assign reg1Data = MEMregOut1; assign reg2Data = MEMregOut2; assign addr = MEMaddress; assign immed = inst[15:0]; assign rs = inst[25:21]; assign rt = inst[20:16]; assign rd = inst[15:11]; assign shamt = inst[10:6]; assign opcode = inst[31:26]; assign func = inst[5:0]; assign jimmed = inst[25:0]; assign breakcode = inst[25:6]; always @ (posedge clk) begin if (rst) rstDone = 1'b1; else if (rstDone) begin $write("time: %d ", $time); $write("0x%h: ", addr); case (opcode) 6'b000010: $write("j 0x%h", jimmed); 6'b000011: $write("jal 0x%h", jimmed); 6'b000100: $write("beq r%d, r%d, %d", rs, rt, immed); 6'b000101: $write("bne r%d, r%d, %d", rs, rt, immed); 6'b001001: $write("addiu r%d, r%d, %d", rt, rs, immed); 6'b001010: $write("slti r%d, r%d, %d", rt, rs, immed); 6'b001011: $write("sltiu r%d, r%d, %d", rt, rs, immed); 6'b001100: $write("andi r%d, r%d, %d", rt, rs, immed); 6'b001101: $write("ori r%d, r%d, %d", rt, rs, immed); 6'b001110: $write("xori r%d, r%d, %d", rt, rs, immed); 6'b001111: $write("lui r%d, %d", rt, immed); 6'b100011: $write("lw r%d, %d(r%d)", rt, immed, rs); 6'b101011: $write("sw r%d, %d(r%d)", rt, immed, rs); 6'b111111: $write("**HALT**"); 6'b000000: case (func) 6'b000000: $write("sll r%d, r%d, %d", rd, rt, shamt); 6'b000010: $write("srl r%d, r%d, %d", rd, rt, shamt); 6'b000011: $write("sra r%d, r%d, %d", rd, rt, shamt); 6'b001101: $write("break code = %d", breakcode); 6'b010000: $write("mfhi r%d", rd); 6'b010010: $write("mflo r%d", rd); 6'b011001: $write("multu r%d, r%d", rs, rt); 6'b100000: $write("add r%d, r%d, r%d", rd, rs, rt); 6'b100001: $write("addu r%d, r%d, r%d", rd, rs, rt); 6'b100010: $write("sub r%d, r%d, r%d", rd, rs, rt); 6'b100011: $write("subu r%d, r%d, r%d", rd, rs, rt); 6'b100100: $write("and r%d, r%d, r%d", rd, rs, rt); 6'b100101: $write("or r%d, r%d, r%d", rd, rs, rt); 6'b100110: $write("xor r%d, r%d, r%d", rd, rs, rt); 6'b101010: $write("slt r%d, r%d, r%d", rd, rs, rt); 6'b101011: $write("sltu r%d, r%d, r%d", rd, rs, rt); 6'b001000: $write("jr, r%d", rs); default: $write("UNKNOWN INSTRUCTION (funct): %h", inst); endcase 6'b000001: case (rt) 5'b00000: $write("bltz r%d, %d", rs, immed); 5'b00001: $write("bgez r%d, %d", rs, immed); endcase default: $write("UNKNOWN INSTRUCTION (opcode): %h", inst); endcase if (opcode == 6'b000000) if (func == 6'b011001) $write(" R[r%d]=0x%h, R[r%d]=0x%h", rs, reg1Data, rt, reg2Data); else $write(" R[r%d]=0x%h, R[r%d]=0x%h, R[r%d]=0x%h", rs, reg1Data, rt, reg2Data, rd, regWriteData); else if (opcode == 6'b101011 || opcode[5:1] == 5'b00010) $write(" R[r%d]=0x%h, R[r%d]=0x%h", rs, reg1Data, rt, reg2Data); else if (opcode == 6'b00001) $write(" R[r%d]=0x%h", rs, reg1Data); else $write(" R[r%d]=0x%h, R[r%d]=0x%h", rs, reg1Data, rt, regWriteData); $write("\n"); MEMaddress <= EXaddress; MEMinstruction <= EXinstruction; MEMregOut1 <= regOut1; MEMregOut2 <= regOut2; EXaddress <= IDaddress; EXinstruction <= IDinstruction; IDinstruction <= instruction; IDaddress <= address; end end endmodule