11d8f4dcbSJay/*************************************************************************************** 21d8f4dcbSJay* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 31d8f4dcbSJay* Copyright (c) 2020-2021 Peng Cheng Laboratory 41d8f4dcbSJay* 51d8f4dcbSJay* XiangShan is licensed under Mulan PSL v2. 61d8f4dcbSJay* You can use this software according to the terms and conditions of the Mulan PSL v2. 71d8f4dcbSJay* You may obtain a copy of Mulan PSL v2 at: 81d8f4dcbSJay* http://license.coscl.org.cn/MulanPSL2 91d8f4dcbSJay* 101d8f4dcbSJay* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 111d8f4dcbSJay* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 121d8f4dcbSJay* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 131d8f4dcbSJay* 141d8f4dcbSJay* See the Mulan PSL v2 for more details. 151d8f4dcbSJay***************************************************************************************/ 161d8f4dcbSJay 171d8f4dcbSJaypackage xiangshan.frontend.icache 181d8f4dcbSJay 198891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 201d8f4dcbSJayimport chisel3._ 211d8f4dcbSJayimport chisel3.util._ 227d45a146SYinan Xuimport difftest._ 231d8f4dcbSJayimport freechips.rocketchip.tilelink.ClientStates 241d8f4dcbSJayimport xiangshan._ 251d8f4dcbSJayimport xiangshan.cache.mmu._ 261d8f4dcbSJayimport utils._ 273c02ee8fSwakafaimport utility._ 281d8f4dcbSJayimport xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} 29f22cf846SJeniusimport xiangshan.frontend.{FtqICacheInfo, FtqToICacheRequestBundle} 301d8f4dcbSJay 311d8f4dcbSJayclass ICacheMainPipeReq(implicit p: Parameters) extends ICacheBundle 321d8f4dcbSJay{ 331d8f4dcbSJay val vaddr = UInt(VAddrBits.W) 341d8f4dcbSJay def vsetIdx = get_idx(vaddr) 351d8f4dcbSJay} 361d8f4dcbSJay 371d8f4dcbSJayclass ICacheMainPipeResp(implicit p: Parameters) extends ICacheBundle 381d8f4dcbSJay{ 391d8f4dcbSJay val vaddr = UInt(VAddrBits.W) 40a61a35e0Sssszwic // val registerData = UInt(blockBits.W) 41a61a35e0Sssszwic // val sramData = UInt(blockBits.W) 42a61a35e0Sssszwic // val select = Bool() 43a61a35e0Sssszwic val data = UInt((blockBits/2).W) 441d8f4dcbSJay val paddr = UInt(PAddrBits.W) 45d0de7e4aSpeixiaokun val gpaddr = UInt(GPAddrBits.W) 461d8f4dcbSJay val tlbExcp = new Bundle{ 471d8f4dcbSJay val pageFault = Bool() 48d0de7e4aSpeixiaokun val guestPageFault = Bool() 491d8f4dcbSJay val accessFault = Bool() 501d8f4dcbSJay val mmio = Bool() 511d8f4dcbSJay } 521d8f4dcbSJay} 531d8f4dcbSJay 541d8f4dcbSJayclass ICacheMainPipeBundle(implicit p: Parameters) extends ICacheBundle 551d8f4dcbSJay{ 56c5c5edaeSJenius val req = Flipped(Decoupled(new FtqToICacheRequestBundle)) 57c5c5edaeSJenius val resp = Vec(PortNumber, ValidIO(new ICacheMainPipeResp)) 58d2b20d1aSTang Haojin val topdownIcacheMiss = Output(Bool()) 59d2b20d1aSTang Haojin val topdownItlbMiss = Output(Bool()) 601d8f4dcbSJay} 611d8f4dcbSJay 621d8f4dcbSJayclass ICacheMetaReqBundle(implicit p: Parameters) extends ICacheBundle{ 63afed18b5SJenius val toIMeta = DecoupledIO(new ICacheReadBundle) 641d8f4dcbSJay val fromIMeta = Input(new ICacheMetaRespBundle) 651d8f4dcbSJay} 661d8f4dcbSJay 671d8f4dcbSJayclass ICacheDataReqBundle(implicit p: Parameters) extends ICacheBundle{ 682da4ac8cSJenius val toIData = DecoupledIO(Vec(partWayNum, new ICacheReadBundle)) 691d8f4dcbSJay val fromIData = Input(new ICacheDataRespBundle) 701d8f4dcbSJay} 711d8f4dcbSJay 721d8f4dcbSJayclass ICacheMSHRBundle(implicit p: Parameters) extends ICacheBundle{ 731d8f4dcbSJay val toMSHR = Decoupled(new ICacheMissReq) 741d8f4dcbSJay val fromMSHR = Flipped(ValidIO(new ICacheMissResp)) 751d8f4dcbSJay} 761d8f4dcbSJay 771d8f4dcbSJayclass ICachePMPBundle(implicit p: Parameters) extends ICacheBundle{ 781d8f4dcbSJay val req = Valid(new PMPReqBundle()) 791d8f4dcbSJay val resp = Input(new PMPRespBundle()) 801d8f4dcbSJay} 811d8f4dcbSJay 821d8f4dcbSJayclass ICachePerfInfo(implicit p: Parameters) extends ICacheBundle{ 831d8f4dcbSJay val only_0_hit = Bool() 841d8f4dcbSJay val only_0_miss = Bool() 851d8f4dcbSJay val hit_0_hit_1 = Bool() 861d8f4dcbSJay val hit_0_miss_1 = Bool() 871d8f4dcbSJay val miss_0_hit_1 = Bool() 881d8f4dcbSJay val miss_0_miss_1 = Bool() 89a108d429SJay val hit_0_except_1 = Bool() 90a108d429SJay val miss_0_except_1 = Bool() 91a108d429SJay val except_0 = Bool() 921d8f4dcbSJay val bank_hit = Vec(2,Bool()) 931d8f4dcbSJay val hit = Bool() 941d8f4dcbSJay} 951d8f4dcbSJay 961d8f4dcbSJayclass ICacheMainPipeInterface(implicit p: Parameters) extends ICacheBundle { 97f57f7f2aSYangyu Chen val hartId = Input(UInt(hartIdLen.W)) 982a3050c2SJay /*** internal interface ***/ 991d8f4dcbSJay val metaArray = new ICacheMetaReqBundle 1001d8f4dcbSJay val dataArray = new ICacheDataReqBundle 101b1ded4e8Sguohongyu /** prefetch io */ 102cb6e5d3cSssszwic val IPFBufferRead = Flipped(new IPFBufferRead) 103cb6e5d3cSssszwic val PIQRead = Flipped(new PIQRead) 104cb6e5d3cSssszwic 105cb6e5d3cSssszwic val IPFReplacer = Flipped(new IPFReplacer) 10658c354d0Sssszwic val ICacheMainPipeInfo = new ICacheMainPipeInfo 107b1ded4e8Sguohongyu 1081d8f4dcbSJay val mshr = Vec(PortNumber, new ICacheMSHRBundle) 10958dbdfc2SJay val errors = Output(Vec(PortNumber, new L1CacheErrorInfo)) 1102a3050c2SJay /*** outside interface ***/ 111c5c5edaeSJenius //val fetch = Vec(PortNumber, new ICacheMainPipeBundle) 112c5c5edaeSJenius /* when ftq.valid is high in T + 1 cycle 113c5c5edaeSJenius * the ftq component must be valid in T cycle 114c5c5edaeSJenius */ 115c5c5edaeSJenius val fetch = new ICacheMainPipeBundle 1161d8f4dcbSJay val pmp = Vec(PortNumber, new ICachePMPBundle) 117f1fe8698SLemover val itlb = Vec(PortNumber, new TlbRequestIO) 1181d8f4dcbSJay val respStall = Input(Bool()) 1191d8f4dcbSJay val perfInfo = Output(new ICachePerfInfo) 12058dbdfc2SJay 121ecccf78fSJay val csr_parity_enable = Input(Bool()) 1221d8f4dcbSJay} 1231d8f4dcbSJay 124f9c51548Sssszwicclass ICacheDB(implicit p: Parameters) extends ICacheBundle { 125f9c51548Sssszwic val blk_vaddr = UInt((VAddrBits - blockOffBits).W) 126f9c51548Sssszwic val blk_paddr = UInt((PAddrBits - blockOffBits).W) 127f9c51548Sssszwic val hit = Bool() 128f9c51548Sssszwic} 129f9c51548Sssszwic 1301d8f4dcbSJayclass ICacheMainPipe(implicit p: Parameters) extends ICacheModule 1311d8f4dcbSJay{ 1321d8f4dcbSJay val io = IO(new ICacheMainPipeInterface) 1331d8f4dcbSJay 13458dbdfc2SJay /** Input/Output port */ 135c5c5edaeSJenius val (fromFtq, toIFU) = (io.fetch.req, io.fetch.resp) 1362a3050c2SJay val (toMeta, metaResp) = (io.metaArray.toIMeta, io.metaArray.fromIMeta) 1372a3050c2SJay val (toData, dataResp) = (io.dataArray.toIData, io.dataArray.fromIData) 138cb6e5d3cSssszwic val (toIPF, fromIPF) = (io.IPFBufferRead.req, io.IPFBufferRead.resp) 139cb6e5d3cSssszwic val (toPIQ, fromPIQ) = (io.PIQRead.req, io.PIQRead.resp) 1401d8f4dcbSJay val (toMSHR, fromMSHR) = (io.mshr.map(_.toMSHR), io.mshr.map(_.fromMSHR)) 1411d8f4dcbSJay val (toITLB, fromITLB) = (io.itlb.map(_.req), io.itlb.map(_.resp)) 1421d8f4dcbSJay val (toPMP, fromPMP) = (io.pmp.map(_.req), io.pmp.map(_.resp)) 143cb6e5d3cSssszwic 144cb6e5d3cSssszwic val IPFReplacer = io.IPFReplacer 14558c354d0Sssszwic val toIPrefetch = io.ICacheMainPipeInfo 14658c354d0Sssszwic 14758c354d0Sssszwic 14858c354d0Sssszwic // Statistics on the frequency distribution of FTQ fire interval 14958c354d0Sssszwic val cntFtqFireInterval = RegInit(0.U(32.W)) 15058c354d0Sssszwic cntFtqFireInterval := Mux(fromFtq.fire, 1.U, cntFtqFireInterval + 1.U) 15158c354d0Sssszwic XSPerfHistogram("ftq2icache_fire_" + p(XSCoreParamsKey).HartId.toString, 15258c354d0Sssszwic cntFtqFireInterval, fromFtq.fire, 15358c354d0Sssszwic 1, 300, 1, right_strict = true) 154b1ded4e8Sguohongyu 155c5c5edaeSJenius // Ftq RegNext Register 156b004fa13SJenius val fromFtqReq = fromFtq.bits.pcMemRead 157c5c5edaeSJenius 15858dbdfc2SJay /** pipeline control signal */ 159f1fe8698SLemover val s1_ready, s2_ready = Wire(Bool()) 160f1fe8698SLemover val s0_fire, s1_fire , s2_fire = Wire(Bool()) 1611d8f4dcbSJay 1622a3050c2SJay /** 1632a3050c2SJay ****************************************************************************** 16458dbdfc2SJay * ICache Stage 0 16558dbdfc2SJay * - send req to ITLB and wait for tlb miss fixing 16658dbdfc2SJay * - send req to Meta/Data SRAM 1672a3050c2SJay ****************************************************************************** 1682a3050c2SJay */ 1692a3050c2SJay 17058dbdfc2SJay /** s0 control */ 171c5c5edaeSJenius val s0_valid = fromFtq.valid 172f56177cbSJenius val s0_req_vaddr = (0 until partWayNum + 1).map(i => VecInit(Seq(fromFtqReq(i).startAddr, fromFtqReq(i).nextlineStart))) 173f56177cbSJenius val s0_req_vsetIdx = (0 until partWayNum + 1).map(i => VecInit(s0_req_vaddr(i).map(get_idx(_)))) 174dc270d3bSJenius val s0_only_first = (0 until partWayNum + 1).map(i => fromFtq.bits.readValid(i) && !fromFtqReq(i).crossCacheline) 175dc270d3bSJenius val s0_double_line = (0 until partWayNum + 1).map(i => fromFtq.bits.readValid(i) && fromFtqReq(i).crossCacheline) 1761d8f4dcbSJay 177f1fe8698SLemover val s0_final_valid = s0_valid 178fd0ecf27SLingrui98 val s0_final_vaddr = s0_req_vaddr.head 179fd0ecf27SLingrui98 val s0_final_vsetIdx = s0_req_vsetIdx.head 180fd0ecf27SLingrui98 val s0_final_only_first = s0_only_first.head 181fd0ecf27SLingrui98 val s0_final_double_line = s0_double_line.head 18261e1db30SJay 18358dbdfc2SJay /** SRAM request */ 184a61a35e0Sssszwic // 0,1,2,3 -> dataArray(data); 3 -> dataArray(code); 0 -> metaArray; 4 -> itlb 185f56177cbSJenius val ftq_req_to_data_doubleline = s0_double_line.init 186f56177cbSJenius val ftq_req_to_data_vset_idx = s0_req_vsetIdx.init 187dc270d3bSJenius val ftq_req_to_data_valid = fromFtq.bits.readValid.init 188f56177cbSJenius 189f56177cbSJenius val ftq_req_to_meta_doubleline = s0_double_line.head 190f56177cbSJenius val ftq_req_to_meta_vset_idx = s0_req_vsetIdx.head 191a61a35e0Sssszwic val ftq_req_to_meta_valid = fromFtq.bits.readValid.head 192f56177cbSJenius 193f56177cbSJenius val ftq_req_to_itlb_only_first = s0_only_first.last 194f56177cbSJenius val ftq_req_to_itlb_doubleline = s0_double_line.last 195f56177cbSJenius val ftq_req_to_itlb_vaddr = s0_req_vaddr.last 196f56177cbSJenius val ftq_req_to_itlb_vset_idx = s0_req_vsetIdx.last 197f56177cbSJenius 198cb6e5d3cSssszwic /** Data request */ 199fd0ecf27SLingrui98 for(i <- 0 until partWayNum) { 200a61a35e0Sssszwic toData.valid := ftq_req_to_data_valid(i) 201f56177cbSJenius toData.bits(i).isDoubleLine := ftq_req_to_data_doubleline(i) 202f56177cbSJenius toData.bits(i).vSetIdx := ftq_req_to_data_vset_idx(i) 2031d8f4dcbSJay } 204afed18b5SJenius 205cb6e5d3cSssszwic /** Meta request */ 206a61a35e0Sssszwic toMeta.valid := ftq_req_to_meta_valid 207f56177cbSJenius toMeta.bits.isDoubleLine := ftq_req_to_meta_doubleline 208f56177cbSJenius toMeta.bits.vSetIdx := ftq_req_to_meta_vset_idx 209afed18b5SJenius 210cb6e5d3cSssszwic val toITLB_s0_valid = VecInit(Seq(s0_valid, s0_valid && ftq_req_to_itlb_doubleline)) 211cb6e5d3cSssszwic val toITLB_s0_size = VecInit(Seq(3.U, 3.U)) // TODO: fix the size 212cb6e5d3cSssszwic val toITLB_s0_vaddr = ftq_req_to_itlb_vaddr 213cb6e5d3cSssszwic val toITLB_s0_debug_pc = ftq_req_to_itlb_vaddr 2142a3050c2SJay 215f1fe8698SLemover val itlb_can_go = toITLB(0).ready && toITLB(1).ready 216afed18b5SJenius val icache_can_go = toData.ready && toMeta.ready 217a61a35e0Sssszwic val pipe_can_go = s1_ready 218f1fe8698SLemover val s0_can_go = itlb_can_go && icache_can_go && pipe_can_go 219cb6e5d3cSssszwic s0_fire := s0_valid && s0_can_go 2207052722fSJay 2217052722fSJay //TODO: fix GTimer() condition 222c5c5edaeSJenius fromFtq.ready := s0_can_go 223f1fe8698SLemover 2242a3050c2SJay /** 2252a3050c2SJay ****************************************************************************** 22658dbdfc2SJay * ICache Stage 1 22758dbdfc2SJay * - get tlb resp data (exceptiong info and physical addresses) 22858dbdfc2SJay * - get Meta/Data SRAM read responses (latched for pipeline stop) 22958dbdfc2SJay * - tag compare/hit check 230cb6e5d3cSssszwic * - check ipf and piq 2312a3050c2SJay ****************************************************************************** 2322a3050c2SJay */ 2331d8f4dcbSJay 23458dbdfc2SJay /** s1 control */ 235f1fe8698SLemover val s1_valid = generatePipeControl(lastFire = s0_fire, thisFire = s1_fire, thisFlush = false.B, lastFlush = false.B) 2361d8f4dcbSJay 237005e809bSJiuyang Liu val s1_req_vaddr = RegEnable(s0_final_vaddr, s0_fire) 238005e809bSJiuyang Liu val s1_req_vsetIdx = RegEnable(s0_final_vsetIdx, s0_fire) 239005e809bSJiuyang Liu val s1_double_line = RegEnable(s0_final_double_line, s0_fire) 240cb6e5d3cSssszwic 241cb6e5d3cSssszwic /** tlb request and response */ 242cb6e5d3cSssszwic fromITLB.foreach(_.ready := true.B) 243cb6e5d3cSssszwic val s1_wait_itlb = RegInit(VecInit(Seq.fill(PortNumber)(false.B))) 244cb6e5d3cSssszwic 245cb6e5d3cSssszwic (0 until PortNumber).foreach { i => 246cb6e5d3cSssszwic when(RegNext(s0_fire) && fromITLB(i).bits.miss) { 247cb6e5d3cSssszwic s1_wait_itlb(i) := true.B 248cb6e5d3cSssszwic }.elsewhen(s1_wait_itlb(i) && !fromITLB(i).bits.miss) { 249cb6e5d3cSssszwic s1_wait_itlb(i) := false.B 250cb6e5d3cSssszwic } 251cb6e5d3cSssszwic } 252cb6e5d3cSssszwic 253cb6e5d3cSssszwic val s1_need_itlb = Seq((RegNext(s0_fire) || s1_wait_itlb(0)) && fromITLB(0).bits.miss, 254cb6e5d3cSssszwic (RegNext(s0_fire) || s1_wait_itlb(1)) && fromITLB(1).bits.miss && s1_double_line) 255cb6e5d3cSssszwic val toITLB_s1_valid = s1_need_itlb 256cb6e5d3cSssszwic val toITLB_s1_size = VecInit(Seq(3.U, 3.U)) // TODO: fix the size 257cb6e5d3cSssszwic val toITLB_s1_vaddr = s1_req_vaddr 258cb6e5d3cSssszwic val toITLB_s1_debug_pc = s1_req_vaddr 259cb6e5d3cSssszwic 260cb6e5d3cSssszwic // chose tlb req between s0 and s1 261cb6e5d3cSssszwic for (i <- 0 until PortNumber) { 262cb6e5d3cSssszwic toITLB(i).valid := Mux(s1_need_itlb(i), toITLB_s1_valid(i), toITLB_s0_valid(i)) 263cb6e5d3cSssszwic toITLB(i).bits.size := Mux(s1_need_itlb(i), toITLB_s1_size(i), toITLB_s0_size(i)) 264cb6e5d3cSssszwic toITLB(i).bits.vaddr := Mux(s1_need_itlb(i), toITLB_s1_vaddr(i), toITLB_s0_vaddr(i)) 265cb6e5d3cSssszwic toITLB(i).bits.debug.pc := Mux(s1_need_itlb(i), toITLB_s1_debug_pc(i), toITLB_s0_debug_pc(i)) 266cb6e5d3cSssszwic } 267cb6e5d3cSssszwic toITLB.map{port => 268cb6e5d3cSssszwic port.bits.cmd := TlbCmd.exec 269cb6e5d3cSssszwic port.bits.memidx := DontCare 270cb6e5d3cSssszwic port.bits.debug.robIdx := DontCare 271cb6e5d3cSssszwic port.bits.no_translate := false.B 272cb6e5d3cSssszwic port.bits.debug.isFirstIssue := DontCare 273cb6e5d3cSssszwic port.bits.kill := DontCare 274382a2ebdSpeixiaokun port.bits.hlvx := DontCare 275382a2ebdSpeixiaokun port.bits.hyperinst := DontCare 276cb6e5d3cSssszwic } 277cb6e5d3cSssszwic io.itlb.foreach(_.req_kill := false.B) 2781d8f4dcbSJay 27958dbdfc2SJay /** tlb response latch for pipeline stop */ 280cb6e5d3cSssszwic // val tlb_valid_tmp = VecInit((0 until PortNumber).map(i => 281cb6e5d3cSssszwic // (RegNext(s0_fire) || s1_wait_itlb(i)) && !fromITLB(i).bits.miss)) 282cb6e5d3cSssszwic val tlb_valid_tmp = VecInit(Seq((RegNext(s0_fire) || s1_wait_itlb(0)) && !fromITLB(0).bits.miss, 283cb6e5d3cSssszwic (RegNext(s0_fire) || s1_wait_itlb(1)) && !fromITLB(1).bits.miss && s1_double_line)) 284cb6e5d3cSssszwic val tlbRespPAddr = VecInit((0 until PortNumber).map(i => 285cb6e5d3cSssszwic ResultHoldBypass(valid = tlb_valid_tmp(i), data = fromITLB(i).bits.paddr(0)))) 286*b436d3b6Speixiaokun val tlbRespGPAddr = VecInit((0 until PortNumber).map(i => 287*b436d3b6Speixiaokun ResultHoldBypass(valid = tlb_valid_tmp(i), data = fromITLB(i).bits.gpaddr(0)))) 288*b436d3b6Speixiaokun val tlbExcpGPF = VecInit((0 until PortNumber).map(i => 289*b436d3b6Speixiaokun ResultHoldBypass(valid = tlb_valid_tmp(i), data = fromITLB(i).bits.excp(0).gpf.instr))) 290cb6e5d3cSssszwic val tlbExcpPF = VecInit((0 until PortNumber).map(i => 291cb6e5d3cSssszwic ResultHoldBypass(valid = tlb_valid_tmp(i), data = fromITLB(i).bits.excp(0).pf.instr))) 292cb6e5d3cSssszwic val tlbExcpAF = VecInit((0 until PortNumber).map(i => 293cb6e5d3cSssszwic ResultHoldBypass(valid = tlb_valid_tmp(i), data = fromITLB(i).bits.excp(0).af.instr))) 294*b436d3b6Speixiaokun val tlbExcp = VecInit((0 until PortNumber).map(i => tlbExcpAF(i) || tlbExcpPF(i) || tlbExcpGPF(i))) 2951d8f4dcbSJay 296cb6e5d3cSssszwic val s1_tlb_valid = VecInit((0 until PortNumber).map(i => ValidHoldBypass(tlb_valid_tmp(i), s1_fire))) 297cb6e5d3cSssszwic val tlbRespAllValid = s1_tlb_valid(0) && (!s1_double_line || s1_double_line && s1_tlb_valid(1)) 2982a3050c2SJay 2991d8f4dcbSJay 300d2b20d1aSTang Haojin def numOfStage = 3 301d2b20d1aSTang Haojin val itlbMissStage = RegInit(VecInit(Seq.fill(numOfStage - 1)(0.B))) 302d2b20d1aSTang Haojin itlbMissStage(0) := !tlbRespAllValid 303d2b20d1aSTang Haojin for (i <- 1 until numOfStage - 1) { 304d2b20d1aSTang Haojin itlbMissStage(i) := itlbMissStage(i - 1) 305d2b20d1aSTang Haojin } 306d2b20d1aSTang Haojin 30758dbdfc2SJay /** s1 hit check/tag compare */ 3081d8f4dcbSJay val s1_req_paddr = tlbRespPAddr 309d0de7e4aSpeixiaokun val s1_req_gpaddr = tlbRespGPAddr 3101d8f4dcbSJay val s1_req_ptags = VecInit(s1_req_paddr.map(get_phy_tag(_))) 3111d8f4dcbSJay 312ccfc2e22SJay val s1_meta_ptags = ResultHoldBypass(data = metaResp.tags, valid = RegNext(s0_fire)) 31360672d5eSguohongyu val s1_meta_valids = ResultHoldBypass(data = metaResp.entryValid, valid = RegNext(s0_fire)) 31458dbdfc2SJay val s1_meta_errors = ResultHoldBypass(data = metaResp.errors, valid = RegNext(s0_fire)) 31558dbdfc2SJay 316ccfc2e22SJay val s1_data_cacheline = ResultHoldBypass(data = dataResp.datas, valid = RegNext(s0_fire)) 31779b191f7SJay val s1_data_errorBits = ResultHoldBypass(data = dataResp.codes, valid = RegNext(s0_fire)) 3181d8f4dcbSJay 3191d8f4dcbSJay val s1_tag_eq_vec = VecInit((0 until PortNumber).map( p => VecInit((0 until nWays).map( w => s1_meta_ptags(p)(w) === s1_req_ptags(p))))) 320a61a35e0Sssszwic val s1_tag_match_vec = VecInit((0 until PortNumber).map( k => VecInit(s1_tag_eq_vec(k).zipWithIndex.map{ case(way_tag_eq, w) => way_tag_eq && s1_meta_valids(k)(w)}))) 3211d8f4dcbSJay val s1_tag_match = VecInit(s1_tag_match_vec.map(vector => ParallelOR(vector))) 3221d8f4dcbSJay 323a61a35e0Sssszwic val s1_port_hit = VecInit(Seq(s1_tag_match(0) && s1_valid, s1_tag_match(1) && s1_valid && s1_double_line)) 3241d8f4dcbSJay 3251d8f4dcbSJay /** choose victim cacheline */ 3262f4a98abSssszwic val bank_vsetIdx = VecInit((0 until PortNumber).map( i => Mux(s1_req_vsetIdx(i)(0), s1_req_vsetIdx(1)(highestIdxBit, 1), s1_req_vsetIdx(0)(highestIdxBit, 1)))) 3275b0cc873Sguohongyu val replacers = Seq.fill(PortNumber)(ReplacementPolicy.fromString(cacheParams.replacer,nWays,nSets/PortNumber)) 3282f4a98abSssszwic val bank_victim_oh = ResultHoldBypass(data = VecInit(replacers.zipWithIndex.map{case (replacer, i) => UIntToOH(replacer.way(bank_vsetIdx(i)))}), valid = RegNext(s0_fire)) 3292f4a98abSssszwic val s1_victim_oh = VecInit((0 until PortNumber).map( i => Mux(s1_req_vsetIdx(i)(0), bank_victim_oh(1), bank_victim_oh(0)))) 3301d8f4dcbSJay 3312f4a98abSssszwic when(s1_fire){ 3322f4a98abSssszwic assert(PopCount(s1_tag_match_vec(0)) <= 1.U && (PopCount(s1_tag_match_vec(1)) <= 1.U || !s1_double_line), 3332f4a98abSssszwic "Multiple hit in main pipe, port0:is=%d,ptag=0x%x,vidx=0x%x,vaddr=0x%x port1:is=%d,ptag=0x%x,vidx=0x%x,vaddr=0x%x ", 3342f4a98abSssszwic PopCount(s1_tag_match_vec(0)) > 1.U,s1_req_ptags(0), get_idx(s1_req_vaddr(0)), s1_req_vaddr(0), 3352f4a98abSssszwic PopCount(s1_tag_match_vec(1)) > 1.U && s1_double_line, s1_req_ptags(1), get_idx(s1_req_vaddr(1)), s1_req_vaddr(1)) 3362f4a98abSssszwic } 3371d8f4dcbSJay 338cb6e5d3cSssszwic /** check ipf, get result at the same cycle */ 339b1ded4e8Sguohongyu (0 until PortNumber).foreach { i => 340cb6e5d3cSssszwic toIPF(i).valid := tlb_valid_tmp(i) 341b1ded4e8Sguohongyu toIPF(i).bits.paddr := s1_req_paddr(i) 342b1ded4e8Sguohongyu } 343cb6e5d3cSssszwic val s1_ipf_hit = VecInit((0 until PortNumber).map(i => toIPF(i).valid && fromIPF(i).ipf_hit)) 344cb6e5d3cSssszwic val s1_ipf_hit_latch = VecInit((0 until PortNumber).map(i => holdReleaseLatch(valid = s1_ipf_hit(i), release = s1_fire, flush = false.B))) 345cb6e5d3cSssszwic val s1_ipf_data = VecInit((0 until PortNumber).map(i => ResultHoldBypass(data = fromIPF(i).cacheline, valid = s1_ipf_hit(i)))) 346b1ded4e8Sguohongyu 347b1ded4e8Sguohongyu /** check in PIQ, if hit, wait until prefetch port hit */ 348cb6e5d3cSssszwic (0 until PortNumber).foreach { i => 349cb6e5d3cSssszwic toPIQ(i).valid := tlb_valid_tmp(i) 350cb6e5d3cSssszwic toPIQ(i).bits.paddr := s1_req_paddr(i) 351b1ded4e8Sguohongyu } 352cb6e5d3cSssszwic val s1_piq_hit = VecInit((0 until PortNumber).map(i => toIPF(i).valid && fromPIQ(i).piq_hit)) 353cb6e5d3cSssszwic val s1_piq_hit_latch = VecInit((0 until PortNumber).map(i => holdReleaseLatch(valid = s1_piq_hit(i), release = s1_fire, flush = false.B))) 354cb6e5d3cSssszwic val wait_piq = VecInit((0 until PortNumber).map(i => toIPF(i).valid && fromPIQ(i).piq_hit && !fromPIQ(i).data_valid)) 355cb6e5d3cSssszwic val wait_piq_latch = VecInit((0 until PortNumber).map(i => holdReleaseLatch(valid = wait_piq(i), release = s1_fire || fromPIQ(i).data_valid, flush = false.B))) 356cb6e5d3cSssszwic val s1_piq_data = VecInit((0 until PortNumber).map(i => ResultHoldBypass(data = fromPIQ(i).cacheline, valid = (s1_piq_hit(i) || wait_piq_latch(i)) && fromPIQ(i).data_valid))) 357b1ded4e8Sguohongyu 358cb6e5d3cSssszwic val s1_wait = (0 until PortNumber).map(i => wait_piq_latch(i) && !fromPIQ(i).data_valid).reduce(_||_) 359b1ded4e8Sguohongyu 360cb6e5d3cSssszwic val s1_prefetch_hit = VecInit((0 until PortNumber).map(i => s1_ipf_hit_latch(i) || s1_piq_hit_latch(i))) 361cb6e5d3cSssszwic val s1_prefetch_hit_data = VecInit((0 until PortNumber).map(i => Mux(s1_ipf_hit_latch(i), s1_ipf_data(i), s1_piq_data(i)))) 362cb6e5d3cSssszwic 363cb6e5d3cSssszwic s1_ready := s2_ready && tlbRespAllValid && !s1_wait || !s1_valid 364cb6e5d3cSssszwic s1_fire := s1_valid && tlbRespAllValid && s2_ready && !s1_wait 365b1ded4e8Sguohongyu 366f9c51548Sssszwic // record cacheline log 367f9c51548Sssszwic val isWriteICacheTable = WireInit(Constantin.createRecord("isWriteICacheTable" + p(XSCoreParamsKey).HartId.toString)) 368f9c51548Sssszwic val ICacheTable = ChiselDB.createTable("ICacheTable" + p(XSCoreParamsKey).HartId.toString, new ICacheDB) 369f9c51548Sssszwic 370f9c51548Sssszwic val ICacheDumpData_req0 = Wire(new ICacheDB) 371f9c51548Sssszwic ICacheDumpData_req0.blk_paddr := getBlkAddr(s1_req_paddr(0)) 372f9c51548Sssszwic ICacheDumpData_req0.blk_vaddr := getBlkAddr(s1_req_vaddr(0)) 373f9c51548Sssszwic ICacheDumpData_req0.hit := s1_port_hit(0) || s1_prefetch_hit(0) 374f9c51548Sssszwic ICacheTable.log( 375f9c51548Sssszwic data = ICacheDumpData_req0, 376f9c51548Sssszwic en = isWriteICacheTable.orR && s1_fire, 377f9c51548Sssszwic clock = clock, 378f9c51548Sssszwic reset = reset 379f9c51548Sssszwic ) 380f9c51548Sssszwic 381f9c51548Sssszwic val ICacheDumpData_req1 = Wire(new ICacheDB) 382f9c51548Sssszwic ICacheDumpData_req1.blk_paddr := getBlkAddr(s1_req_paddr(1)) 383f9c51548Sssszwic ICacheDumpData_req1.blk_vaddr := getBlkAddr(s1_req_vaddr(1)) 384f9c51548Sssszwic ICacheDumpData_req1.hit := s1_port_hit(1) || s1_prefetch_hit(1) 385f9c51548Sssszwic ICacheTable.log( 386f9c51548Sssszwic data = ICacheDumpData_req1, 387f9c51548Sssszwic en = isWriteICacheTable.orR && s1_fire && s1_double_line, 388f9c51548Sssszwic clock = clock, 389f9c51548Sssszwic reset = reset 390f9c51548Sssszwic ) 391f9c51548Sssszwic 39258dbdfc2SJay /** <PERF> replace victim way number */ 39358dbdfc2SJay 3941d8f4dcbSJay (0 until nWays).map{ w => 3951d8f4dcbSJay XSPerfAccumulate("line_0_hit_way_" + Integer.toString(w, 10), s1_fire && s1_port_hit(0) && OHToUInt(s1_tag_match_vec(0)) === w.U) 3961d8f4dcbSJay } 3971d8f4dcbSJay 3981d8f4dcbSJay (0 until nWays).map{ w => 3991d8f4dcbSJay XSPerfAccumulate("line_0_victim_way_" + Integer.toString(w, 10), s1_fire && !s1_port_hit(0) && OHToUInt(s1_victim_oh(0)) === w.U) 4001d8f4dcbSJay } 4011d8f4dcbSJay 4021d8f4dcbSJay (0 until nWays).map{ w => 4031d8f4dcbSJay XSPerfAccumulate("line_1_hit_way_" + Integer.toString(w, 10), s1_fire && s1_double_line && s1_port_hit(1) && OHToUInt(s1_tag_match_vec(1)) === w.U) 4041d8f4dcbSJay } 4051d8f4dcbSJay 4061d8f4dcbSJay (0 until nWays).map{ w => 4071d8f4dcbSJay XSPerfAccumulate("line_1_victim_way_" + Integer.toString(w, 10), s1_fire && s1_double_line && !s1_port_hit(1) && OHToUInt(s1_victim_oh(1)) === w.U) 4081d8f4dcbSJay } 4091d8f4dcbSJay 410b1ded4e8Sguohongyu XSPerfAccumulate("mainPipe_stage1_block_by_piq_cycles", s1_valid && s1_wait) 411b1ded4e8Sguohongyu 4122a3050c2SJay /** 4132a3050c2SJay ****************************************************************************** 41458dbdfc2SJay * ICache Stage 2 41558dbdfc2SJay * - send request to MSHR if ICache miss 41658dbdfc2SJay * - generate secondary miss status/data registers 41758dbdfc2SJay * - response to IFU 4182a3050c2SJay ****************************************************************************** 4192a3050c2SJay */ 42058dbdfc2SJay 42158dbdfc2SJay /** s2 control */ 4221d8f4dcbSJay val s2_fetch_finish = Wire(Bool()) 4231d8f4dcbSJay 424f1fe8698SLemover val s2_valid = generatePipeControl(lastFire = s1_fire, thisFire = s2_fire, thisFlush = false.B, lastFlush = false.B) 4251d8f4dcbSJay 426a61a35e0Sssszwic s2_ready := (s2_valid && s2_fetch_finish && !io.respStall) || !s2_valid 4271d8f4dcbSJay s2_fire := s2_valid && s2_fetch_finish && !io.respStall 4281d8f4dcbSJay 42958dbdfc2SJay /** s2 data */ 430cb6e5d3cSssszwic // val mmio = fromPMP.map(port => port.mmio) // TODO: handle it 431005e809bSJiuyang Liu val (s2_req_paddr , s2_req_vaddr) = (RegEnable(s1_req_paddr, s1_fire), RegEnable(s1_req_vaddr, s1_fire)) 432d0de7e4aSpeixiaokun val s2_req_gpaddr = RegEnable(s1_req_gpaddr, s1_fire) 433005e809bSJiuyang Liu val s2_req_vsetIdx = RegEnable(s1_req_vsetIdx, s1_fire) 434005e809bSJiuyang Liu val s2_req_ptags = RegEnable(s1_req_ptags, s1_fire) 435005e809bSJiuyang Liu val s2_double_line = RegEnable(s1_double_line, s1_fire) 436005e809bSJiuyang Liu val s2_port_hit = RegEnable(s1_port_hit, s1_fire) 437005e809bSJiuyang Liu val s2_waymask = RegEnable(s1_victim_oh, s1_fire) 438005e809bSJiuyang Liu val s2_tag_match_vec = RegEnable(s1_tag_match_vec, s1_fire) 4391d8f4dcbSJay 440a61a35e0Sssszwic val s2_meta_errors = RegEnable(s1_meta_errors, s1_fire) 441a61a35e0Sssszwic val s2_data_errorBits = RegEnable(s1_data_errorBits, s1_fire) 442a61a35e0Sssszwic val s2_data_cacheline = RegEnable(s1_data_cacheline, s1_fire) 443d2b20d1aSTang Haojin 44458c354d0Sssszwic /** send req info of s1 and s2 to IPrefetchPipe for filter request */ 44558c354d0Sssszwic toIPrefetch.s1Info(0).paddr := s1_req_paddr(0) 44658c354d0Sssszwic toIPrefetch.s1Info(0).valid := s1_valid 44758c354d0Sssszwic toIPrefetch.s1Info(1).paddr := s1_req_paddr(1) 44858c354d0Sssszwic toIPrefetch.s1Info(1).valid := s1_valid && s1_double_line 44958c354d0Sssszwic toIPrefetch.s2Info(0).paddr := s2_req_paddr(0) 45058c354d0Sssszwic toIPrefetch.s2Info(0).valid := s2_valid 45158c354d0Sssszwic toIPrefetch.s2Info(1).paddr := s2_req_paddr(1) 45258c354d0Sssszwic toIPrefetch.s2Info(1).valid := s2_valid && s2_double_line 45358c354d0Sssszwic 454f1fe8698SLemover assert(RegNext(!s2_valid || s2_req_paddr(0)(11,0) === s2_req_vaddr(0)(11,0), true.B)) 455f1fe8698SLemover 456a61a35e0Sssszwic /** 457a61a35e0Sssszwic ****************************************************************************** 458a61a35e0Sssszwic * tlb exception and pmp logic 459a61a35e0Sssszwic ****************************************************************************** 460a61a35e0Sssszwic */ 461a61a35e0Sssszwic // short delay exception signal 462a61a35e0Sssszwic val s2_except_tlb_pf = RegEnable(tlbExcpPF, s1_fire) 463*b436d3b6Speixiaokun val s2_except_tlb_gpf = RegEnable(tlbExcpGPF, s1_fire) 464a61a35e0Sssszwic val s2_except_tlb_af = RegEnable(tlbExcpAF, s1_fire) 465*b436d3b6Speixiaokun val s2_except_tlb = VecInit(Seq(s2_except_tlb_pf(0) || s2_except_tlb_af(0) || s2_except_tlb_gpf(0), s2_double_line && (s2_except_tlb_pf(1) || s2_except_tlb_af(1) || s2_except_tlb_gpf(1)))) 466a61a35e0Sssszwic val s2_has_except_tlb = s2_valid && s2_except_tlb.reduce(_||_) 467a61a35e0Sssszwic // long delay exception signal 468a61a35e0Sssszwic // exception information and mmio 469a61a35e0Sssszwic val pmpExcpAF = VecInit(Seq(fromPMP(0).instr, fromPMP(1).instr && s2_double_line)) 470a61a35e0Sssszwic val s2_except_pmp_af = DataHoldBypass(pmpExcpAF, RegNext(s1_fire)) 471a61a35e0Sssszwic val s2_mmio = s2_valid && DataHoldBypass(fromPMP(0).mmio && !s2_except_tlb(0) && !s2_except_pmp_af(0), RegNext(s1_fire)).asBool 472a61a35e0Sssszwic // pmp port 473a61a35e0Sssszwic toPMP.zipWithIndex.map { case (p, i) => 474a61a35e0Sssszwic p.valid := s2_valid 475a61a35e0Sssszwic p.bits.addr := s2_req_paddr(i) 476a61a35e0Sssszwic p.bits.size := 3.U // TODO 477a61a35e0Sssszwic p.bits.cmd := TlbCmd.exec 478a61a35e0Sssszwic } 4791d8f4dcbSJay 480a61a35e0Sssszwic /** 481a61a35e0Sssszwic ****************************************************************************** 482a61a35e0Sssszwic * look last miss data 483a61a35e0Sssszwic ****************************************************************************** 484a61a35e0Sssszwic */ 485a61a35e0Sssszwic class MissSlot(implicit p: Parameters) extends ICacheBundle { 486a61a35e0Sssszwic val paddr = RegInit(0.U(PAddrBits.W)) 487a61a35e0Sssszwic val vSetIdx = RegInit(0.U(idxBits.W)) 488a61a35e0Sssszwic val waymask = RegInit(0.U(nWays.W)) 489a61a35e0Sssszwic val data = RegInit(0.U(blockBits.W)) 490a61a35e0Sssszwic val corrupt = RegInit(false.B) 491a61a35e0Sssszwic val finish = RegInit(true.B) 492a61a35e0Sssszwic val valid = RegInit(false.B) 493a61a35e0Sssszwic def data_vec = data.asTypeOf(Vec(2, UInt((blockBits/2).W))) 494a61a35e0Sssszwic def pTag = get_phy_tag(paddr) 495a61a35e0Sssszwic } 496a61a35e0Sssszwic val missSlot = Seq.fill(2)(new MissSlot) 49779b191f7SJay 498a61a35e0Sssszwic // whether hit in last miss req 499a61a35e0Sssszwic def getMissSituat(missNum : Int, slotNum : Int ) :Bool = { 500a61a35e0Sssszwic (missSlot(slotNum).vSetIdx === s1_req_vsetIdx(missNum)) && 501a61a35e0Sssszwic (missSlot(slotNum).pTag === s1_req_ptags(missNum)) && 502a61a35e0Sssszwic !missSlot(slotNum).corrupt && missSlot(slotNum).finish && 503a61a35e0Sssszwic missSlot(slotNum).valid 504a61a35e0Sssszwic } 505a61a35e0Sssszwic 506a61a35e0Sssszwic // s2_hit_slot(0)(1): port 0 hit slot 1 507a61a35e0Sssszwic // Use the signal of S1 to make a judgment for timing, the value of missSlot has benn set when s1 fire 508a61a35e0Sssszwic val s1_hit_slot_vec = VecInit((0 until PortNumber).map(port => VecInit((0 until PortNumber).map(getMissSituat(port, _))))) 509a61a35e0Sssszwic val s2_hit_slot_vec = RegEnable(s1_hit_slot_vec, s1_fire) 510a61a35e0Sssszwic 511a61a35e0Sssszwic // select one from two missSlots to handle miss for every port 512a61a35e0Sssszwic // slot(0) hit && slot(1) hit : don't case 513a61a35e0Sssszwic // slot(0) hit && slot(1) miss: (a) missed port(0) -> slot(1); (b) missed port(1) -> slot(1) 514a61a35e0Sssszwic // slot(0) miss && slot(1) hit : (a) missed port(0) -> slot(0); (b) missed port(1) -> slot(0) 515a61a35e0Sssszwic // slot(0) miss && slot(1) miss: missed port(0) -> slot(0) missed port(1) -> slot(1) 516a61a35e0Sssszwic val s1_curr_slot_id = Wire(Vec(2, Bool())) 517a61a35e0Sssszwic s1_curr_slot_id(0) := s1_hit_slot_vec(0)(0) || s1_hit_slot_vec(1)(0) 518a61a35e0Sssszwic s1_curr_slot_id(1) := !(s1_hit_slot_vec(0)(1) || s1_hit_slot_vec(1)(1)) 519a61a35e0Sssszwic val s2_curr_slot_id = RegEnable(s1_curr_slot_id, s1_fire) 520a61a35e0Sssszwic 521a61a35e0Sssszwic /** 522a61a35e0Sssszwic ****************************************************************************** 523a61a35e0Sssszwic * miss handle 524a61a35e0Sssszwic ****************************************************************************** 525a61a35e0Sssszwic */ 526a61a35e0Sssszwic val s2_hit_slot = VecInit(s2_hit_slot_vec.map(_.asUInt.orR)) 527a61a35e0Sssszwic val s2_fixed_port_hit = VecInit((0 until PortNumber).map(port => s2_port_hit(port) || s2_hit_slot(port))) 528a61a35e0Sssszwic 529a61a35e0Sssszwic // only handle port0 miss when port1 have tlb except or pmp except 530a61a35e0Sssszwic val s2_port_miss = Wire(Vec(PortNumber, Bool())) 531a61a35e0Sssszwic 532a61a35e0Sssszwic s2_port_miss(0) := !s2_fixed_port_hit(0) && !s2_except_tlb(0) && !s2_except_pmp_af(0) && !s2_mmio 533a61a35e0Sssszwic s2_port_miss(1) := !s2_fixed_port_hit(1) && s2_double_line && !s2_except_tlb(0) && !s2_except_tlb(1) && 534a61a35e0Sssszwic !s2_except_pmp_af(0) && !s2_except_pmp_af(1) && !s2_mmio 535a61a35e0Sssszwic 536a61a35e0Sssszwic (0 until PortNumber).map{ i => 537a61a35e0Sssszwic when(s2_port_miss(i) && RegNext(s1_fire)) { 538a61a35e0Sssszwic when(s2_curr_slot_id(i)) { 539a61a35e0Sssszwic missSlot(1).vSetIdx := s2_req_vsetIdx(i) 540a61a35e0Sssszwic missSlot(1).paddr := s2_req_paddr(i) 541a61a35e0Sssszwic missSlot(1).waymask := s2_waymask(i) 542a61a35e0Sssszwic missSlot(1).finish := false.B 543a61a35e0Sssszwic missSlot(1).valid := true.B 544a61a35e0Sssszwic }.otherwise { 545a61a35e0Sssszwic missSlot(0).vSetIdx := s2_req_vsetIdx(i) 546a61a35e0Sssszwic missSlot(0).paddr := s2_req_paddr(i) 547a61a35e0Sssszwic missSlot(0).waymask := s2_waymask(i) 548a61a35e0Sssszwic missSlot(0).finish := false.B 549a61a35e0Sssszwic missSlot(0).valid := true.B 550a61a35e0Sssszwic } 551a61a35e0Sssszwic } 552a61a35e0Sssszwic } 553a61a35e0Sssszwic 554a61a35e0Sssszwic // which missSlot need to be issued 555a61a35e0Sssszwic val s2_missSlot_issue = Wire(Vec(2, Bool())) 556a61a35e0Sssszwic s2_missSlot_issue(0) := (s2_port_miss(0) && !s2_curr_slot_id(0)) || (s2_port_miss(1) && !s2_curr_slot_id(1)) 557a61a35e0Sssszwic s2_missSlot_issue(1) := (s2_port_miss(0) && s2_curr_slot_id(0)) || (s2_port_miss(1) && s2_curr_slot_id(1)) 558a61a35e0Sssszwic 559a61a35e0Sssszwic // state machine 560a61a35e0Sssszwic val m_idle ::m_send_req :: m_wait_resp :: Nil = Enum(3) 561a61a35e0Sssszwic val missStateQueue = RegInit(VecInit(Seq.fill(2)(m_idle))) 562a61a35e0Sssszwic 563a61a35e0Sssszwic (0 until PortNumber).map{ i => 564a61a35e0Sssszwic switch(missStateQueue(i)){ 565a61a35e0Sssszwic is(m_idle) { 566a61a35e0Sssszwic missStateQueue(i) := Mux(RegNext(s1_fire) && s2_missSlot_issue(i), m_send_req, m_idle) 567a61a35e0Sssszwic } 568a61a35e0Sssszwic is(m_send_req) { 569a61a35e0Sssszwic missStateQueue(i) := Mux(toMSHR(i).fire, m_wait_resp, m_send_req) 570a61a35e0Sssszwic } 571a61a35e0Sssszwic is(m_wait_resp) { 572a61a35e0Sssszwic missStateQueue(i) := Mux(fromMSHR(i).fire, m_idle, m_wait_resp) 573a61a35e0Sssszwic } 574a61a35e0Sssszwic } 575a61a35e0Sssszwic } 576a61a35e0Sssszwic 577a61a35e0Sssszwic // send req to MSHR 578a61a35e0Sssszwic (0 until PortNumber).map{i => 579a61a35e0Sssszwic toMSHR(i).valid := missStateQueue(i) === m_send_req 580a61a35e0Sssszwic toMSHR(i).bits.paddr := missSlot(i).paddr 581a61a35e0Sssszwic toMSHR(i).bits.vSetIdx := missSlot(i).vSetIdx 582a61a35e0Sssszwic toMSHR(i).bits.waymask := missSlot(i).waymask 583a61a35e0Sssszwic } 584a61a35e0Sssszwic 585a61a35e0Sssszwic // recrive resp from MSHR to update missSlot 586a61a35e0Sssszwic (0 until PortNumber).map{ i => 587a61a35e0Sssszwic when((missStateQueue(i) === m_wait_resp) && fromMSHR(i).fire) { 588a61a35e0Sssszwic missSlot(i).finish := true.B 589a61a35e0Sssszwic missSlot(i).data := fromMSHR(i).bits.data 590a61a35e0Sssszwic missSlot(i).corrupt := fromMSHR(i).bits.corrupt 591a61a35e0Sssszwic } 592a61a35e0Sssszwic } 593a61a35e0Sssszwic 594a61a35e0Sssszwic // handle miss finish 595a61a35e0Sssszwic s2_fetch_finish := (!s2_port_miss(0) && !s2_port_miss(1)) || (missSlot(0).finish && missSlot(1).finish && !RegNext(s1_fire)) 596a61a35e0Sssszwic 597a61a35e0Sssszwic /** 598a61a35e0Sssszwic ****************************************************************************** 599a61a35e0Sssszwic * select data from hitted sram data, last missSlot and current missSlot 600a61a35e0Sssszwic ****************************************************************************** 601a61a35e0Sssszwic */ 602a61a35e0Sssszwic val s2_hit_datas = Wire(Vec(2, UInt((blockBits/2).W))) 603a61a35e0Sssszwic s2_hit_datas(0) := Mux1H(s2_tag_match_vec(0).asUInt, s2_data_cacheline(0)) 604a61a35e0Sssszwic s2_hit_datas(1) := Mux1H(Mux(s2_double_line, s2_tag_match_vec(1).asUInt, s2_tag_match_vec(0).asUInt), s2_data_cacheline(1)) 605a61a35e0Sssszwic 606a61a35e0Sssszwic // get cacheline from last slot 607a61a35e0Sssszwic val s2_last_slot_cacheline = (0 until PortNumber).map(port => Mux1H(s2_hit_slot_vec(port).asUInt, missSlot.map(_.data_vec))) 608a61a35e0Sssszwic // get cacheline from curr slot 609a61a35e0Sssszwic val s2_curr_slot_cacheline = (0 until PortNumber).map(port => Mux(s2_curr_slot_id(port), missSlot(1).data_vec, missSlot(0).data_vec)) 610a61a35e0Sssszwic val s2_slot_cacheline = (0 until PortNumber).map(port => Mux(s2_hit_slot(port), s2_last_slot_cacheline(port), s2_curr_slot_cacheline(port))) 611a61a35e0Sssszwic val s2_slot_data = Wire(Vec(PortNumber, UInt((blockBits/2).W))) 612a61a35e0Sssszwic s2_slot_data(0) := Mux(s2_double_line, s2_slot_cacheline(0)(1), s2_slot_cacheline(0)(0)) 613a61a35e0Sssszwic s2_slot_data(1) := Mux(s2_double_line, s2_slot_cacheline(1)(0), s2_slot_cacheline(0)(1)) 614a61a35e0Sssszwic 615a61a35e0Sssszwic val s2_fetch_data = Wire(Vec(2, UInt((blockBits/2).W))) 616a61a35e0Sssszwic s2_fetch_data(0) := Mux(s2_port_hit(0), s2_hit_datas(0), s2_slot_data(0)) 617a61a35e0Sssszwic s2_fetch_data(1) := Mux(s2_port_hit(1) || (s2_port_hit(0) && !s2_double_line), s2_hit_datas(1), s2_slot_data(1)) 618a61a35e0Sssszwic 619a61a35e0Sssszwic val s2_corrupt = (0 until PortNumber).map(port => s2_port_miss(port) && Mux(s2_curr_slot_id(port), missSlot(1).corrupt, missSlot(0).corrupt)) 620a61a35e0Sssszwic 621a61a35e0Sssszwic /** 622a61a35e0Sssszwic ****************************************************************************** 623a61a35e0Sssszwic * IFU data resp 624a61a35e0Sssszwic ****************************************************************************** 625a61a35e0Sssszwic */ 626a61a35e0Sssszwic (0 until PortNumber).map{ i => 627a61a35e0Sssszwic if(i ==0) toIFU(i).valid := s2_fire 628a61a35e0Sssszwic else toIFU(i).valid := s2_fire && s2_double_line 629a61a35e0Sssszwic toIFU(i).bits.paddr := s2_req_paddr(i) 630*b436d3b6Speixiaokun toIFU(i).bits.gpaddr := s2_req_gpaddr(i) 631a61a35e0Sssszwic toIFU(i).bits.vaddr := s2_req_vaddr(i) 632a61a35e0Sssszwic toIFU(i).bits.data := s2_fetch_data(i) 633a61a35e0Sssszwic toIFU(i).bits.tlbExcp.pageFault := s2_except_tlb_pf(i) 634*b436d3b6Speixiaokun toIFU(i).bits.tlbExcp.guestPageFault:= s2_except_tlb_gpf(i) 635a61a35e0Sssszwic toIFU(i).bits.tlbExcp.accessFault := s2_except_tlb_af(i) || s2_corrupt(i) || s2_except_pmp_af(i) 636a61a35e0Sssszwic toIFU(i).bits.tlbExcp.mmio := s2_mmio 637a61a35e0Sssszwic } 638a61a35e0Sssszwic 639a61a35e0Sssszwic /** 640a61a35e0Sssszwic ****************************************************************************** 641a61a35e0Sssszwic * error resp: MSHR error 642a61a35e0Sssszwic ****************************************************************************** 643a61a35e0Sssszwic */ 644a61a35e0Sssszwic // data/meta parity error 64579b191f7SJay val s2_data_errors = Wire(Vec(PortNumber,Vec(nWays, Bool()))) 64679b191f7SJay (0 until PortNumber).map{ i => 64779b191f7SJay val read_datas = s2_data_cacheline(i).asTypeOf(Vec(nWays,Vec(dataCodeUnitNum, UInt(dataCodeUnit.W)))) 64879b191f7SJay val read_codes = s2_data_errorBits(i).asTypeOf(Vec(nWays,Vec(dataCodeUnitNum, UInt(dataCodeBits.W)))) 64979b191f7SJay val data_full_wayBits = VecInit((0 until nWays).map( w => 65079b191f7SJay VecInit((0 until dataCodeUnitNum).map( u => 65179b191f7SJay Cat(read_codes(w)(u), read_datas(w)(u)))))) 65279b191f7SJay val data_error_wayBits = VecInit((0 until nWays).map( w => 65379b191f7SJay VecInit((0 until dataCodeUnitNum).map( u => 65479b191f7SJay cacheParams.dataCode.decode(data_full_wayBits(w)(u)).error)))) 655a61a35e0Sssszwic // register for timing 65679b191f7SJay if(i == 0){ 65779b191f7SJay (0 until nWays).map{ w => 65879b191f7SJay s2_data_errors(i)(w) := RegNext(RegNext(s1_fire)) && RegNext(data_error_wayBits(w)).reduce(_||_) 65979b191f7SJay } 66079b191f7SJay } else { 66179b191f7SJay (0 until nWays).map{ w => 66279b191f7SJay s2_data_errors(i)(w) := RegNext(RegNext(s1_fire)) && RegNext(RegNext(s1_double_line)) && RegNext(data_error_wayBits(w)).reduce(_||_) 66379b191f7SJay } 66479b191f7SJay } 66579b191f7SJay } 66679b191f7SJay 66779b191f7SJay val s2_parity_meta_error = VecInit((0 until PortNumber).map(i => s2_meta_errors(i).reduce(_||_) && io.csr_parity_enable)) 66879b191f7SJay val s2_parity_data_error = VecInit((0 until PortNumber).map(i => s2_data_errors(i).reduce(_||_) && io.csr_parity_enable)) 66979b191f7SJay val s2_parity_error = VecInit((0 until PortNumber).map(i => RegNext(s2_parity_meta_error(i)) || s2_parity_data_error(i))) 67079b191f7SJay 67179b191f7SJay for(i <- 0 until PortNumber){ 672e8e4462cSJay io.errors(i).valid := RegNext(s2_parity_error(i) && RegNext(RegNext(s1_fire))) 673e8e4462cSJay io.errors(i).report_to_beu := RegNext(s2_parity_error(i) && RegNext(RegNext(s1_fire))) 67479b191f7SJay io.errors(i).paddr := RegNext(RegNext(s2_req_paddr(i))) 67579b191f7SJay io.errors(i).source := DontCare 67679b191f7SJay io.errors(i).source.tag := RegNext(RegNext(s2_parity_meta_error(i))) 67779b191f7SJay io.errors(i).source.data := RegNext(s2_parity_data_error(i)) 67879b191f7SJay io.errors(i).source.l2 := false.B 67979b191f7SJay io.errors(i).opType := DontCare 68079b191f7SJay io.errors(i).opType.fetch := true.B 68179b191f7SJay } 68279b191f7SJay 683a61a35e0Sssszwic // MSHR error 684a61a35e0Sssszwic (0 until PortNumber).map{ i => 685a61a35e0Sssszwic when(RegNext(s2_fire && s2_corrupt(i))){ 686a61a35e0Sssszwic io.errors(i).valid := true.B 687a61a35e0Sssszwic io.errors(i).report_to_beu := false.B // l2 should have report that to bus error unit, no need to do it again 688a61a35e0Sssszwic io.errors(i).paddr := RegNext(s2_req_paddr(i)) 689a61a35e0Sssszwic io.errors(i).source.tag := false.B 690a61a35e0Sssszwic io.errors(i).source.data := false.B 691a61a35e0Sssszwic io.errors(i).source.l2 := true.B 6921d8f4dcbSJay } 6931d8f4dcbSJay } 6941d8f4dcbSJay 695a61a35e0Sssszwic /** 696a61a35e0Sssszwic ****************************************************************************** 697a61a35e0Sssszwic * s2 prefetch port 698a61a35e0Sssszwic ****************************************************************************** 699a61a35e0Sssszwic */ 700a61a35e0Sssszwic (0 until PortNumber).foreach{ i => 701a61a35e0Sssszwic // TODO: consider corrupt of missSlot 702a61a35e0Sssszwic toIPrefetch.missSlot(i).valid := missSlot(i).valid 703a61a35e0Sssszwic toIPrefetch.missSlot(i).vSetIdx := missSlot(i).vSetIdx 704a61a35e0Sssszwic toIPrefetch.missSlot(i).ptag := missSlot(i).pTag 7051d8f4dcbSJay } 7061d8f4dcbSJay 707a61a35e0Sssszwic /** 708a61a35e0Sssszwic ****************************************************************************** 709a61a35e0Sssszwic * update replacement status register 710a61a35e0Sssszwic ****************************************************************************** 711a61a35e0Sssszwic */ 712a61a35e0Sssszwic /** replacement status register */ 7132f4a98abSssszwic val port_touch_sets = Seq.fill(PortNumber)(Wire(Vec(2, UInt(log2Ceil(nSets/2).W)))) 7142f4a98abSssszwic val port_touch_ways = Seq.fill(PortNumber)(Wire(Vec(2, Valid(UInt(log2Ceil(nWays).W))))) 7152f4a98abSssszwic (port_touch_ways zip port_touch_sets).zipWithIndex.map{ case((t_w,t_s), i) => 7162f4a98abSssszwic /** update replacement status register: 0 is hit access/ 1 is miss access */ 7175b0cc873Sguohongyu t_s(0) := s2_req_vsetIdx(i)(highestIdxBit, 1) 7182f4a98abSssszwic // hit in slot will be ignored, which generate a repeated access 71961e1db30SJay t_w(0).valid := s2_valid && s2_port_hit(i) 72061e1db30SJay t_w(0).bits := OHToUInt(s2_tag_match_vec(i)) 7211d8f4dcbSJay 7225b0cc873Sguohongyu t_s(1) := s2_req_vsetIdx(i)(highestIdxBit, 1) 723a61a35e0Sssszwic t_w(1).valid := s2_valid && s2_port_miss(i) 7241d8f4dcbSJay t_w(1).bits := OHToUInt(s2_waymask(i)) 7251d8f4dcbSJay } 7261d8f4dcbSJay 7272f4a98abSssszwic val touch_ways = VecInit((0 until PortNumber).map( i => Mux(s2_req_vsetIdx(i)(0), port_touch_ways(1), port_touch_ways(0)))) 7282f4a98abSssszwic val touch_sets = VecInit((0 until PortNumber).map( i => Mux(s2_req_vsetIdx(i)(0), port_touch_sets(1), port_touch_sets(0)))) 7292f4a98abSssszwic ((replacers zip touch_sets) zip touch_ways).map{case ((r, s),w) => r.access(s,w)} 730a61a35e0Sssszwic // TODO: need choose one replacer according to the bankid 7312f4a98abSssszwic IPFReplacer.waymask := UIntToOH(replacers(0).way(IPFReplacer.vsetIdx)) 7322f4a98abSssszwic 733a61a35e0Sssszwic /** 734a61a35e0Sssszwic ****************************************************************************** 735a61a35e0Sssszwic * performance info. TODO: need to simplify the logic 736a61a35e0Sssszwic ***********************************************************s******************* 737a61a35e0Sssszwic */ 738a61a35e0Sssszwic io.fetch.topdownIcacheMiss := s2_port_miss(0) || s2_port_miss(1) 739d2b20d1aSTang Haojin io.fetch.topdownItlbMiss := itlbMissStage(0) 740d2b20d1aSTang Haojin 741a61a35e0Sssszwic io.perfInfo.only_0_hit := s2_fixed_port_hit(0) && !s2_double_line 742a61a35e0Sssszwic io.perfInfo.only_0_miss := !s2_fixed_port_hit(0) && !s2_double_line 743a61a35e0Sssszwic io.perfInfo.hit_0_hit_1 := s2_fixed_port_hit(0) && s2_fixed_port_hit(1) && s2_double_line 744a61a35e0Sssszwic io.perfInfo.hit_0_miss_1 := s2_fixed_port_hit(0) && !s2_fixed_port_hit(1) && s2_double_line 745a61a35e0Sssszwic io.perfInfo.miss_0_hit_1 := !s2_fixed_port_hit(0) && s2_fixed_port_hit(1) && s2_double_line 746a61a35e0Sssszwic io.perfInfo.miss_0_miss_1 := !s2_fixed_port_hit(0) && !s2_fixed_port_hit(1) && s2_double_line 747a61a35e0Sssszwic io.perfInfo.hit_0_except_1 := s2_fixed_port_hit(0) && (s2_except_tlb(1) || s2_except_pmp_af(1)) && s2_double_line 748a61a35e0Sssszwic io.perfInfo.miss_0_except_1 := !s2_fixed_port_hit(0) && (s2_except_tlb(1) || s2_except_pmp_af(1)) && s2_double_line 749a61a35e0Sssszwic io.perfInfo.bank_hit(0) := s2_fixed_port_hit(0) 750a61a35e0Sssszwic io.perfInfo.bank_hit(1) := s2_fixed_port_hit(1) && s2_double_line 751a61a35e0Sssszwic io.perfInfo.except_0 := s2_except_tlb(0) || s2_except_pmp_af(0) 752a61a35e0Sssszwic io.perfInfo.hit := !s2_port_miss(0) && !s2_port_miss(1) 75358dbdfc2SJay 75458dbdfc2SJay /** <PERF> fetch bubble generated by icache miss*/ 75500240ba6SJay XSPerfAccumulate("icache_bubble_s2_miss", s2_valid && !s2_fetch_finish ) 756a61a35e0Sssszwic XSPerfAccumulate("icache_bubble_s0_tlb_miss", s1_valid && !tlbRespAllValid) 75758dbdfc2SJay 758a61a35e0Sssszwic /** 759a61a35e0Sssszwic ****************************************************************************** 760a61a35e0Sssszwic * difftest refill check 761a61a35e0Sssszwic ****************************************************************************** 762a61a35e0Sssszwic */ 763afa866b1Sguohongyu if (env.EnableDifftest) { 764afa866b1Sguohongyu val discards = (0 until PortNumber).map { i => 765*b436d3b6Speixiaokun val discard = toIFU(i).bits.tlbExcp.pageFault || toIFU(i).bits.tlbExcp.guestPageFault || toIFU(i).bits.tlbExcp.accessFault || toIFU(i).bits.tlbExcp.mmio 766afa866b1Sguohongyu discard 767afa866b1Sguohongyu } 768afa866b1Sguohongyu (0 until PortNumber).map { i => 769a0c65233SYinan Xu val diffMainPipeOut = DifftestModule(new DiffRefillEvent, dontCare = true) 7707d45a146SYinan Xu diffMainPipeOut.coreid := io.hartId 7717d45a146SYinan Xu diffMainPipeOut.index := (4 + i).U 772a61a35e0Sssszwic if (i == 0) { 773a61a35e0Sssszwic diffMainPipeOut.valid := s2_fire && !discards(0) 774a61a35e0Sssszwic diffMainPipeOut.addr := s2_req_paddr(0) 775a61a35e0Sssszwic } else { 776a61a35e0Sssszwic diffMainPipeOut.valid := s2_fire && !discards(0) && (!s2_double_line || (s2_double_line && !discards(1))) 777a61a35e0Sssszwic diffMainPipeOut.addr := s2_req_paddr(0) + (blockBits/2).U 778afa866b1Sguohongyu } 779a61a35e0Sssszwic diffMainPipeOut.data := Cat(0.U((blockBits/2).W), toIFU(i).bits.data).asTypeOf(diffMainPipeOut.data) 780a61a35e0Sssszwic // idtfr: 0 -> data from icache 1 -> reversedData 2 -> data from missUnit 781a61a35e0Sssszwic diffMainPipeOut.idtfr := Mux(s2_port_hit(i), 0.U, Mux(s2_fixed_port_hit(i), 1.U, 2.U)) 782afa866b1Sguohongyu diffMainPipeOut 783afa866b1Sguohongyu } 784afa866b1Sguohongyu } 7851d8f4dcbSJay} 786