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.mem._ 25import xiangshan.cache.{DCacheParameters, L1plusCacheWrapper, L1plusCacheParameters, PTWWrapper, PTWRepeater, PTWFilter} 26import xiangshan.cache.prefetch._ 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.ctrlInfo <> ctrlBlock.io.perfInfo.ctrlInfo 224 integerBlock.io.csrio.perf.memInfo <> memBlock.io.memInfo 225 integerBlock.io.csrio.perf.frontendInfo <> frontend.io.frontendInfo 226 227 integerBlock.io.csrio.fpu.fflags <> ctrlBlock.io.roqio.toCSR.fflags 228 integerBlock.io.csrio.fpu.isIllegal := false.B 229 integerBlock.io.csrio.fpu.dirty_fs <> ctrlBlock.io.roqio.toCSR.dirty_fs 230 integerBlock.io.csrio.fpu.frm <> floatBlock.io.frm 231 integerBlock.io.csrio.exception <> ctrlBlock.io.roqio.exception 232 integerBlock.io.csrio.isXRet <> ctrlBlock.io.roqio.toCSR.isXRet 233 integerBlock.io.csrio.trapTarget <> ctrlBlock.io.roqio.toCSR.trapTarget 234 integerBlock.io.csrio.interrupt <> ctrlBlock.io.roqio.toCSR.intrBitSet 235 integerBlock.io.csrio.memExceptionVAddr <> memBlock.io.lsqio.exceptionAddr.vaddr 236 integerBlock.io.csrio.externalInterrupt <> io.externalInterrupt 237 238 floatBlock.io.redirect <> ctrlBlock.io.redirect 239 floatBlock.io.flush <> ctrlBlock.io.flush 240 241 integerBlock.io.fenceio.sfence <> memBlock.io.sfence 242 integerBlock.io.fenceio.sbuffer <> memBlock.io.fenceToSbuffer 243 244 memBlock.io.redirect <> ctrlBlock.io.redirect 245 memBlock.io.flush <> ctrlBlock.io.flush 246 memBlock.io.csrCtrl <> integerBlock.io.csrio.customCtrl 247 memBlock.io.tlbCsr <> integerBlock.io.csrio.tlb 248 memBlock.io.lsqio.roq <> ctrlBlock.io.roqio.lsq 249 memBlock.io.lsqio.exceptionAddr.lsIdx.lqIdx := ctrlBlock.io.roqio.exception.bits.uop.lqIdx 250 memBlock.io.lsqio.exceptionAddr.lsIdx.sqIdx := ctrlBlock.io.roqio.exception.bits.uop.sqIdx 251 memBlock.io.lsqio.exceptionAddr.isStore := CommitType.lsInstIsStore(ctrlBlock.io.roqio.exception.bits.uop.ctrl.commitType) 252 253 val itlbRepeater = Module(new PTWRepeater(2)) 254 val dtlbRepeater = if (usePTWRepeater) { 255 Module(new PTWRepeater(LoadPipelineWidth + StorePipelineWidth)) 256 } else { 257 Module(new PTWFilter(LoadPipelineWidth + StorePipelineWidth, PtwMissQueueSize)) 258 } 259 itlbRepeater.io.tlb <> frontend.io.ptw 260 dtlbRepeater.io.tlb <> memBlock.io.ptw 261 itlbRepeater.io.sfence <> integerBlock.io.fenceio.sfence 262 dtlbRepeater.io.sfence <> integerBlock.io.fenceio.sfence 263 ptw.io.tlb(0) <> itlbRepeater.io.ptw 264 ptw.io.tlb(1) <> dtlbRepeater.io.ptw 265 ptw.io.sfence <> integerBlock.io.fenceio.sfence 266 ptw.io.csr <> integerBlock.io.csrio.tlb 267 268 // if l2 prefetcher use stream prefetch, it should be placed in XSCore 269 assert(l2PrefetcherParameters._type == "bop") 270 io.l2_pf_enable := integerBlock.io.csrio.customCtrl.l2_pf_enable 271 272 val l1plus_reset_gen = Module(new ResetGen(1, !debugOpts.FPGAPlatform)) 273 l1pluscache.reset := l1plus_reset_gen.io.out 274 275 val ptw_reset_gen = Module(new ResetGen(2, !debugOpts.FPGAPlatform)) 276 ptw.reset := ptw_reset_gen.io.out 277 itlbRepeater.reset := ptw_reset_gen.io.out 278 dtlbRepeater.reset := ptw_reset_gen.io.out 279 280 val memBlock_reset_gen = Module(new ResetGen(3, !debugOpts.FPGAPlatform)) 281 memBlock.reset := memBlock_reset_gen.io.out 282 283 val intBlock_reset_gen = Module(new ResetGen(4, !debugOpts.FPGAPlatform)) 284 integerBlock.reset := intBlock_reset_gen.io.out 285 286 val fpBlock_reset_gen = Module(new ResetGen(5, !debugOpts.FPGAPlatform)) 287 floatBlock.reset := fpBlock_reset_gen.io.out 288 289 val ctrlBlock_reset_gen = Module(new ResetGen(6, !debugOpts.FPGAPlatform)) 290 ctrlBlock.reset := ctrlBlock_reset_gen.io.out 291 292 val frontend_reset_gen = Module(new ResetGen(7, !debugOpts.FPGAPlatform)) 293 frontend.reset := frontend_reset_gen.io.out 294} 295