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