1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* 4* XiangShan is licensed under Mulan PSL v2. 5* You can use this software according to the terms and conditions of the Mulan PSL v2. 6* You may obtain a copy of Mulan PSL v2 at: 7* http://license.coscl.org.cn/MulanPSL2 8* 9* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 10* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 11* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 12* 13* See the Mulan PSL v2 for more details. 14***************************************************************************************/ 15 16package xiangshan 17 18import chisel3._ 19import chisel3.util._ 20import xiangshan.backend._ 21import xiangshan.backend.fu.HasExceptionNO 22import xiangshan.backend.exu.Wb 23import xiangshan.frontend._ 24import xiangshan.cache.{L1plusCacheWrapper, PTWWrapper, PTWRepeater, PTWFilter} 25import chipsalliance.rocketchip.config 26import chipsalliance.rocketchip.config.Parameters 27import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 28import freechips.rocketchip.tile.HasFPUParameters 29import system.{HasSoCParameter, L1CacheErrorInfo} 30import utils._ 31 32abstract class XSModule(implicit val p: Parameters) extends MultiIOModule 33 with HasXSParameter 34 with HasExceptionNO 35 with HasFPUParameters { 36 def io: Record 37} 38 39//remove this trait after impl module logic 40trait NeedImpl { 41 this: RawModule => 42 override protected def IO[T <: Data](iodef: T): T = { 43 println(s"[Warn]: (${this.name}) please reomve 'NeedImpl' after implement this module") 44 val io = chisel3.experimental.IO(iodef) 45 io <> DontCare 46 io 47 } 48} 49 50abstract class XSBundle(implicit val p: Parameters) extends Bundle 51 with HasXSParameter 52 53case class EnviromentParameters 54( 55 FPGAPlatform: Boolean = true, 56 EnableDebug: Boolean = false, 57 EnablePerfDebug: Boolean = true, 58 DualCore: Boolean = false 59) 60 61abstract class XSCoreBase()(implicit p: config.Parameters) extends LazyModule 62 with HasXSParameter 63{ 64 // outer facing nodes 65 val frontend = LazyModule(new Frontend()) 66 val l1pluscache = LazyModule(new L1plusCacheWrapper()) 67 val ptw = LazyModule(new PTWWrapper()) 68 val memBlock = LazyModule(new MemBlock) 69 70 // TODO: better RS organization 71 // generate rs according to number of function units 72 require(exuParameters.JmpCnt == 1) 73 require(exuParameters.MduCnt <= exuParameters.AluCnt && exuParameters.MduCnt > 0) 74 require(exuParameters.FmiscCnt <= exuParameters.FmacCnt && exuParameters.FmiscCnt > 0) 75 require(exuParameters.LduCnt == 2 && exuParameters.StuCnt == 2) 76 // one RS every 2 MDUs 77 val schedulePorts = Seq( 78 // exuCfg, numDeq, intFastWakeupTarget, fpFastWakeupTarget 79 (AluExeUnitCfg, exuParameters.AluCnt, Seq(0, 1, 2, 5, 6, 7, 8), Seq()), 80 (MulDivExeUnitCfg, exuParameters.MduCnt, Seq(0, 1, 2, 5, 6, 7, 8), Seq()), 81 (JumpExeUnitCfg, 1, Seq(), Seq()), 82 (FmacExeUnitCfg, exuParameters.FmacCnt, Seq(), Seq(3, 4)), 83 (FmiscExeUnitCfg, exuParameters.FmiscCnt, Seq(), Seq(3, 4)), 84 (LdExeUnitCfg, 1, Seq(0, 5, 6), Seq()), 85 (LdExeUnitCfg, 1, Seq(0, 5, 6), Seq()), 86 (StExeUnitCfg, 1, Seq(), Seq()), 87 (StExeUnitCfg, 1, Seq(), Seq()) 88 ) 89 // allow mdu and fmisc to have 2*numDeq enqueue ports 90 val intDpPorts = (0 until exuParameters.AluCnt).map(i => { 91 if (i < exuParameters.JmpCnt) Seq((0, i), (1, i), (2, i)) 92 else if (i < 2*exuParameters.MduCnt) Seq((0, i), (1, i)) 93 else Seq((0, i)) 94 }) 95 val fpDpPorts = (0 until exuParameters.FmacCnt).map(i => { 96 if (i < 2*exuParameters.FmiscCnt) Seq((3, i), (4, i)) 97 else Seq((4, i)) 98 }) 99 val lsDpPorts = Seq( 100 Seq((5, 0)), 101 Seq((6, 0)), 102 Seq((7, 0)), 103 Seq((8, 0)) 104 ) 105 val dispatchPorts = intDpPorts ++ fpDpPorts ++ lsDpPorts 106 107 val scheduler = LazyModule(new Scheduler(schedulePorts, dispatchPorts)) 108 109} 110 111class XSCore()(implicit p: config.Parameters) extends XSCoreBase 112 with HasXSDts 113{ 114 lazy val module = new XSCoreImp(this) 115} 116 117class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer) 118 with HasXSParameter 119 with HasSoCParameter 120 with HasExeBlockHelper { 121 val io = IO(new Bundle { 122 val hartId = Input(UInt(64.W)) 123 val externalInterrupt = new ExternalInterruptIO 124 val l2_pf_enable = Output(Bool()) 125 val l1plus_error, icache_error, dcache_error = Output(new L1CacheErrorInfo) 126 }) 127 128 println(s"FPGAPlatform:${env.FPGAPlatform} EnableDebug:${env.EnableDebug}") 129 AddressSpace.checkMemmap() 130 AddressSpace.printMemmap() 131 132 // to fast wake up fp, mem rs 133 val intBlockFastWakeUp = intExuConfigs.filter(_.hasCertainLatency) 134 val intBlockSlowWakeUp = intExuConfigs.filter(_.hasUncertainlatency) 135 136 val ctrlBlock = Module(new CtrlBlock) 137 138 val integerBlock = Module(new IntegerBlock) 139 val floatBlock = Module(new FloatBlock) 140 141 val frontend = outer.frontend.module 142 val memBlock = outer.memBlock.module 143 val l1pluscache = outer.l1pluscache.module 144 val ptw = outer.ptw.module 145 val scheduler = outer.scheduler.module 146 147 val allWriteback = integerBlock.io.writeback ++ floatBlock.io.writeback ++ memBlock.io.writeback 148 val intConfigs = exuConfigs.filter(_.writeIntRf) 149 val intArbiter = Module(new Wb(intConfigs, NRIntWritePorts, isFp = false)) 150 val intWriteback = allWriteback.zip(exuConfigs).filter(_._2.writeIntRf).map(_._1) 151 // set default value for ready 152 integerBlock.io.writeback.map(_.ready := true.B) 153 floatBlock.io.writeback.map(_.ready := true.B) 154 memBlock.io.writeback.map(_.ready := true.B) 155 intArbiter.io.in.zip(intWriteback).foreach { case (arb, wb) => 156 arb.valid := wb.valid && !wb.bits.uop.ctrl.fpWen 157 arb.bits := wb.bits 158 when (arb.valid) { 159 wb.ready := arb.ready 160 } 161 } 162 163 val fpArbiter = Module(new Wb(exuConfigs.filter(_.writeFpRf), NRFpWritePorts, isFp = true)) 164 val fpWriteback = allWriteback.zip(exuConfigs).filter(_._2.writeFpRf).map(_._1) 165 fpArbiter.io.in.zip(fpWriteback).foreach{ case (arb, wb) => 166 arb.valid := wb.valid && wb.bits.uop.ctrl.fpWen 167 arb.bits := wb.bits 168 when (arb.valid) { 169 wb.ready := arb.ready 170 } 171 } 172 173 io.l1plus_error <> l1pluscache.io.error 174 io.icache_error <> frontend.io.error 175 io.dcache_error <> memBlock.io.error 176 177 frontend.io.backend <> ctrlBlock.io.frontend 178 frontend.io.sfence <> integerBlock.io.fenceio.sfence 179 frontend.io.tlbCsr <> integerBlock.io.csrio.tlb 180 frontend.io.csrCtrl <> integerBlock.io.csrio.customCtrl 181 182 frontend.io.icacheMemAcq <> l1pluscache.io.req 183 l1pluscache.io.resp <> frontend.io.icacheMemGrant 184 l1pluscache.io.flush := frontend.io.l1plusFlush 185 frontend.io.fencei := integerBlock.io.fenceio.fencei 186 187 ctrlBlock.io.csrCtrl <> integerBlock.io.csrio.customCtrl 188 ctrlBlock.io.exuRedirect <> integerBlock.io.exuRedirect 189 ctrlBlock.io.stIn <> memBlock.io.stIn 190 ctrlBlock.io.stOut <> memBlock.io.stOut 191 ctrlBlock.io.memoryViolation <> memBlock.io.memoryViolation 192 ctrlBlock.io.enqLsq <> memBlock.io.enqLsq 193 // TODO 194 ctrlBlock.io.writeback <> VecInit(intArbiter.io.out ++ fpArbiter.io.out) 195 196 scheduler.io.redirect <> ctrlBlock.io.redirect 197 scheduler.io.flush <> ctrlBlock.io.flush 198 scheduler.io.allocate <> ctrlBlock.io.enqIQ 199 scheduler.io.issue <> integerBlock.io.issue ++ floatBlock.io.issue ++ memBlock.io.issue 200 // TODO arbiter 201 scheduler.io.writeback <> VecInit(intArbiter.io.out ++ fpArbiter.io.out) 202 203 scheduler.io.replay <> memBlock.io.replay 204 scheduler.io.rsIdx <> memBlock.io.rsIdx 205 scheduler.io.isFirstIssue <> memBlock.io.isFirstIssue 206 scheduler.io.stData <> memBlock.io.stData 207 scheduler.io.otherFastWakeup <> memBlock.io.otherFastWakeup 208 scheduler.io.jumpPc <> ctrlBlock.io.jumpPc 209 scheduler.io.jalr_target <> ctrlBlock.io.jalr_target 210 scheduler.io.stIssuePtr <> memBlock.io.stIssuePtr 211 scheduler.io.debug_fp_rat <> ctrlBlock.io.debug_fp_rat 212 scheduler.io.debug_int_rat <> ctrlBlock.io.debug_int_rat 213 scheduler.io.readIntRf <> ctrlBlock.io.readIntRf 214 scheduler.io.readFpRf <> ctrlBlock.io.readFpRf 215 216 integerBlock.io.redirect <> ctrlBlock.io.redirect 217 integerBlock.io.flush <> ctrlBlock.io.flush 218 integerBlock.io.csrio.hartId <> io.hartId 219 integerBlock.io.csrio.perf <> DontCare 220 integerBlock.io.csrio.perf.retiredInstr <> ctrlBlock.io.roqio.toCSR.perfinfo.retiredInstr 221 integerBlock.io.csrio.perf.bpuInfo <> ctrlBlock.io.perfInfo.bpuInfo 222 integerBlock.io.csrio.perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo 223 integerBlock.io.csrio.perf.memInfo <> memBlock.io.memInfo 224 integerBlock.io.csrio.perf.frontendInfo <> frontend.io.frontendInfo 225 226 integerBlock.io.csrio.fpu.fflags <> ctrlBlock.io.roqio.toCSR.fflags 227 integerBlock.io.csrio.fpu.isIllegal := false.B 228 integerBlock.io.csrio.fpu.dirty_fs <> ctrlBlock.io.roqio.toCSR.dirty_fs 229 integerBlock.io.csrio.fpu.frm <> floatBlock.io.frm 230 integerBlock.io.csrio.exception <> ctrlBlock.io.roqio.exception 231 integerBlock.io.csrio.isXRet <> ctrlBlock.io.roqio.toCSR.isXRet 232 integerBlock.io.csrio.trapTarget <> ctrlBlock.io.roqio.toCSR.trapTarget 233 integerBlock.io.csrio.interrupt <> ctrlBlock.io.roqio.toCSR.intrBitSet 234 integerBlock.io.csrio.memExceptionVAddr <> memBlock.io.lsqio.exceptionAddr.vaddr 235 integerBlock.io.csrio.externalInterrupt <> io.externalInterrupt 236 237 floatBlock.io.redirect <> ctrlBlock.io.redirect 238 floatBlock.io.flush <> ctrlBlock.io.flush 239 240 integerBlock.io.fenceio.sfence <> memBlock.io.sfence 241 integerBlock.io.fenceio.sbuffer <> memBlock.io.fenceToSbuffer 242 243 memBlock.io.redirect <> ctrlBlock.io.redirect 244 memBlock.io.flush <> ctrlBlock.io.flush 245 memBlock.io.csrCtrl <> integerBlock.io.csrio.customCtrl 246 memBlock.io.tlbCsr <> integerBlock.io.csrio.tlb 247 memBlock.io.lsqio.roq <> ctrlBlock.io.roqio.lsq 248 memBlock.io.lsqio.exceptionAddr.lsIdx.lqIdx := ctrlBlock.io.roqio.exception.bits.uop.lqIdx 249 memBlock.io.lsqio.exceptionAddr.lsIdx.sqIdx := ctrlBlock.io.roqio.exception.bits.uop.sqIdx 250 memBlock.io.lsqio.exceptionAddr.isStore := CommitType.lsInstIsStore(ctrlBlock.io.roqio.exception.bits.uop.ctrl.commitType) 251 252 val itlbRepeater = Module(new PTWRepeater()) 253 val dtlbRepeater = if (usePTWRepeater) { 254 Module(new PTWRepeater(LoadPipelineWidth + StorePipelineWidth)) 255 } else { 256 Module(new PTWFilter(LoadPipelineWidth + StorePipelineWidth, PtwMissQueueSize)) 257 } 258 itlbRepeater.io.tlb <> frontend.io.ptw 259 dtlbRepeater.io.tlb <> memBlock.io.ptw 260 itlbRepeater.io.sfence <> integerBlock.io.fenceio.sfence 261 dtlbRepeater.io.sfence <> integerBlock.io.fenceio.sfence 262 ptw.io.tlb(0) <> itlbRepeater.io.ptw 263 ptw.io.tlb(1) <> dtlbRepeater.io.ptw 264 ptw.io.sfence <> integerBlock.io.fenceio.sfence 265 ptw.io.csr <> integerBlock.io.csrio.tlb 266 267 // if l2 prefetcher use stream prefetch, it should be placed in XSCore 268 assert(l2PrefetcherParameters._type == "bop") 269 io.l2_pf_enable := integerBlock.io.csrio.customCtrl.l2_pf_enable 270 271 val l1plus_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform)) 272 l1pluscache.reset := l1plus_reset_gen.io.out 273 274 val ptw_reset_gen = Module(new ResetGen(2, !debugOpts.FPGAPlatform)) 275 ptw.reset := ptw_reset_gen.io.out 276 itlbRepeater.reset := ptw_reset_gen.io.out 277 dtlbRepeater.reset := ptw_reset_gen.io.out 278 279 val memBlock_reset_gen = Module(new ResetGen(3, !debugOpts.FPGAPlatform)) 280 memBlock.reset := memBlock_reset_gen.io.out 281 282 val intBlock_reset_gen = Module(new ResetGen(4, !debugOpts.FPGAPlatform)) 283 integerBlock.reset := intBlock_reset_gen.io.out 284 285 val fpBlock_reset_gen = Module(new ResetGen(5, !debugOpts.FPGAPlatform)) 286 floatBlock.reset := fpBlock_reset_gen.io.out 287 288 val ctrlBlock_reset_gen = Module(new ResetGen(6, !debugOpts.FPGAPlatform)) 289 ctrlBlock.reset := ctrlBlock_reset_gen.io.out 290 291 val frontend_reset_gen = Module(new ResetGen(7, !debugOpts.FPGAPlatform)) 292 frontend.reset := frontend_reset_gen.io.out 293} 294