From 162ae049dc89c5b5fd8c0c1cd94e1d5593a4f2e3 Mon Sep 17 00:00:00 2001 From: Yifan Ruan Date: Mon, 13 Jun 2022 04:54:00 +0800 Subject: [PATCH] lab4 --- Makefile | 2 +- vsrc/include/pipes.sv | 103 +++++++++++++++- vsrc/pipeline/core.sv | 93 +++++++++++--- vsrc/pipeline/csr/csr.sv | 138 +++++++++++++++++++++ vsrc/pipeline/decode/decode.sv | 7 +- vsrc/pipeline/decode/decoder.sv | 175 ++++++++++++++++++++++++--- vsrc/pipeline/decode/immgen.sv | 3 + vsrc/pipeline/decode/jump.sv | 9 +- vsrc/pipeline/execute/alu.sv | 6 + vsrc/pipeline/execute/execute.sv | 4 +- vsrc/pipeline/fetch/fetch.sv | 12 +- vsrc/pipeline/fetch/selectpc.sv | 6 +- vsrc/pipeline/hazard/hazard.sv | 37 +++++- vsrc/pipeline/memory/memory.sv | 70 +++++++++-- vsrc/pipeline/writeback/writeback.sv | 38 +++++- 15 files changed, 630 insertions(+), 73 deletions(-) create mode 100644 vsrc/pipeline/csr/csr.sv diff --git a/Makefile b/Makefile index f8acf16..a503738 100644 --- a/Makefile +++ b/Makefile @@ -57,7 +57,7 @@ microbench: ./build/emu --diff ./riscv64-nemu-interpreter-so -i ./ready-to-run/challenge/microbench-riscv64-nutshell.bin $(VOPT) || true test-lab4: sim - TEST=$(TEST) ./build/emu --diff ./riscv64-nemu-interpreter-so -i ./ready-to-run/lab4/all-test-priv.bin $(VOPT) || true + TEST=$(TEST) ./build/emu --no-diff -i ./ready-to-run/lab4/all-test-priv.bin $(VOPT) || true test-lab4full: sim TEST=$(TEST) ./build/emu --diff ./riscv64-nemu-interpreter-so -i ./ready-to-run/lab4/all-test-privfull.bin $(VOPT) || true diff --git a/vsrc/include/pipes.sv b/vsrc/include/pipes.sv index 1cfc138..eda19b1 100644 --- a/vsrc/include/pipes.sv +++ b/vsrc/include/pipes.sv @@ -9,7 +9,7 @@ package pipes; import common::*; /* Define instrucion decoding rules here */ -/* rv64i + rv64im */ +/* rv64i + rv64im + csr */ parameter OP_LUI = 7'b0110111; @@ -97,6 +97,18 @@ parameter F3_SRLW = 3'b101; parameter F3_REMW = 3'b110; parameter F3_REMUW = 3'b111; +parameter OP_SYSTEM = 7'b1110011; +parameter F3_PRIV = 3'b000; + parameter F25_ECALL = 25'b0000000000000000000000000; + parameter F25_MRET = 25'b0011000000100000000000000; +parameter F3_CSSRW = 3'b001; +parameter F3_CSRRS = 3'b010; +parameter F3_CSRRC = 3'b011; +parameter F3_CSSRWI = 3'b101; +parameter F3_CSRRSI = 3'b110; +parameter F3_CSRRCI = 3'b111; + +parameter OP_ZERO = 7'b0000000; /* Define pipeline structures here */ @@ -117,13 +129,15 @@ typedef enum logic [4:0] { ALU_RIGHT6_SEXT, ALU_RIGHT32, ALU_RIGHT32_SEXT, - ALU_NEXT_PC + ALU_NEXT_PC, + ALU_AND_REV, + ALU_REV_AND } alufunc_t; typedef struct packed { u32 raw_instr; u64 pc; - u1 valid; + u1 valid, instr_misalign; } fetch_data_t; typedef enum logic [2:0] { @@ -132,9 +146,26 @@ typedef enum logic [2:0] { B, U, S, - J + J, + CSR } decode_op_t; +typedef struct packed { + u1 + is_csr, + is_err, + is_mret, + illegal_instr, + instr_misalign, + is_ecall, + load_misalign, + store_misalign, + csra, + csrb; + u64 csrs; + csr_addr_t csr; +} csr_control_t; + typedef struct packed { u32 raw_instr; u1 PCSel, RegWEn, BrUn, BSel, ASel, ra1En, ra2En, WBSel, SltEn, EqEn, LTEn, EqSel, LTSel, mem_unsigned, loadEn; @@ -145,6 +176,7 @@ typedef struct packed { u2 multiplyEn; // {W, is} u4 divideEn; // {W, is, type_rem, unsgn} creg_addr_t wa; + csr_control_t csr; } control_t; typedef struct packed { @@ -167,6 +199,69 @@ typedef struct packed { u1 valid, addr31; } memory_data_t; +// csrs +parameter u12 CSR_MHARTID = 12'hf14; +parameter u12 CSR_MIE = 12'h304; +parameter u12 CSR_MIP = 12'h344; +parameter u12 CSR_MTVEC = 12'h305; +parameter u12 CSR_MSTATUS = 12'h300; +parameter u12 CSR_MSCRATCH = 12'h340; +parameter u12 CSR_MEPC = 12'h341; +parameter u12 CSR_SATP = 12'h180; +parameter u12 CSR_MCAUSE = 12'h342; +parameter u12 CSR_MCYCLE = 12'hb00; +parameter u12 CSR_MTVAL = 12'h343; + +typedef struct packed { + u1 sd; + logic [MXLEN-2-36:0] wpri1; + u2 sxl; + u2 uxl; + u9 wpri2; + u1 tsr; + u1 tw; + u1 tvm; + u1 mxr; + u1 sum; + u1 mprv; + u2 xs; + u2 fs; + u2 mpp; + u2 wpri3; + u1 spp; + u1 mpie; + u1 wpri4; + u1 spie; + u1 upie; + u1 mie; + u1 wpri5; + u1 sie; + u1 uie; +} mstatus_t; + +typedef struct packed { + u4 mode; + u16 asid; + u44 ppn; +} satp_t; + +typedef struct packed { + u64 + mhartid, // Hardware thread Id, read-only as 0 in this work + mie, // Machine interrupt-enable register + mip, // Machine interrupt pending + mtvec; // Machine trap-handler base address + mstatus_t + mstatus; // Machine status register + u64 + mscratch, // Scratch register for machine trap handlers + mepc, // Machine exception program counter + satp, // Supervisor address translation and protection, read-only as 0 in this work + mcause, // Machine trap cause + mcycle, // Counter + mtval; +} csr_regs_t; + endpackage `endif diff --git a/vsrc/pipeline/core.sv b/vsrc/pipeline/core.sv index 95be383..1b4259b 100644 --- a/vsrc/pipeline/core.sv +++ b/vsrc/pipeline/core.sv @@ -17,6 +17,7 @@ `include "pipeline/writeback/writeback.sv" `include "pipeline/hazard/hazard.sv" `include "pipeline/forward/forward.sv" +`include "pipeline/csr/csr.sv" `else @@ -63,11 +64,21 @@ module core u64 d_pc, imm; u1 d_valid; + u1 csr_flush, csr_valid; + u64 pc_csr; + + csr_addr_t csr_ra, csr_wa; + u64 csr_rd, csr_wd; + + u1 is_stall, is_int; + selectpc selectpc( .pc_address, .PCSel, .predPC, - .pc_selected(pc_nxt) + .pc_selected(pc_nxt), + .pc_csr, + .csr_flush ); pcreg pcreg( @@ -84,9 +95,7 @@ module core .pc, .dataF_nxt, .imem_wait, - .predPC, - .clk, - .reset + .predPC ); freg freg( @@ -104,7 +113,8 @@ module core .ctl, .d_pc, .d_valid, - .imm + .imm, + .csr_ra ); forward forward( @@ -133,7 +143,8 @@ module core .dataD_nxt, .last_pc(dataF_nxt.pc), .PCSel, - .pc_address + .pc_address, + .csr_rd ); hazard hazard( @@ -146,7 +157,9 @@ module core .FWrite, .DWrite, .EWrite, - .MWrite + .MWrite, + .csr_flush, + .is_stall ); dreg dreg( @@ -178,7 +191,10 @@ module core .dreq, .dataE, .dataM_nxt, - .dmem_wait + .dmem_wait, + .clk, + .reset, + .csr_flush ); mreg mreg( @@ -193,9 +209,46 @@ module core .dataM, .wa, .wd, - .wvalid + .wvalid, + .csr_wa, + .csr_wd, + .csr_flush, + .csr_valid, + .is_int ); + u64 real_pc; + always_comb begin + if (dataM.pc > 0) begin + real_pc = dataM.pc; + end else if (dataE.pc > 0) begin + real_pc = dataE.pc; + end else if (dataD.pc > 0) begin + real_pc = dataD.pc; + end else if (dataF.pc > 0) begin + real_pc = dataF.pc; + end else begin + real_pc = dataF_nxt.pc; + end + end + + csr csr( + .clk, + .reset, + .csr_ra, + .csr_rd, + .csr_wa, + .csr_wd, + .csr_control(dataM.ctl.csr), + .pc_csr, + .trint, + .swint, + .exint, + .csr_valid, + .is_stall, + .is_int, + .real_pc + ); regfile regfile( .clk, .reset, @@ -213,7 +266,7 @@ module core .clock (clk), .coreid (0), .index (0), - .valid (~reset && dataM.valid), + .valid (~reset && dataM.valid && ~is_stall), .pc (dataM.pc), .instr (dataM.ctl.raw_instr), .skip (dataM.ctl.MemRW != 2'b00 && dataM.addr31 == 0), @@ -274,21 +327,21 @@ module core DifftestCSRState DifftestCSRState( .clock (clk), .coreid (0), - .priviledgeMode (3), - .mstatus (0), - .sstatus (0 /* mstatus & 64'h800000030001e000 */), - .mepc (0), + .priviledgeMode (csr.mode_nxt[1:0]), + .mstatus (csr.regs_nxt.mstatus), + .sstatus (csr.regs_nxt.mstatus & 64'h800000030001e000), + .mepc (csr.regs_nxt.mepc), .sepc (0), - .mtval (0), + .mtval (csr.regs_nxt.mtval), .stval (0), - .mtvec (0), + .mtvec (csr.regs_nxt.mtvec), .stvec (0), - .mcause (0), + .mcause (csr.regs_nxt.mcause), .scause (0), .satp (0), - .mip (0), - .mie (0), - .mscratch (0), + .mip (csr.regs_nxt.mip), + .mie (csr.regs_nxt.mie), + .mscratch (csr.regs_nxt.mscratch), .sscratch (0), .mideleg (0), .medeleg (0) diff --git a/vsrc/pipeline/csr/csr.sv b/vsrc/pipeline/csr/csr.sv new file mode 100644 index 0000000..390dafd --- /dev/null +++ b/vsrc/pipeline/csr/csr.sv @@ -0,0 +1,138 @@ +`ifndef __CSR_SV +`define __CSR_SV + +`ifdef VERILATOR +`include "include/common.sv" +`include "include/pipes.sv" +`endif + +module csr + import common::*; + import pipes::*;( + input logic clk, reset, + input csr_addr_t csr_ra, csr_wa, + input u64 csr_wd, + output u64 csr_rd, + input u1 csr_valid, + + input csr_control_t csr_control, + input u64 real_pc, + output u64 pc_csr, + input logic trint, swint, exint, + input u1 is_stall, + output u1 is_int +); + csr_regs_t regs, regs_nxt; + u4 mode, mode_nxt; + + wire tr = trint & regs.mie[7]; + wire sw = swint & regs.mie[3]; + wire ex = exint & regs.mie[11]; + assign is_int = regs.mstatus.mie & (tr | sw | ex); + + always_ff @(posedge clk) begin + if (reset) begin + regs <= '0; + regs.mcause[1] <= 1'b1; + regs.mepc[31] <= 1'b1; + mode <= 4'b0011; + end else if (~is_stall) begin + regs <= regs_nxt; + mode <= mode_nxt; + end + end + + // read + always_comb begin + csr_rd = '0; + unique case(csr_ra) + CSR_MIE: csr_rd = regs.mie; + CSR_MIP: csr_rd = regs.mip; + CSR_MTVEC: csr_rd = regs.mtvec; + CSR_MSTATUS: csr_rd = regs.mstatus; + CSR_MSCRATCH: csr_rd = regs.mscratch; + CSR_MEPC: csr_rd = regs.mepc; + CSR_MCAUSE: csr_rd = regs.mcause; + CSR_MCYCLE: csr_rd = regs.mcycle; + CSR_MTVAL: csr_rd = regs.mtval; + default: begin + + end + endcase + end + + // write + always_comb begin + regs_nxt = regs; + mode_nxt = mode; + regs_nxt.mcycle = regs.mcycle + 1; + regs_nxt.mip[7] = trint; + regs_nxt.mip[3] = swint; + regs_nxt.mip[11] = exint; + // Writeback: W stage + if (csr_control.is_err) begin + regs_nxt.mepc = real_pc; + pc_csr = regs.mtvec; + regs_nxt.mstatus.mpie = regs.mstatus.mie; + regs_nxt.mstatus.mie = 0; + regs_nxt.mstatus.mpp = mode[1:0]; + // mcause + if (csr_control.illegal_instr) begin + regs_nxt.mcause = 2; + end else if (csr_control.instr_misalign) begin + regs_nxt.mcause = 0; + end else if (csr_control.is_ecall) begin + regs_nxt.mcause[63] = 0; + regs_nxt.mcause[3:0] = mode + 8; + end else if (csr_control.load_misalign) begin + regs_nxt.mcause = 4; + end else if (csr_control.store_misalign) begin + regs_nxt.mcause = 6; + end + mode_nxt = 3; + end else if (is_int) begin + regs_nxt.mepc = real_pc; + pc_csr = regs.mtvec; + regs_nxt.mstatus.mpie = regs.mstatus.mie; + regs_nxt.mstatus.mie = 0; + regs_nxt.mstatus.mpp = mode[1:0]; + mode_nxt = 3; + if (tr) begin + regs_nxt.mcause = 7; + end else if (sw) begin + regs_nxt.mcause = 3; + end else if (ex) begin + regs_nxt.mcause = 11; + end + regs_nxt.mcause[63] = 1'b1; + end else if (csr_valid) begin + unique case(csr_wa) + CSR_MIE: regs_nxt.mie = csr_wd; + CSR_MIP: regs_nxt.mip = csr_wd; + CSR_MTVEC: regs_nxt.mtvec = csr_wd; + CSR_MSTATUS: regs_nxt.mstatus = csr_wd; + CSR_MSCRATCH: regs_nxt.mscratch = csr_wd; + CSR_MEPC: regs_nxt.mepc = csr_wd; + CSR_MCAUSE: regs_nxt.mcause = csr_wd; + CSR_MCYCLE: regs_nxt.mcycle = csr_wd; + CSR_MTVAL: regs_nxt.mtval = csr_wd; + default: begin + + end + endcase + regs_nxt.mstatus.sd = regs_nxt.mstatus.fs != 0; + pc_csr = real_pc + 4; + end else if (csr_control.is_mret) begin + mode_nxt[1:0] = regs.mstatus.mpp; + regs_nxt.mstatus.mie = regs_nxt.mstatus.mpie; + regs_nxt.mstatus.mpie = 1'b1; + regs_nxt.mstatus.mpp = 2'b0; + regs_nxt.mstatus.xs = 0; + pc_csr = regs.mepc; + end + end + + +endmodule + +`endif diff --git a/vsrc/pipeline/decode/decode.sv b/vsrc/pipeline/decode/decode.sv index 7be90ce..2349940 100644 --- a/vsrc/pipeline/decode/decode.sv +++ b/vsrc/pipeline/decode/decode.sv @@ -18,17 +18,20 @@ module decode output control_t ctl, output u64 d_pc, output u1 d_valid, - output u64 imm + output u64 imm, + output csr_addr_t csr_ra ); decoder decoder( .raw_instr(dataF.raw_instr), - .ctl + .ctl, + .instr_misalign(dataF.instr_misalign) ); assign ra1 = ctl.ra1En ? dataF.raw_instr[19:15] : '0; assign ra2 = ctl.ra2En? dataF.raw_instr[24:20] : '0; assign d_pc = dataF.pc; assign d_valid = dataF.valid; + assign csr_ra = ctl.csr.csr; immgen immgen( .raw_instr(dataF.raw_instr), diff --git a/vsrc/pipeline/decode/decoder.sv b/vsrc/pipeline/decode/decoder.sv index c0de95e..c01ea3e 100644 --- a/vsrc/pipeline/decode/decoder.sv +++ b/vsrc/pipeline/decode/decoder.sv @@ -12,12 +12,14 @@ module decoder import common::*; import pipes::*;( input u32 raw_instr, - output control_t ctl + output control_t ctl, + input u1 instr_misalign ); wire [6:0] opcode = raw_instr[6:0]; wire [2:0] funct3 = raw_instr[14:12]; wire [6:0] funct7 = raw_instr[31:25]; wire [5:0] funct6 = raw_instr[31:26]; + wire [24:0] funct25 = raw_instr[31:7]; always_comb begin @@ -67,7 +69,9 @@ module decoder ctl.mem_unsigned = 1'b1; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -102,7 +106,9 @@ module decoder ctl.LTEn = 1'b1; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -127,7 +133,9 @@ module decoder ctl.msize = MSIZE8; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -175,7 +183,9 @@ module decoder ctl.ALUSel = ALU_RIGHT6_SEXT; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -186,7 +196,9 @@ module decoder ctl.ALUSel = ALU_AND; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -209,7 +221,9 @@ module decoder ctl.multiplyEn = 2'b01; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -234,7 +248,9 @@ module decoder ctl.divideEn = 4'b0100; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -250,7 +266,9 @@ module decoder ctl.divideEn = 4'b0101; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -263,7 +281,9 @@ module decoder ctl.divideEn = 4'b0110; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -276,12 +296,16 @@ module decoder ctl.divideEn = 4'b0111; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -308,12 +332,16 @@ module decoder ctl.ALUSel = ALU_RIGHT32_SEXT; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -336,7 +364,9 @@ module decoder ctl.multiplyEn = 2'b11; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -358,7 +388,9 @@ module decoder ctl.divideEn = 4'b1101; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -369,7 +401,9 @@ module decoder ctl.divideEn = 4'b1111; end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase end @@ -390,10 +424,115 @@ module decoder ctl.wa = raw_instr[11:7]; ctl.ra1En = 1'b1; end + OP_SYSTEM: begin + unique case(funct3) + F3_PRIV: begin + unique case(funct25) + F25_ECALL: begin + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.is_ecall = 1'b1; + end + F25_MRET: begin + ctl.csr.is_csr = 1'b1; + ctl.csr.is_mret = 1'b1; + end + default: begin + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; + end + endcase + end + F3_CSSRW: begin + ctl.csr.is_csr = 1'b1; + ctl.ra1En = 1'b1; + ctl.RegWEn = 1'b1; + ctl.ALUSel = ALU_A; + ctl.WBSel = 1'b1; + ctl.wa = raw_instr[11:7]; + ctl.csr.csr = raw_instr[31:20]; + ctl.csr.csrb = 1'b1; + end + F3_CSRRS: begin + ctl.csr.is_csr = 1'b1; + ctl.ra1En = 1'b1; + ctl.RegWEn = 1'b1; + ctl.ALUSel = ALU_OR; + ctl.WBSel = 1'b1; + ctl.wa = raw_instr[11:7]; + ctl.csr.csr = raw_instr[31:20]; + ctl.csr.csrb = 1'b1; + end + F3_CSRRC: begin + ctl.csr.is_csr = 1'b1; + ctl.ra1En = 1'b1; + ctl.RegWEn = 1'b1; + ctl.ALUSel = ALU_REV_AND; + ctl.WBSel = 1'b1; + ctl.wa = raw_instr[11:7]; + ctl.csr.csr = raw_instr[31:20]; + ctl.csr.csrb = 1'b1; + end + F3_CSSRWI: begin + ctl.csr.is_csr = 1'b1; + ctl.ImmSel = CSR; + ctl.RegWEn = 1'b1; + ctl.ALUSel = ALU_B; + ctl.WBSel = 1'b1; + ctl.BSel = 1'b1; + ctl.wa = raw_instr[11:7]; + ctl.csr.csr = raw_instr[31:20]; + ctl.csr.csra = 1'b1; + end + F3_CSRRSI: begin + ctl.csr.is_csr = 1'b1; + ctl.ImmSel = CSR; + ctl.RegWEn = 1'b1; + ctl.ALUSel = ALU_OR; + ctl.WBSel = 1'b1; + ctl.BSel = 1'b1; + ctl.wa = raw_instr[11:7]; + ctl.csr.csr = raw_instr[31:20]; + ctl.csr.csra = 1'b1; + end + F3_CSRRCI: begin + ctl.csr.is_csr = 1'b1; + ctl.ImmSel = CSR; + ctl.RegWEn = 1'b1; + ctl.ALUSel = ALU_AND_REV; + ctl.WBSel = 1'b1; + ctl.BSel = 1'b1; + ctl.wa = raw_instr[11:7]; + ctl.csr.csr = raw_instr[31:20]; + ctl.csr.csra = 1'b1; + end + default: begin + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; + end + endcase + end default: begin - + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.illegal_instr = 1'b1; end endcase + if (raw_instr == '0) begin + ctl = '0; + ctl.raw_instr = raw_instr; + end + if (instr_misalign) begin + ctl.csr.is_csr = 1'b1; + ctl.csr.is_err = 1'b1; + ctl.csr.instr_misalign = 1'b1; + end + if (raw_instr == 32'h5006b) begin + ctl = '0; + ctl.raw_instr = raw_instr; + end end endmodule diff --git a/vsrc/pipeline/decode/immgen.sv b/vsrc/pipeline/decode/immgen.sv index 89845eb..153b3e6 100644 --- a/vsrc/pipeline/decode/immgen.sv +++ b/vsrc/pipeline/decode/immgen.sv @@ -33,6 +33,9 @@ module immgen J: begin imm = {{44{raw_instr[31]}}, raw_instr[19:12], raw_instr[20], raw_instr[30:21], 1'b0}; end + CSR: begin + imm = {59'b0, raw_instr[19:15]}; + end default: begin end diff --git a/vsrc/pipeline/decode/jump.sv b/vsrc/pipeline/decode/jump.sv index 0f08c73..a5d4688 100644 --- a/vsrc/pipeline/decode/jump.sv +++ b/vsrc/pipeline/decode/jump.sv @@ -18,15 +18,20 @@ module jump output decode_data_t dataD_nxt, input u64 last_pc, output u1 PCSel, - output u64 pc_address + output u64 pc_address, + input u64 csr_rd ); - assign dataD_nxt.ctl = ctl; + // assign dataD_nxt.ctl = ctl; assign dataD_nxt.pc = d_pc; assign dataD_nxt.imm = imm; assign dataD_nxt.rs1 = rs1; assign dataD_nxt.rs2 = rs2; assign dataD_nxt.valid = d_valid; assign dataD_nxt.stalled = '0; + always_comb begin + dataD_nxt.ctl = ctl; + dataD_nxt.ctl.csr.csrs = csr_rd; + end u1 BrLT, BrEq; branchcomp branchcomp( diff --git a/vsrc/pipeline/execute/alu.sv b/vsrc/pipeline/execute/alu.sv index f786590..297d30f 100644 --- a/vsrc/pipeline/execute/alu.sv +++ b/vsrc/pipeline/execute/alu.sv @@ -54,6 +54,12 @@ module alu ALU_NEXT_PC: begin c = a + 4; end + ALU_AND_REV: begin + c = a & ~b; + end + ALU_REV_AND: begin + c = ~a & b; + end default: begin end diff --git a/vsrc/pipeline/execute/execute.sv b/vsrc/pipeline/execute/execute.sv index 876a688..92a9c0a 100644 --- a/vsrc/pipeline/execute/execute.sv +++ b/vsrc/pipeline/execute/execute.sv @@ -22,8 +22,8 @@ module execute ); wire BrLT = dataD.BrLT; u64 a, b, c; - assign a = dataD.ctl.ASel ? dataD.pc : dataD.rs1; - assign b = dataD.ctl.SltEn ? (BrLT ? 1 : 0) : (dataD.ctl.BSel ? dataD.imm : dataD.rs2); + assign a = dataD.ctl.csr.csra ? dataD.ctl.csr.csrs : (dataD.ctl.ASel ? dataD.pc : dataD.rs1); + assign b = dataD.ctl.csr.csrb ? dataD.ctl.csr.csrs : dataD.ctl.SltEn ? (BrLT ? 1 : 0) : (dataD.ctl.BSel ? dataD.imm : dataD.rs2); alu alu( .a, .b, diff --git a/vsrc/pipeline/fetch/fetch.sv b/vsrc/pipeline/fetch/fetch.sv index 938a8db..373bc2f 100644 --- a/vsrc/pipeline/fetch/fetch.sv +++ b/vsrc/pipeline/fetch/fetch.sv @@ -18,16 +18,18 @@ module fetch input u64 pc, output fetch_data_t dataF_nxt, output u1 imem_wait, - output u64 predPC, - - input logic clk, reset + output u64 predPC ); + u1 instr_misalign; + assign instr_misalign = ~(pc[1:0] == 2'b00); + assign ireq.addr = pc; - assign ireq.valid = '1; - assign imem_wait = ~iresp.data_ok; + assign ireq.valid = ~instr_misalign; + assign imem_wait = ~iresp.data_ok & ~instr_misalign; assign dataF_nxt.pc = pc; assign dataF_nxt.raw_instr = iresp.data; assign dataF_nxt.valid = iresp.data_ok; + assign dataF_nxt.instr_misalign = instr_misalign; predictpc predictpc( .pc, diff --git a/vsrc/pipeline/fetch/selectpc.sv b/vsrc/pipeline/fetch/selectpc.sv index 03be4e3..5edd535 100644 --- a/vsrc/pipeline/fetch/selectpc.sv +++ b/vsrc/pipeline/fetch/selectpc.sv @@ -14,9 +14,11 @@ module selectpc input u64 predPC, input u64 pc_address, input u1 PCSel, - output u64 pc_selected + output u64 pc_selected, + input u64 pc_csr, + input u1 csr_flush ); - assign pc_selected = PCSel ? pc_address : predPC; + assign pc_selected = csr_flush ? pc_csr : (PCSel ? pc_address : predPC); endmodule diff --git a/vsrc/pipeline/hazard/hazard.sv b/vsrc/pipeline/hazard/hazard.sv index 6b2c082..b83241f 100644 --- a/vsrc/pipeline/hazard/hazard.sv +++ b/vsrc/pipeline/hazard/hazard.sv @@ -9,15 +9,17 @@ module hazard import common::*; import pipes::*;( - input u1 PCSel, imem_wait, dmem_wait, decode_wait, exe_wait, + input u1 PCSel, imem_wait, dmem_wait, decode_wait, exe_wait, csr_flush, + output u1 is_stall, output u2 PCWrite, FWrite, DWrite, EWrite, MWrite // 2'b00: stream; 2'b01: flush; others: keep ); always_comb begin - PCWrite = '0; - FWrite = '0; - DWrite = '0; - EWrite = '0; MWrite = '0; + EWrite = '0; + DWrite = '0; + FWrite = '0; + PCWrite = '0; + is_stall = '0; if (dmem_wait) begin MWrite = 2'b01; EWrite = 2'b11; @@ -36,14 +38,37 @@ module hazard end else if (imem_wait) begin PCWrite = 2'b11; if (PCSel) begin - FWrite = 2'b11; DWrite = 2'b01; + FWrite = 2'b11; end else begin FWrite = 2'b01; end end else if (PCSel) begin FWrite = 2'b01; end + if (csr_flush) begin + if (dmem_wait) begin + MWrite = 2'b11; + EWrite = 2'b11; + DWrite = 2'b01; + FWrite = 2'b01; + PCWrite = 2'b11; + is_stall = 1'b1; + end else if (imem_wait) begin + MWrite = 2'b11; + EWrite = 2'b01; + DWrite = 2'b01; + FWrite = 2'b01; + PCWrite = 2'b11; + is_stall = 1'b1; + end else begin + MWrite = 2'b01; + EWrite = 2'b01; + DWrite = 2'b01; + FWrite = 2'b01; + PCWrite = 2'b00; + end + end end endmodule diff --git a/vsrc/pipeline/memory/memory.sv b/vsrc/pipeline/memory/memory.sv index ddb7084..0c9670d 100644 --- a/vsrc/pipeline/memory/memory.sv +++ b/vsrc/pipeline/memory/memory.sv @@ -13,14 +13,41 @@ module memory import common::*; import pipes::*;( + input logic clk, reset, input dbus_resp_t dresp, output dbus_req_t dreq, input execute_data_t dataE, output memory_data_t dataM_nxt, - output u1 dmem_wait + output u1 dmem_wait, + input u1 csr_flush ); u64 wd; strobe_t strobe_write; + + u1 valid, valid_nxt; + u1 memory_misalign; + + always_comb begin + memory_misalign = '0; + unique case(dataE.ctl.msize) + MSIZE1: begin + memory_misalign = '0; + end + MSIZE2: begin + memory_misalign = ~(dataE.alu[0] == '0); + end + MSIZE4: begin + memory_misalign = ~(dataE.alu[1:0] == '0); + end + MSIZE8: begin + memory_misalign = ~(dataE.alu[2:0] == '0); + end + default: begin + + end + endcase + end + writedata writedata( .addr(dataE.alu[2:0]), ._wd(dataE.rs2), @@ -28,17 +55,19 @@ module memory .wd, .strobe(strobe_write) ); + + wire flush = csr_flush & ~valid; always_comb begin dreq = '0; unique case (dataE.ctl.MemRW) 2'b10: begin - dreq.valid = '1; + dreq.valid = ~flush & ~memory_misalign; dreq.strobe = '0; dreq.addr = dataE.alu; dreq.size = dataE.ctl.msize; end 2'b11: begin - dreq.valid = '1; + dreq.valid = ~flush & ~memory_misalign; dreq.strobe = strobe_write; dreq.addr = dataE.alu; dreq.data = wd; @@ -51,7 +80,16 @@ module memory endcase end - assign dmem_wait = dreq.valid & ~dresp.data_ok; + assign valid_nxt = dreq.valid; + + always_ff @(posedge clk) begin + if (reset) begin + valid <= '0; + end else begin + valid <= valid_nxt; + end + end + u64 rd; readdata readdata( @@ -61,9 +99,27 @@ module memory .msize(dataE.ctl.msize), .mem_unsigned(dataE.ctl.mem_unsigned) ); - - - assign dataM_nxt.ctl = dataE.ctl; + + always_comb begin + dataM_nxt.ctl = dataE.ctl; + dmem_wait = dreq.valid & ~dresp.data_ok; + unique case (dataE.ctl.MemRW) + 2'b10: if (memory_misalign) begin + dataM_nxt.ctl.csr.is_csr = 1'b1; + dataM_nxt.ctl.csr.is_err = 1'b1; + dataM_nxt.ctl.csr.load_misalign = 1'b1; + end + 2'b11: if (memory_misalign) begin + dataM_nxt.ctl.csr.is_csr = 1'b1; + dataM_nxt.ctl.csr.is_err = 1'b1; + dataM_nxt.ctl.csr.store_misalign = 1'b1; + end + default: begin + + end + endcase + end + assign dataM_nxt.pc = dataE.pc; assign dataM_nxt.valid = dataE.valid; assign dataM_nxt.addr31 = dataE.alu[31]; diff --git a/vsrc/pipeline/writeback/writeback.sv b/vsrc/pipeline/writeback/writeback.sv index 743e83c..ac84477 100644 --- a/vsrc/pipeline/writeback/writeback.sv +++ b/vsrc/pipeline/writeback/writeback.sv @@ -14,11 +14,41 @@ module writeback input memory_data_t dataM, output creg_addr_t wa, output u64 wd, - output u1 wvalid + output u1 wvalid, + + output csr_addr_t csr_wa, + output u64 csr_wd, + output u1 csr_valid, + + output u1 csr_flush, + input u1 is_int ); - assign wa = dataM.ctl.wa; - assign wd = dataM.result; - assign wvalid = dataM.ctl.RegWEn; + always_comb begin + wa = '0; + wd = '0; + wvalid = '0; + csr_wa = '0; + csr_wd = '0; + csr_valid = '0; + csr_flush = '0; + if (dataM.ctl.csr.is_csr) begin + csr_flush = 1; + if (~dataM.ctl.csr.is_err & ~dataM.ctl.csr.is_mret) begin + csr_wa = dataM.ctl.csr.csr; + csr_wd = dataM.result; + csr_valid = 1; + wa = dataM.ctl.wa; + wd = dataM.ctl.csr.csrs; + wvalid = dataM.ctl.RegWEn; + end + end else if (is_int) begin + csr_flush = 1; + end else begin + wa = dataM.ctl.wa; + wd = dataM.result; + wvalid = dataM.ctl.RegWEn; + end + end endmodule