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, SoCParamsKey} 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 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(AluExeUnitCfg, MulDivExeUnitCfg, JumpExeUnitCfg, LdExeUnitCfg, StExeUnitCfg), Seq()), 82 (MulDivExeUnitCfg, exuParameters.MduCnt, Seq(AluExeUnitCfg, MulDivExeUnitCfg, JumpExeUnitCfg, LdExeUnitCfg, StExeUnitCfg), Seq()), 83 (JumpExeUnitCfg, 1, Seq(), Seq()), 84 (FmacExeUnitCfg, exuParameters.FmacCnt, Seq(), Seq(FmacExeUnitCfg, FmiscExeUnitCfg)), 85 (FmiscExeUnitCfg, exuParameters.FmiscCnt, Seq(), Seq(FmacExeUnitCfg, FmiscExeUnitCfg)), 86 (LdExeUnitCfg, exuParameters.LduCnt, Seq(AluExeUnitCfg, LdExeUnitCfg), Seq()), 87 (StExeUnitCfg, exuParameters.StuCnt, 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((5, 1)), 102 Seq((6, 0)), 103 Seq((6, 1)) 104 ) 105 val dispatchPorts = intDpPorts ++ fpDpPorts ++ lsDpPorts 106 107 val mappedSchedulePorts = schedulePorts.map(port => { 108 val intWakeup = port._3.flatMap(cfg => schedulePorts.zipWithIndex.filter(_._1._1 == cfg).map(_._2)) 109 val fpWakeup = port._4.flatMap(cfg => schedulePorts.zipWithIndex.filter(_._1._1 == cfg).map(_._2)) 110 (port._1, port._2, intWakeup, fpWakeup) 111 }) 112 113 val scheduler = LazyModule(new Scheduler(mappedSchedulePorts, dispatchPorts)) 114 115 val memBlock = LazyModule(new MemBlock()(p.alter((site, here, up) => { 116 case XSCoreParamsKey => up(XSCoreParamsKey).copy( 117 IssQueSize = scheduler.memRsEntries.max 118 ) 119 }))) 120} 121 122class XSCore()(implicit p: config.Parameters) extends XSCoreBase 123 with HasXSDts 124{ 125 lazy val module = new XSCoreImp(this) 126} 127 128class XSCoreImp(outer: XSCoreBase) extends LazyModuleImp(outer) 129 with HasXSParameter 130 with HasSoCParameter 131 with HasExeBlockHelper { 132 val io = IO(new Bundle { 133 val hartId = Input(UInt(64.W)) 134 val externalInterrupt = new ExternalInterruptIO 135 val l2_pf_enable = Output(Bool()) 136 val l1plus_error, icache_error, dcache_error = Output(new L1CacheErrorInfo) 137 }) 138 139 println(s"FPGAPlatform:${env.FPGAPlatform} EnableDebug:${env.EnableDebug}") 140 AddressSpace.checkMemmap() 141 AddressSpace.printMemmap() 142 143 // to fast wake up fp, mem rs 144 val intBlockFastWakeUp = intExuConfigs.filter(_.hasCertainLatency) 145 val intBlockSlowWakeUp = intExuConfigs.filter(_.hasUncertainlatency) 146 147 val ctrlBlock = Module(new CtrlBlock) 148 149 val integerBlock = Module(new IntegerBlock) 150 val floatBlock = Module(new FloatBlock) 151 152 val frontend = outer.frontend.module 153 val memBlock = outer.memBlock.module 154 val l1pluscache = outer.l1pluscache.module 155 val ptw = outer.ptw.module 156 val scheduler = outer.scheduler.module 157 158 val allWriteback = integerBlock.io.writeback ++ floatBlock.io.writeback ++ memBlock.io.writeback 159 val intConfigs = exuConfigs.filter(_.writeIntRf) 160 val intArbiter = Module(new Wb(intConfigs, NRIntWritePorts, isFp = false)) 161 val intWriteback = allWriteback.zip(exuConfigs).filter(_._2.writeIntRf).map(_._1) 162 // set default value for ready 163 integerBlock.io.writeback.map(_.ready := true.B) 164 floatBlock.io.writeback.map(_.ready := true.B) 165 memBlock.io.writeback.map(_.ready := true.B) 166 intArbiter.io.in.zip(intWriteback).foreach { case (arb, wb) => 167 arb.valid := wb.valid && !wb.bits.uop.ctrl.fpWen 168 arb.bits := wb.bits 169 when (arb.valid) { 170 wb.ready := arb.ready 171 } 172 } 173 174 val fpArbiter = Module(new Wb(exuConfigs.filter(_.writeFpRf), NRFpWritePorts, isFp = true)) 175 val fpWriteback = allWriteback.zip(exuConfigs).filter(_._2.writeFpRf).map(_._1) 176 fpArbiter.io.in.zip(fpWriteback).foreach{ case (arb, wb) => 177 arb.valid := wb.valid && wb.bits.uop.ctrl.fpWen 178 arb.bits := wb.bits 179 when (arb.valid) { 180 wb.ready := arb.ready 181 } 182 } 183 184 io.l1plus_error <> l1pluscache.io.error 185 io.icache_error <> frontend.io.error 186 io.dcache_error <> memBlock.io.error 187 188 frontend.io.backend <> ctrlBlock.io.frontend 189 frontend.io.sfence <> integerBlock.io.fenceio.sfence 190 frontend.io.tlbCsr <> integerBlock.io.csrio.tlb 191 frontend.io.csrCtrl <> integerBlock.io.csrio.customCtrl 192 193 frontend.io.icacheMemAcq <> l1pluscache.io.req 194 l1pluscache.io.resp <> frontend.io.icacheMemGrant 195 l1pluscache.io.flush := frontend.io.l1plusFlush 196 frontend.io.fencei := integerBlock.io.fenceio.fencei 197 198 ctrlBlock.io.csrCtrl <> integerBlock.io.csrio.customCtrl 199 ctrlBlock.io.exuRedirect <> integerBlock.io.exuRedirect 200 ctrlBlock.io.stIn <> memBlock.io.stIn 201 ctrlBlock.io.stOut <> memBlock.io.stOut 202 ctrlBlock.io.memoryViolation <> memBlock.io.memoryViolation 203 ctrlBlock.io.enqLsq <> memBlock.io.enqLsq 204 ctrlBlock.io.writeback <> VecInit(intArbiter.io.out ++ fpArbiter.io.out) 205 206 scheduler.io.redirect <> ctrlBlock.io.redirect 207 scheduler.io.flush <> ctrlBlock.io.flush 208 scheduler.io.allocate <> ctrlBlock.io.enqIQ 209 scheduler.io.issue <> integerBlock.io.issue ++ floatBlock.io.issue ++ memBlock.io.issue 210 scheduler.io.writeback <> VecInit(intArbiter.io.out ++ fpArbiter.io.out) 211 212 scheduler.io.replay <> memBlock.io.replay 213 scheduler.io.rsIdx <> memBlock.io.rsIdx 214 println(s"${scheduler.io.rsIdx(0).getWidth}, ${memBlock.io.rsIdx(0).getWidth}") 215 require(scheduler.io.rsIdx(0).getWidth == memBlock.io.rsIdx(0).getWidth) 216 scheduler.io.isFirstIssue <> memBlock.io.isFirstIssue 217 scheduler.io.stData <> memBlock.io.stData 218 scheduler.io.otherFastWakeup <> memBlock.io.otherFastWakeup 219 scheduler.io.jumpPc <> ctrlBlock.io.jumpPc 220 scheduler.io.jalr_target <> ctrlBlock.io.jalr_target 221 scheduler.io.stIssuePtr <> memBlock.io.stIssuePtr 222 scheduler.io.debug_fp_rat <> ctrlBlock.io.debug_fp_rat 223 scheduler.io.debug_int_rat <> ctrlBlock.io.debug_int_rat 224 scheduler.io.readIntRf <> ctrlBlock.io.readIntRf 225 scheduler.io.readFpRf <> ctrlBlock.io.readFpRf 226 227 integerBlock.io.redirect <> ctrlBlock.io.redirect 228 integerBlock.io.flush <> ctrlBlock.io.flush 229 integerBlock.io.csrio.hartId <> io.hartId 230 integerBlock.io.csrio.perf <> DontCare 231 integerBlock.io.csrio.perf.retiredInstr <> ctrlBlock.io.roqio.toCSR.perfinfo.retiredInstr 232 integerBlock.io.csrio.perf.bpuInfo <> ctrlBlock.io.perfInfo.bpuInfo 233 integerBlock.io.csrio.perf.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo 234 integerBlock.io.csrio.perf.memInfo <> memBlock.io.memInfo 235 integerBlock.io.csrio.perf.frontendInfo <> frontend.io.frontendInfo 236 237 integerBlock.io.csrio.fpu.fflags <> ctrlBlock.io.roqio.toCSR.fflags 238 integerBlock.io.csrio.fpu.isIllegal := false.B 239 integerBlock.io.csrio.fpu.dirty_fs <> ctrlBlock.io.roqio.toCSR.dirty_fs 240 integerBlock.io.csrio.fpu.frm <> floatBlock.io.frm 241 integerBlock.io.csrio.exception <> ctrlBlock.io.roqio.exception 242 integerBlock.io.csrio.isXRet <> ctrlBlock.io.roqio.toCSR.isXRet 243 integerBlock.io.csrio.trapTarget <> ctrlBlock.io.roqio.toCSR.trapTarget 244 integerBlock.io.csrio.interrupt <> ctrlBlock.io.roqio.toCSR.intrBitSet 245 integerBlock.io.csrio.memExceptionVAddr <> memBlock.io.lsqio.exceptionAddr.vaddr 246 integerBlock.io.csrio.externalInterrupt <> io.externalInterrupt 247 248 floatBlock.io.redirect <> ctrlBlock.io.redirect 249 floatBlock.io.flush <> ctrlBlock.io.flush 250 251 integerBlock.io.fenceio.sfence <> memBlock.io.sfence 252 integerBlock.io.fenceio.sbuffer <> memBlock.io.fenceToSbuffer 253 254 memBlock.io.redirect <> ctrlBlock.io.redirect 255 memBlock.io.flush <> ctrlBlock.io.flush 256 memBlock.io.csrCtrl <> integerBlock.io.csrio.customCtrl 257 memBlock.io.tlbCsr <> integerBlock.io.csrio.tlb 258 memBlock.io.lsqio.roq <> ctrlBlock.io.roqio.lsq 259 memBlock.io.lsqio.exceptionAddr.lsIdx.lqIdx := ctrlBlock.io.roqio.exception.bits.uop.lqIdx 260 memBlock.io.lsqio.exceptionAddr.lsIdx.sqIdx := ctrlBlock.io.roqio.exception.bits.uop.sqIdx 261 memBlock.io.lsqio.exceptionAddr.isStore := CommitType.lsInstIsStore(ctrlBlock.io.roqio.exception.bits.uop.ctrl.commitType) 262 263 val itlbRepeater = Module(new PTWRepeater()) 264 val dtlbRepeater = if (usePTWRepeater) { 265 Module(new PTWRepeater(LoadPipelineWidth + StorePipelineWidth)) 266 } else { 267 Module(new PTWFilter(LoadPipelineWidth + StorePipelineWidth, PtwMissQueueSize)) 268 } 269 itlbRepeater.io.tlb <> frontend.io.ptw 270 dtlbRepeater.io.tlb <> memBlock.io.ptw 271 itlbRepeater.io.sfence <> integerBlock.io.fenceio.sfence 272 dtlbRepeater.io.sfence <> integerBlock.io.fenceio.sfence 273 ptw.io.tlb(0) <> itlbRepeater.io.ptw 274 ptw.io.tlb(1) <> dtlbRepeater.io.ptw 275 ptw.io.sfence <> integerBlock.io.fenceio.sfence 276 ptw.io.csr <> integerBlock.io.csrio.tlb 277 278 // if l2 prefetcher use stream prefetch, it should be placed in XSCore 279 assert(l2PrefetcherParameters._type == "bop") 280 io.l2_pf_enable := integerBlock.io.csrio.customCtrl.l2_pf_enable 281 282 val l1plus_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform)) 283 l1pluscache.reset := l1plus_reset_gen.io.out 284 285 val ptw_reset_gen = Module(new ResetGen(2, !debugOpts.FPGAPlatform)) 286 ptw.reset := ptw_reset_gen.io.out 287 itlbRepeater.reset := ptw_reset_gen.io.out 288 dtlbRepeater.reset := ptw_reset_gen.io.out 289 290 val memBlock_reset_gen = Module(new ResetGen(3, !debugOpts.FPGAPlatform)) 291 memBlock.reset := memBlock_reset_gen.io.out 292 293 val intBlock_reset_gen = Module(new ResetGen(4, !debugOpts.FPGAPlatform)) 294 integerBlock.reset := intBlock_reset_gen.io.out 295 296 val fpBlock_reset_gen = Module(new ResetGen(5, !debugOpts.FPGAPlatform)) 297 floatBlock.reset := fpBlock_reset_gen.io.out 298 299 val ctrlBlock_reset_gen = Module(new ResetGen(6, !debugOpts.FPGAPlatform)) 300 ctrlBlock.reset := ctrlBlock_reset_gen.io.out 301 302 val frontend_reset_gen = Module(new ResetGen(7, !debugOpts.FPGAPlatform)) 303 frontend.reset := frontend_reset_gen.io.out 304} 305