1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* Copyright (c) 2020-2021 Peng Cheng Laboratory 4* 5* XiangShan is licensed under Mulan PSL v2. 6* You can use this software according to the terms and conditions of the Mulan PSL v2. 7* You may obtain a copy of Mulan PSL v2 at: 8* http://license.coscl.org.cn/MulanPSL2 9* 10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13* 14* See the Mulan PSL v2 for more details. 15***************************************************************************************/ 16 17package xiangshan.backend.issue 18 19import chipsalliance.rocketchip.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import xiangshan._ 23import utils._ 24import xiangshan.backend.decode.{ImmUnion, Imm_LUI_LOAD, Imm_U} 25import xiangshan.backend.exu.ExuConfig 26 27class DataArrayReadIO(numEntries: Int, numSrc: Int, dataBits: Int)(implicit p: Parameters) extends XSBundle { 28 val addr = Input(UInt(numEntries.W)) 29 val data = Vec(numSrc, Output(UInt(dataBits.W))) 30} 31 32class DataArrayWriteIO(numEntries: Int, numSrc: Int, dataBits: Int)(implicit p: Parameters) extends XSBundle { 33 val enable = Input(Bool()) 34 val mask = Vec(numSrc, Input(Bool())) 35 val addr = Input(UInt(numEntries.W)) 36 val data = Vec(numSrc, Input(UInt(dataBits.W))) 37} 38 39class DataArrayMultiWriteIO(numEntries: Int, numSrc: Int, dataBits: Int)(implicit p: Parameters) extends XSBundle { 40 val enable = Input(Bool()) 41 val addr = Vec(numSrc, Input(UInt(numEntries.W))) 42 val data = Input(UInt(dataBits.W)) 43} 44 45class DataArrayDelayedWriteIO(numEntries: Int, numSrc: Int, dataBits: Int)(implicit p: Parameters) extends XSBundle { 46 val mask = Vec(numSrc, Input(Bool())) 47 val addr = Input(UInt(numEntries.W)) 48 val data = Vec(numSrc, Input(UInt(dataBits.W))) 49} 50 51class DataArrayIO(params: RSParams)(implicit p: Parameters) extends XSBundle { 52 val read = Vec(params.numDeq + 1, new DataArrayReadIO(params.numEntries, params.numSrc, params.dataBits)) 53 val write = Vec(params.numEnq, new DataArrayWriteIO(params.numEntries, params.numSrc, params.dataBits)) 54 val multiWrite = Vec(params.numWakeup, new DataArrayMultiWriteIO(params.numEntries, params.numSrc, params.dataBits)) 55 val delayedWrite = if (params.delayedSrc) Vec(params.numEnq, new DataArrayDelayedWriteIO(params.numEntries, params.numSrc, params.dataBits)) else null 56 val partialWrite = if (params.hasMidState) Vec(params.numDeq, new DataArrayWriteIO(params.numEntries, params.numSrc - 1, params.dataBits)) else null 57} 58 59class DataArray(params: RSParams)(implicit p: Parameters) extends XSModule { 60 val io = IO(new DataArrayIO(params)) 61 62 for (i <- 0 until params.numSrc) { 63 val delayedWen = if (params.delayedSrc) io.delayedWrite.map(_.mask(i)) else Seq() 64 val delayedWaddr = if (params.delayedSrc) io.delayedWrite.map(_.addr) else Seq() 65 val delayedWdata = if (params.delayedSrc) io.delayedWrite.map(_.data(i)) else Seq() 66 67 val partialWen = if (i < 2 && params.hasMidState) io.partialWrite.map(w => RegNext(w.enable)) else Seq() 68 val partialWaddr = if (i < 2 && params.hasMidState) io.partialWrite.map(w => RegEnable(w.addr, w.enable)) else Seq() 69 val partialWdata = if (i < 2 && params.hasMidState) io.partialWrite.map(w => RegEnable(w.data(i), w.enable)) else Seq() 70 71 val wen = io.write.map(w => w.enable && w.mask(i)) ++ io.multiWrite.map(_.enable) ++ delayedWen ++ partialWen 72 val waddr = io.write.map(_.addr) ++ io.multiWrite.map(_.addr(i)) ++ delayedWaddr ++ partialWaddr 73 val wdata = io.write.map(_.data(i)) ++ io.multiWrite.map(_.data) ++ delayedWdata ++ partialWdata 74 75 val dataModule = Module(new AsyncRawDataModuleTemplate(UInt(params.dataBits.W), params.numEntries, io.read.length, wen.length)) 76 dataModule.io.rvec := VecInit(io.read.map(_.addr)) 77 io.read.map(_.data(i)).zip(dataModule.io.rdata).foreach{ case (d, r) => d := r } 78 dataModule.io.wen := wen 79 dataModule.io.wvec := waddr 80 dataModule.io.wdata := wdata 81 82 if (i < 2 && params.hasMidState) { 83 for (r <- io.read) { 84 val addr_match = partialWaddr.map(addr => (addr & r.addr).asUInt.orR) 85 val bypass = partialWen.zip(addr_match).map(p => p._1 && p._2) 86 when (VecInit(bypass).asUInt.orR) { 87 r.data(i) := Mux1H(bypass, partialWdata) 88 } 89 } 90 } 91 92 for (i <- 0 until params.numEntries) { 93 val w = VecInit(wen.indices.map(j => dataModule.io.wen(j) && dataModule.io.wvec(j)(i))) 94 XSError(RegNext(PopCount(w) > 1.U), s"why not OH $i?") 95 when(PopCount(w) > 1.U) { 96 XSDebug("ERROR: RS DataArray write overlap!\n") 97 } 98 } 99 } 100 101} 102 103class ImmExtractor(numSrc: Int, dataBits: Int)(implicit p: Parameters) extends XSModule { 104 val io = IO(new Bundle { 105 val uop = Input(new MicroOp) 106 val data_in = Vec(numSrc, Input(UInt(dataBits.W))) 107 val data_out = Vec(numSrc, Output(UInt(dataBits.W))) 108 }) 109 io.data_out := io.data_in 110} 111 112class JumpImmExtractor(implicit p: Parameters) extends ImmExtractor(2, 64) { 113 val jump_pc = IO(Input(UInt(VAddrBits.W))) 114 val jalr_target = IO(Input(UInt(VAddrBits.W))) 115 116 when (SrcType.isPc(io.uop.ctrl.srcType(0))) { 117 io.data_out(0) := SignExt(jump_pc, XLEN) 118 } 119 // when src1 is reg (like sfence's asid) do not let data_out(1) be the jalr_target 120 when (SrcType.isPcOrImm(io.uop.ctrl.srcType(1))) { 121 io.data_out(1) := jalr_target 122 } 123} 124 125class AluImmExtractor(implicit p: Parameters) extends ImmExtractor(2, 64) { 126 when (SrcType.isImm(io.uop.ctrl.srcType(1))) { 127 val imm32 = Mux(io.uop.ctrl.selImm === SelImm.IMM_U, 128 ImmUnion.U.toImm32(io.uop.ctrl.imm), 129 ImmUnion.I.toImm32(io.uop.ctrl.imm) 130 ) 131 io.data_out(1) := SignExt(imm32, XLEN) 132 } 133} 134 135class MduImmExtractor(implicit p: Parameters) extends ImmExtractor(2, 64) { 136 when (SrcType.isImm(io.uop.ctrl.srcType(1))) { 137 val imm32 = ImmUnion.I.toImm32(io.uop.ctrl.imm) 138 io.data_out(1) := SignExt(imm32, XLEN) 139 } 140} 141 142class LoadImmExtractor(implicit p: Parameters) extends ImmExtractor(1, 64) { 143 when (SrcType.isImm(io.uop.ctrl.srcType(0))) { 144 io.data_out(0) := SignExt(Imm_LUI_LOAD().getLuiImm(io.uop), XLEN) 145 } 146} 147 148object ImmExtractor { 149 def apply(params: RSParams, uop: MicroOp, data_in: Vec[UInt], pc: Option[UInt], target: Option[UInt]) 150 (implicit p: Parameters): Vec[UInt] = { 151 val immExt = if (params.isJump) { 152 val ext = Module(new JumpImmExtractor) 153 ext.jump_pc := pc.get 154 ext.jalr_target := target.get 155 ext 156 } 157 else if (params.isAlu) { Module(new AluImmExtractor) } 158 else if (params.isMul) { Module(new MduImmExtractor) } 159 else if (params.isLoad) { Module(new LoadImmExtractor) } 160 else { Module(new ImmExtractor(params.numSrc, params.dataBits)) } 161 immExt.io.uop := uop 162 immExt.io.data_in := data_in 163 immExt.io.data_out 164 } 165} 166