|
| 1 | +package treecorel3 |
| 2 | + |
| 3 | +import chisel._ |
| 4 | +import chisel.util._ |
| 5 | + |
| 6 | +object Const { |
| 7 | + val PC_START = 0x200 |
| 8 | + val PC_EVEC = 0x100 |
| 9 | +} |
| 10 | + |
| 11 | +class DataPathIO(implicit p: Parameters) extends Bundle { |
| 12 | + val host = new HostIO |
| 13 | + val icache = Flipped(new CacheIO) |
| 14 | + val dcache = Flipped(new CacheIO) |
| 15 | + val ctrl = Flipped(new ControlIO) |
| 16 | +} |
| 17 | + |
| 18 | +class Datapath(implicit val p: Parameters) extends Module { |
| 19 | + val io = IO(new DataPathIO) |
| 20 | + val csr = Module(new CSR) |
| 21 | + val regFile = Module(new RegFile) |
| 22 | + val alu = Module(new ALU) |
| 23 | + val immGen = Module(new IMMGen) |
| 24 | + val brCond = p(BuildBrCond)(p) |
| 25 | + |
| 26 | + import Control._ |
| 27 | + |
| 28 | + // fetch / execute Register |
| 29 | + val fe_inst = RegInit(Instruction.NOP) |
| 30 | + val fe_pc = Reg(UInt()) |
| 31 | + |
| 32 | + // execute / write Back Registers |
| 33 | + val ew_inst = RegInit(Instruction.NOP) |
| 34 | + val ew_pc = Reg(UInt()) |
| 35 | + val ew_alu = Reg(UInt()) |
| 36 | + val csr_in = Reg(UInt()) |
| 37 | + |
| 38 | + // control signals |
| 39 | + val st_type = Reg(io.ctrl.st_type.cloneType) |
| 40 | + val ld_type = Reg(io.ctrl.ld_type.cloneType) |
| 41 | + val wb_sel = Reg(io.ctrl.wb_sel.cloneType) |
| 42 | + val wb_en = Reg(Bool()) |
| 43 | + val csr_cmd = Reg(io.ctrl.csr_cmd.cloneType) |
| 44 | + val illegal = Reg(Bool()) |
| 45 | + val pc_check = Reg(Bool()) |
| 46 | + |
| 47 | + // fetch |
| 48 | + val started = RegNext(reset.asBool()) |
| 49 | + val stall = !io.icache.resp.valid || !io.dcache.resp.valid |
| 50 | + val pc = RegInit(Const.PC_START.U(xlen.W) - 4.U(xlen.W)) |
| 51 | + val npc = Mux( |
| 52 | + stall, |
| 53 | + pc, |
| 54 | + Mux( |
| 55 | + csr.io.expt, |
| 56 | + csr.io.evec, |
| 57 | + Mux(io.ctrl.pc_sel === PC_EPC, csr.io.epc, Mux(io.ctrl.pc_sel === PC_ALU || brCond.io.taken, alu.io.sum >> 1.U << 1.U, Mux(io.ctrl.pc_sel === PC_0, pc, pc + 4.U))) |
| 58 | + ) |
| 59 | + ) |
| 60 | + val inst = Mux(started || io.ctrl.inst_kill || brCond.io.taken || csr.io.expt, Instruction.NOP, io.icache.resp.bits.data) |
| 61 | + pc := npc |
| 62 | + io.icache.req.bits.addr := npc |
| 63 | + io.icache.req.bits.data := 0.U |
| 64 | + io.icache.req.bits.mask := 0.U |
| 65 | + io.icache.req.valid := !stall |
| 66 | + io.icache.abort := false.B |
| 67 | + |
| 68 | + // Pipelining |
| 69 | + when(!stall) { |
| 70 | + fe_pc := pc |
| 71 | + fe_inst := inst |
| 72 | + } |
| 73 | + |
| 74 | + // execute |
| 75 | + // decode |
| 76 | + io.ctrl.inst := fe_inst |
| 77 | + |
| 78 | + // regFile read |
| 79 | + val rd_addr = fe_inst(11, 7) |
| 80 | + val rs1_addr = fe_inst(19, 15) |
| 81 | + val rs2_addr = fe_inst(24, 20) |
| 82 | + regFile.io.raddr1 := rs1_addr |
| 83 | + regFile.io.raddr2 := rs2_addr |
| 84 | + |
| 85 | + // gen immdeates |
| 86 | + immGen.io.inst := fe_inst |
| 87 | + immGen.io.sel := io.ctrl.imm_sel |
| 88 | + |
| 89 | + // bypass |
| 90 | + val wb_rd_addr = ew_inst(11, 7) |
| 91 | + val rs1hazard = wb_en && rs1_addr.orR && (rs1_addr === wb_rd_addr) |
| 92 | + val rs2hazard = wb_en && rs2_addr.orR && (rs2_addr === wb_rd_addr) |
| 93 | + val rs1 = Mux(wb_sel === WB_ALU && rs1hazard, ew_alu, regFile.io.rdata1) |
| 94 | + val rs2 = Mux(wb_sel === WB_ALU && rs2hazard, ew_alu, regFile.io.rdata2) |
| 95 | + |
| 96 | + // ALU operations |
| 97 | + alu.io.A := Mux(io.ctrl.A_sel === A_RS1, rs1, fe_pc) |
| 98 | + alu.io.B := Mux(io.ctrl.B_sel === B_RS2, rs2, immGen.io.out) |
| 99 | + alu.io.alu_op := io.ctrl.alu_op |
| 100 | + |
| 101 | + // Branch condition calc |
| 102 | + brCond.io.rs1 := rs1 |
| 103 | + brCond.io.rs2 := rs2 |
| 104 | + brCond.io.br_type := io.ctrl.br_type |
| 105 | + |
| 106 | + // dcache access |
| 107 | + val daddr = Mux(stall, ew_alu, alu.io.sum) >> 2.U << 2.U |
| 108 | + val woffset = alu.io.sum(1) << 4.U | alu.io.sum(0) << 3.U |
| 109 | + io.dcache.req.valid := !stall && (io.ctrl.st_type.orR || io.ctrl.ld_type.orR) |
| 110 | + io.dcache.req.bits.addr := daddr |
| 111 | + io.dcache.req.bits.data := rs2 << woffset |
| 112 | + io.dcache.req.bits.mask := MuxLookup( |
| 113 | + Mux(stall, st_type, io.ctrl.st_type), |
| 114 | + "b0000".U, |
| 115 | + Seq( |
| 116 | + ST_SW -> "b1111".U, |
| 117 | + ST_SH -> ("b11".U << alu.io.sum(1, 0)), |
| 118 | + ST_SB -> ("b1".U << alu.io.sum(1, 0)) |
| 119 | + ) |
| 120 | + ) |
| 121 | + |
| 122 | + // pipelining |
| 123 | + when(reset.asBool() || !stall && csr.io.expt) { |
| 124 | + st_type := 0.U |
| 125 | + ld_type := 0.U |
| 126 | + wb_en := false.B |
| 127 | + csr_cmd := 0.U |
| 128 | + illegal := false.B |
| 129 | + pc_check := false.B |
| 130 | + }.elsewhen(!stall && !csr.io.expt) { |
| 131 | + ew_pc := fe_pc |
| 132 | + ew_inst := fe_inst |
| 133 | + ew_alu := alu.io.out |
| 134 | + csr_in := Mux(io.ctrl.imm_sel === IMM_Z, immGen.io.out, rs1) |
| 135 | + st_type := io.ctrl.st_type |
| 136 | + ld_type := io.ctrl.ld_type |
| 137 | + wb_sel := io.ctrl.wb_sel |
| 138 | + wb_en := io.ctrl.wb_en |
| 139 | + csr_cmd := io.ctrl.csr_cmd |
| 140 | + illegal := io.ctrl.illegal |
| 141 | + pc_check := io.ctrl.pc_sel === PC_ALU |
| 142 | + } |
| 143 | + |
| 144 | + // load |
| 145 | + val loffset = ew_alu(1) << 4.U | ew_alu(0) << 3.U |
| 146 | + val lshift = io.dcache.resp.bits.data >> loffset |
| 147 | + val load = MuxLookup( |
| 148 | + ld_type, |
| 149 | + io.dcache.resp.bits.data.zext, |
| 150 | + Seq( |
| 151 | + LD_LH -> lshift(15, 0).asSInt, |
| 152 | + LD_LB -> lshift(7, 0).asSInt, |
| 153 | + LD_LHU -> lshift(15, 0).zext, |
| 154 | + LD_LBU -> lshift(7, 0).zext |
| 155 | + ) |
| 156 | + ) |
| 157 | + |
| 158 | + // CSR access |
| 159 | + csr.io.stall := stall |
| 160 | + csr.io.in := csr_in |
| 161 | + csr.io.cmd := csr_cmd |
| 162 | + csr.io.inst := ew_inst |
| 163 | + csr.io.pc := ew_pc |
| 164 | + csr.io.addr := ew_alu |
| 165 | + csr.io.illegal := illegal |
| 166 | + csr.io.pc_check := pc_check |
| 167 | + csr.io.ld_type := ld_type |
| 168 | + csr.io.st_type := st_type |
| 169 | + io.host <> csr.io.host |
| 170 | + |
| 171 | + // Regfile Write |
| 172 | + val regWrite = MuxLookup( |
| 173 | + wb_sel, |
| 174 | + ew_alu.zext, |
| 175 | + Seq( |
| 176 | + WB_MEM -> load, |
| 177 | + WB_PC4 -> (ew_pc + 4.U).zext, |
| 178 | + WB_CSR -> csr.io.out.zext |
| 179 | + ) |
| 180 | + ).asUInt |
| 181 | + |
| 182 | + regFile.io.wen := wb_en && !stall && !csr.io.expt |
| 183 | + regFile.io.waddr := wb_rd_addr |
| 184 | + regFile.io.wdata := regWrite |
| 185 | + |
| 186 | + // Abort store when there's an excpetion |
| 187 | + io.dcache.abort := csr.io.expt |
| 188 | + |
| 189 | + if (p(Trace)) { |
| 190 | + printf("PC: %x, INST: %x, REG[%d] <- %x\n", ew_pc, ew_inst, Mux(regFile.io.wen, wb_rd_addr, 0.U), Mux(regFile.io.wen, regFile.io.wdata, 0.U)) |
| 191 | + } |
| 192 | +} |
0 commit comments