2021-06-04 09:06:35 +08:00
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright ( c ) 2020 - 2021 Institute of Computing Technology , Chinese Academy of Sciences
2021-07-24 23:26:38 +08:00
* Copyright ( c ) 2020 - 2021 Peng Cheng Laboratory
2021-06-04 09:06:35 +08:00
*
* XiangShan is licensed under Mulan PSL v2 .
* You can use this software according to the terms and conditions of the Mulan PSL v2 .
* You may obtain a copy of Mulan PSL v2 at :
* http : //license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS , WITHOUT WARRANTIES OF ANY KIND ,
* EITHER EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED TO NON - INFRINGEMENT ,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE .
*
* See the Mulan PSL v2 for more details .
***************************************************************************************/
2020-08-06 16:58:13 +08:00
package xiangshan.mem
2021-04-19 21:19:20 +08:00
import chipsalliance.rocketchip.config.Parameters
2020-08-06 16:58:13 +08:00
import chisel3._
import chisel3.util._
import utils._
import xiangshan._
2021-01-14 11:33:49 +08:00
import xiangshan.backend.decode.ImmUnion
2020-10-25 13:24:10 +08:00
import xiangshan.cache._
2021-08-23 19:33:09 +08:00
import xiangshan.cache.mmu. { TlbRequestIO , TlbReq , TlbResp , TlbCmd }
2020-08-06 16:58:13 +08:00
2021-04-19 21:19:20 +08:00
class LoadToLsqIO ( implicit p : Parameters ) extends XSBundle {
2020-08-06 16:58:13 +08:00
val loadIn = ValidIO ( new LsPipelineBundle )
val ldout = Flipped ( DecoupledIO ( new ExuOutput ) )
2021-01-25 19:46:19 +08:00
val loadDataForwarded = Output ( Bool ( ) )
2021-02-05 23:10:00 +08:00
val needReplayFromRS = Output ( Bool ( ) )
2021-04-30 10:40:51 +08:00
val forward = new PipeLoadForwardQueryIO
2020-08-06 16:58:13 +08:00
}
2020-10-17 21:05:46 +08:00
// Load Pipeline Stage 0
// Generate addr, use addr to query DCache and DTLB
2021-04-19 21:19:20 +08:00
class LoadUnit_S0 ( implicit p : Parameters ) extends XSModule {
2020-08-06 16:58:13 +08:00
val io = IO ( new Bundle ( ) {
2020-10-17 21:05:46 +08:00
val in = Flipped ( Decoupled ( new ExuInput ) )
val out = Decoupled ( new LsPipelineBundle )
2020-11-07 17:40:20 +08:00
val dtlbReq = DecoupledIO ( new TlbReq )
2021-01-08 17:17:13 +08:00
val dcacheReq = DecoupledIO ( new DCacheWordReq )
2021-01-30 17:31:42 +08:00
val rsIdx = Input ( UInt ( log2Up ( IssQueSize ) . W ) )
2021-03-13 08:49:36 +08:00
val isFirstIssue = Input ( Bool ( ) )
2020-08-06 16:58:13 +08:00
} )
2020-10-17 21:05:46 +08:00
val s0_uop = io . in . bits . uop
2021-05-09 09:05:53 +08:00
// val s0_vaddr = io.in.bits.src(0) + SignExt(s0_uop.ctrl.imm(11,0), VAddrBits)
2021-02-03 18:13:46 +08:00
// val s0_mask = genWmask(s0_vaddr, s0_uop.ctrl.fuOpType(1,0))
2021-01-26 14:05:21 +08:00
val imm12 = WireInit ( s0_uop . ctrl . imm ( 11 , 0 ) )
2021-05-09 09:05:53 +08:00
val s0_vaddr_lo = io . in . bits . src ( 0 ) ( 11 , 0 ) + Cat ( 0. U ( 1. W ) , imm12 )
2021-03-05 20:23:11 +08:00
val s0_vaddr_hi = Mux ( s0_vaddr_lo ( 12 ) ,
2021-05-09 09:05:53 +08:00
Mux ( imm12 ( 11 ) , io . in . bits . src ( 0 ) ( VAddrBits - 1 , 12 ) , io . in . bits . src ( 0 ) ( VAddrBits - 1 , 12 ) + 1. U ) ,
Mux ( imm12 ( 11 ) , io . in . bits . src ( 0 ) ( VAddrBits - 1 , 12 ) + SignExt ( 1. U , VAddrBits - 12 ) , io . in . bits . src ( 0 ) ( VAddrBits - 1 , 12 ) ) ,
2021-01-26 14:05:21 +08:00
)
val s0_vaddr = Cat ( s0_vaddr_hi , s0_vaddr_lo ( 11 , 0 ) )
val s0_mask = genWmask ( s0_vaddr_lo , s0_uop . ctrl . fuOpType ( 1 , 0 ) )
2020-10-17 21:05:46 +08:00
// query DTLB
2020-12-11 19:59:25 +08:00
io . dtlbReq . valid : = io . in . valid
2020-10-25 13:24:10 +08:00
io . dtlbReq . bits . vaddr : = s0_vaddr
io . dtlbReq . bits . cmd : = TlbCmd . read
io . dtlbReq . bits . roqIdx : = s0_uop . roqIdx
io . dtlbReq . bits . debug . pc : = s0_uop . cf . pc
2021-03-13 08:49:36 +08:00
io . dtlbReq . bits . debug . isFirstIssue : = io . isFirstIssue
2020-10-17 21:05:46 +08:00
// query DCache
2020-12-11 19:59:25 +08:00
io . dcacheReq . valid : = io . in . valid
2020-10-25 13:24:10 +08:00
io . dcacheReq . bits . cmd : = MemoryOpConstants . M_XRD
io . dcacheReq . bits . addr : = s0_vaddr
io . dcacheReq . bits . mask : = s0_mask
2020-10-26 12:11:38 +08:00
io . dcacheReq . bits . data : = DontCare
// TODO: update cache meta
2021-01-24 10:18:49 +08:00
io . dcacheReq . bits . id : = DontCare
2020-10-17 21:05:46 +08:00
val addrAligned = LookupTree ( s0_uop . ctrl . fuOpType ( 1 , 0 ) , List (
"b00" . U -> true . B , //b
"b01" . U -> ( s0_vaddr ( 0 ) === 0. U ) , //h
"b10" . U -> ( s0_vaddr ( 1 , 0 ) === 0. U ) , //w
"b11" . U -> ( s0_vaddr ( 2 , 0 ) === 0. U ) //d
2020-09-03 23:49:29 +08:00
) )
2020-10-17 21:05:46 +08:00
2020-12-14 11:59:11 +08:00
io . out . valid : = io . in . valid && io . dcacheReq . ready
2020-12-11 19:59:25 +08:00
2020-10-17 21:05:46 +08:00
io . out . bits : = DontCare
io . out . bits . vaddr : = s0_vaddr
io . out . bits . mask : = s0_mask
io . out . bits . uop : = s0_uop
io . out . bits . uop . cf . exceptionVec ( loadAddrMisaligned ) : = ! addrAligned
2021-01-30 17:31:42 +08:00
io . out . bits . rsIdx : = io . rsIdx
2020-10-17 21:05:46 +08:00
2020-12-11 19:59:25 +08:00
io . in . ready : = ! io . in . valid || ( io . out . ready && io . dcacheReq . ready )
2020-10-27 18:11:11 +08:00
2020-12-11 19:59:25 +08:00
XSDebug ( io . dcacheReq . fire ( ) ,
2020-12-13 21:31:00 +08:00
p "[DCACHE LOAD REQ] pc ${Hexadecimal(s0_uop.cf.pc)}, vaddr ${Hexadecimal(s0_vaddr)}\n"
2020-10-27 18:11:11 +08:00
)
2021-03-25 21:08:52 +08:00
XSPerfAccumulate ( "in" , io . in . valid )
XSPerfAccumulate ( "stall_out" , io . out . valid && ! io . out . ready && io . dcacheReq . ready )
XSPerfAccumulate ( "stall_dcache" , io . out . valid && io . out . ready && ! io . dcacheReq . ready )
2021-05-09 09:05:53 +08:00
XSPerfAccumulate ( "addr_spec_success" , io . out . fire ( ) && s0_vaddr ( VAddrBits - 1 , 12 ) === io . in . bits . src ( 0 ) ( VAddrBits - 1 , 12 ) )
XSPerfAccumulate ( "addr_spec_failed" , io . out . fire ( ) && s0_vaddr ( VAddrBits - 1 , 12 ) =/= io . in . bits . src ( 0 ) ( VAddrBits - 1 , 12 ) )
XSPerfAccumulate ( "addr_spec_success_once" , io . out . fire ( ) && s0_vaddr ( VAddrBits - 1 , 12 ) === io . in . bits . src ( 0 ) ( VAddrBits - 1 , 12 ) && io . isFirstIssue )
XSPerfAccumulate ( "addr_spec_failed_once" , io . out . fire ( ) && s0_vaddr ( VAddrBits - 1 , 12 ) =/= io . in . bits . src ( 0 ) ( VAddrBits - 1 , 12 ) && io . isFirstIssue )
2020-10-17 21:05:46 +08:00
}
// Load Pipeline Stage 1
// TLB resp (send paddr to dcache)
2021-04-19 21:19:20 +08:00
class LoadUnit_S1 ( implicit p : Parameters ) extends XSModule {
2020-10-17 21:05:46 +08:00
val io = IO ( new Bundle ( ) {
val in = Flipped ( Decoupled ( new LsPipelineBundle ) )
val out = Decoupled ( new LsPipelineBundle )
2020-12-13 21:31:00 +08:00
val dtlbResp = Flipped ( DecoupledIO ( new TlbResp ) )
val dcachePAddr = Output ( UInt ( PAddrBits . W ) )
2021-01-08 20:49:30 +08:00
val dcacheKill = Output ( Bool ( ) )
2020-11-02 19:23:04 +08:00
val sbuffer = new LoadForwardQueryIO
2021-04-30 10:40:51 +08:00
val lsq = new PipeLoadForwardQueryIO
2020-08-06 16:58:13 +08:00
} )
2020-08-16 15:59:15 +08:00
2020-10-17 21:05:46 +08:00
val s1_uop = io . in . bits . uop
2020-12-13 21:31:00 +08:00
val s1_paddr = io . dtlbResp . bits . paddr
2021-01-14 16:18:29 +08:00
val s1_exception = selectLoad ( io . out . bits . uop . cf . exceptionVec , false ) . asUInt . orR
2020-12-13 21:31:00 +08:00
val s1_tlb_miss = io . dtlbResp . bits . miss
2021-01-16 21:24:32 +08:00
val s1_mmio = ! s1_tlb_miss && io . dtlbResp . bits . mmio
2020-11-02 19:23:04 +08:00
val s1_mask = io . in . bits . mask
2020-11-18 20:47:14 +08:00
2020-11-02 19:23:04 +08:00
io . out . bits : = io . in . bits // forwardXX field will be updated in s1
2020-12-13 21:31:00 +08:00
io . dtlbResp . ready : = true . B
2021-01-10 12:20:47 +08:00
// TOOD: PMA check
2020-12-13 21:31:00 +08:00
io . dcachePAddr : = s1_paddr
2021-01-10 12:20:47 +08:00
io . dcacheKill : = s1_tlb_miss || s1_exception || s1_mmio
2020-10-21 10:40:51 +08:00
2020-11-02 19:23:04 +08:00
// load forward query datapath
io . sbuffer . valid : = io . in . valid
io . sbuffer . paddr : = s1_paddr
io . sbuffer . uop : = s1_uop
io . sbuffer . sqIdx : = s1_uop . sqIdx
io . sbuffer . mask : = s1_mask
io . sbuffer . pc : = s1_uop . cf . pc // FIXME: remove it
2020-11-18 20:47:14 +08:00
io . lsq . valid : = io . in . valid
io . lsq . paddr : = s1_paddr
io . lsq . uop : = s1_uop
io . lsq . sqIdx : = s1_uop . sqIdx
2021-02-02 00:17:52 +08:00
io . lsq . sqIdxMask : = DontCare // will be overwritten by sqIdxMask pre-generated in s0
2020-11-18 20:47:14 +08:00
io . lsq . mask : = s1_mask
io . lsq . pc : = s1_uop . cf . pc // FIXME: remove it
2020-11-02 19:23:04 +08:00
2021-01-08 20:49:30 +08:00
io . out . valid : = io . in . valid // && !s1_tlb_miss
2020-10-17 21:05:46 +08:00
io . out . bits . paddr : = s1_paddr
2021-01-10 12:20:47 +08:00
io . out . bits . mmio : = s1_mmio && ! s1_exception
2020-10-26 12:11:38 +08:00
io . out . bits . tlbMiss : = s1_tlb_miss
2020-12-13 21:31:00 +08:00
io . out . bits . uop . cf . exceptionVec ( loadPageFault ) : = io . dtlbResp . bits . excp . pf . ld
2021-01-16 21:24:32 +08:00
io . out . bits . uop . cf . exceptionVec ( loadAccessFault ) : = io . dtlbResp . bits . excp . af . ld
2021-03-05 20:23:11 +08:00
io . out . bits . ptwBack : = io . dtlbResp . bits . ptwBack
2021-01-30 17:31:42 +08:00
io . out . bits . rsIdx : = io . in . bits . rsIdx
2020-08-06 16:58:13 +08:00
2020-12-11 19:59:25 +08:00
io . in . ready : = ! io . in . valid || io . out . ready
2020-08-19 15:28:58 +08:00
2021-03-25 21:08:52 +08:00
XSPerfAccumulate ( "in" , io . in . valid )
XSPerfAccumulate ( "tlb_miss" , io . in . valid && s1_tlb_miss )
XSPerfAccumulate ( "stall_out" , io . out . valid && ! io . out . ready )
2020-10-17 21:05:46 +08:00
}
2020-08-19 15:28:58 +08:00
2020-10-17 21:05:46 +08:00
// Load Pipeline Stage 2
// DCache resp
2021-04-19 21:19:20 +08:00
class LoadUnit_S2 ( implicit p : Parameters ) extends XSModule with HasLoadHelper {
2020-10-17 21:05:46 +08:00
val io = IO ( new Bundle ( ) {
val in = Flipped ( Decoupled ( new LsPipelineBundle ) )
val out = Decoupled ( new LsPipelineBundle )
2021-04-30 10:40:51 +08:00
val rsFeedback = ValidIO ( new RSFeedback )
2020-10-25 13:24:10 +08:00
val dcacheResp = Flipped ( DecoupledIO ( new DCacheWordResp ) )
2020-12-02 18:16:42 +08:00
val lsq = new LoadForwardQueryIO
2020-12-16 14:44:10 +08:00
val sbuffer = new LoadForwardQueryIO
2021-01-25 19:46:19 +08:00
val dataForwarded = Output ( Bool ( ) )
2021-02-05 23:10:00 +08:00
val needReplayFromRS = Output ( Bool ( ) )
2020-10-17 21:05:46 +08:00
} )
2020-08-18 17:17:24 +08:00
2020-10-17 21:05:46 +08:00
val s2_uop = io . in . bits . uop
val s2_mask = io . in . bits . mask
val s2_paddr = io . in . bits . paddr
2021-01-08 20:49:30 +08:00
val s2_tlb_miss = io . in . bits . tlbMiss
2021-04-30 10:40:51 +08:00
val s2_data_invalid = io . lsq . dataInvalid
2021-01-14 16:18:29 +08:00
val s2_exception = selectLoad ( io . in . bits . uop . cf . exceptionVec , false ) . asUInt . orR
2021-01-31 09:54:39 +08:00
val s2_mmio = io . in . bits . mmio && ! s2_exception
2020-10-25 13:24:10 +08:00
val s2_cache_miss = io . dcacheResp . bits . miss
2021-01-08 17:17:13 +08:00
val s2_cache_replay = io . dcacheResp . bits . replay
2020-08-06 16:58:13 +08:00
2020-10-25 13:24:10 +08:00
io . dcacheResp . ready : = true . B
2021-01-10 12:20:47 +08:00
val dcacheShouldResp = ! ( s2_tlb_miss || s2_exception || s2_mmio )
assert ( ! ( io . in . valid && dcacheShouldResp && ! io . dcacheResp . valid ) , "DCache response got lost" )
2020-08-06 16:58:13 +08:00
2021-01-08 20:49:30 +08:00
// feedback tlb result to RS
2021-04-30 10:40:51 +08:00
io . rsFeedback . valid : = io . in . valid
io . rsFeedback . bits . hit : = ! s2_tlb_miss && ( ! s2_cache_replay || s2_mmio || s2_exception ) && ! s2_data_invalid
io . rsFeedback . bits . rsIdx : = io . in . bits . rsIdx
io . rsFeedback . bits . flushState : = io . in . bits . ptwBack
2021-07-19 11:36:58 +08:00
io . rsFeedback . bits . sourceType : = Mux ( s2_tlb_miss , RSFeedbackType . tlbMiss ,
2021-04-30 10:40:51 +08:00
Mux ( io . lsq . dataInvalid ,
RSFeedbackType . dataInvalid ,
RSFeedbackType . mshrFull
)
)
2021-07-19 11:36:58 +08:00
// s2_cache_replay is quite slow to generate, send it separately to LQ
2021-02-05 23:10:00 +08:00
io . needReplayFromRS : = s2_cache_replay
2021-01-08 20:49:30 +08:00
2021-02-01 23:59:58 +08:00
// merge forward result
// lsq has higher priority than sbuffer
val forwardMask = Wire ( Vec ( 8 , Bool ( ) ) )
val forwardData = Wire ( Vec ( 8 , UInt ( 8. W ) ) )
2021-01-08 20:49:30 +08:00
2021-04-30 10:40:51 +08:00
val fullForward = ( ~ forwardMask . asUInt & s2_mask ) === 0. U && ! io . lsq . dataInvalid
2021-02-01 23:59:58 +08:00
io . lsq : = DontCare
io . sbuffer : = DontCare
// generate XLEN/8 Muxs
for ( i <- 0 until XLEN / 8 ) {
forwardMask ( i ) : = io . lsq . forwardMask ( i ) || io . sbuffer . forwardMask ( i )
forwardData ( i ) : = Mux ( io . lsq . forwardMask ( i ) , io . lsq . forwardData ( i ) , io . sbuffer . forwardData ( i ) )
}
2020-08-06 16:58:13 +08:00
2020-12-02 18:16:42 +08:00
XSDebug ( io . out . fire ( ) , "[FWD LOAD RESP] pc %x fwd %x(%b) + %x(%b)\n" ,
s2_uop . cf . pc ,
io . lsq . forwardData . asUInt , io . lsq . forwardMask . asUInt ,
io . in . bits . forwardData . asUInt , io . in . bits . forwardMask . asUInt
)
2020-08-06 16:58:13 +08:00
// data merge
2021-02-01 23:59:58 +08:00
val rdataVec = VecInit ( ( 0 until XLEN / 8 ) . map ( j =>
Mux ( forwardMask ( j ) , forwardData ( j ) , io . dcacheResp . bits . data ( 8 * ( j + 1 ) - 1 , 8 * j ) ) ) )
val rdata = rdataVec . asUInt
2020-10-17 21:05:46 +08:00
val rdataSel = LookupTree ( s2_paddr ( 2 , 0 ) , List (
2020-08-06 16:58:13 +08:00
"b000" . U -> rdata ( 63 , 0 ) ,
"b001" . U -> rdata ( 63 , 8 ) ,
"b010" . U -> rdata ( 63 , 16 ) ,
"b011" . U -> rdata ( 63 , 24 ) ,
"b100" . U -> rdata ( 63 , 32 ) ,
"b101" . U -> rdata ( 63 , 40 ) ,
"b110" . U -> rdata ( 63 , 48 ) ,
"b111" . U -> rdata ( 63 , 56 )
) )
2020-12-12 23:48:12 +08:00
val rdataPartialLoad = rdataHelper ( s2_uop , rdataSel )
2020-08-06 16:58:13 +08:00
2021-04-30 10:40:51 +08:00
io . out . valid : = io . in . valid && ! s2_tlb_miss && ! s2_data_invalid
2020-11-18 20:47:14 +08:00
// Inst will be canceled in store queue / lsq,
2020-10-26 14:36:09 +08:00
// so we do not need to care about flush in load / store unit's out.valid
2020-10-17 21:05:46 +08:00
io . out . bits : = io . in . bits
io . out . bits . data : = rdataPartialLoad
2021-01-15 22:24:39 +08:00
// when exception occurs, set it to not miss and let it write back to roq (via int port)
2021-01-25 19:46:19 +08:00
io . out . bits . miss : = s2_cache_miss && ! s2_exception
2021-01-15 22:24:39 +08:00
io . out . bits . uop . ctrl . fpWen : = io . in . bits . uop . ctrl . fpWen && ! s2_exception
2021-01-11 22:00:04 +08:00
io . out . bits . mmio : = s2_mmio
2020-10-17 21:05:46 +08:00
2021-01-25 19:46:19 +08:00
// For timing reasons, we can not let
// io.out.bits.miss := s2_cache_miss && !s2_exception && !fullForward
// We use io.dataForwarded instead. It means forward logic have prepared all data needed,
// and dcache query is no longer needed.
// Such inst will be writebacked from load queue.
io . dataForwarded : = s2_cache_miss && fullForward && ! s2_exception
2021-02-01 23:59:58 +08:00
// io.out.bits.forwardX will be send to lq
2021-03-05 20:23:11 +08:00
io . out . bits . forwardMask : = forwardMask
2021-02-01 23:59:58 +08:00
// data retbrived from dcache is also included in io.out.bits.forwardData
io . out . bits . forwardData : = rdataVec
2021-01-25 19:46:19 +08:00
2020-10-17 21:05:46 +08:00
io . in . ready : = io . out . ready || ! io . in . valid
2020-11-18 20:47:14 +08:00
XSDebug ( io . out . fire ( ) , "[DCACHE LOAD RESP] pc %x rdata %x <- D$ %x + fwd %x(%b)\n" ,
2020-10-26 19:48:20 +08:00
s2_uop . cf . pc , rdataPartialLoad , io . dcacheResp . bits . data ,
2021-02-01 23:59:58 +08:00
forwardData . asUInt , forwardMask . asUInt
2020-08-06 16:58:13 +08:00
)
2021-03-08 22:31:59 +08:00
2021-03-25 21:08:52 +08:00
XSPerfAccumulate ( "in" , io . in . valid )
XSPerfAccumulate ( "dcache_miss" , io . in . valid && s2_cache_miss )
XSPerfAccumulate ( "full_forward" , io . in . valid && fullForward )
XSPerfAccumulate ( "dcache_miss_full_forward" , io . in . valid && s2_cache_miss && fullForward )
2021-04-30 10:40:51 +08:00
XSPerfAccumulate ( "replay" , io . rsFeedback . valid && ! io . rsFeedback . bits . hit )
XSPerfAccumulate ( "replay_tlb_miss" , io . rsFeedback . valid && ! io . rsFeedback . bits . hit && s2_tlb_miss )
XSPerfAccumulate ( "replay_cache" , io . rsFeedback . valid && ! io . rsFeedback . bits . hit && ! s2_tlb_miss && s2_cache_replay )
2021-03-25 21:08:52 +08:00
XSPerfAccumulate ( "stall_out" , io . out . valid && ! io . out . ready )
2020-10-17 21:05:46 +08:00
}
2020-08-06 16:58:13 +08:00
2021-04-19 21:19:20 +08:00
class LoadUnit ( implicit p : Parameters ) extends XSModule with HasLoadHelper {
2020-10-17 21:05:46 +08:00
val io = IO ( new Bundle ( ) {
val ldin = Flipped ( Decoupled ( new ExuInput ) )
val ldout = Decoupled ( new ExuOutput )
val redirect = Flipped ( ValidIO ( new Redirect ) )
2021-01-25 12:57:38 +08:00
val flush = Input ( Bool ( ) )
2021-04-30 10:40:51 +08:00
val rsFeedback = ValidIO ( new RSFeedback )
2021-01-30 17:31:42 +08:00
val rsIdx = Input ( UInt ( log2Up ( IssQueSize ) . W ) )
2021-03-13 08:49:36 +08:00
val isFirstIssue = Input ( Bool ( ) )
2020-10-25 13:24:10 +08:00
val dcache = new DCacheLoadIO
2021-08-23 19:33:09 +08:00
val dtlb = new TlbRequestIO ( )
2020-10-17 21:05:46 +08:00
val sbuffer = new LoadForwardQueryIO
2020-11-18 20:47:14 +08:00
val lsq = new LoadToLsqIO
2021-08-04 09:07:05 +08:00
val fastUop = ValidIO ( new MicroOp ) // early wakeup signal generated in load_s1
2020-10-17 21:05:46 +08:00
} )
val load_s0 = Module ( new LoadUnit_S0 )
val load_s1 = Module ( new LoadUnit_S1 )
val load_s2 = Module ( new LoadUnit_S2 )
load_s0 . io . in <> io . ldin
2021-08-23 19:33:09 +08:00
load_s0 . io . dtlbReq <> io . dtlb . req
2020-10-25 13:24:10 +08:00
load_s0 . io . dcacheReq <> io . dcache . req
2021-01-30 17:31:42 +08:00
load_s0 . io . rsIdx : = io . rsIdx
2021-03-13 08:49:36 +08:00
load_s0 . io . isFirstIssue : = io . isFirstIssue
2020-10-17 21:05:46 +08:00
2021-01-25 12:57:38 +08:00
PipelineConnect ( load_s0 . io . out , load_s1 . io . in , true . B , load_s0 . io . out . bits . uop . roqIdx . needFlush ( io . redirect , io . flush ) )
2020-10-17 21:05:46 +08:00
2021-08-23 19:33:09 +08:00
load_s1 . io . dtlbResp <> io . dtlb . resp
2020-12-13 21:31:00 +08:00
io . dcache . s1_paddr <> load_s1 . io . dcachePAddr
2021-01-08 20:49:30 +08:00
io . dcache . s1_kill <> load_s1 . io . dcacheKill
2020-12-11 19:59:25 +08:00
load_s1 . io . sbuffer <> io . sbuffer
load_s1 . io . lsq <> io . lsq . forward
2020-10-17 21:05:46 +08:00
2021-01-25 12:57:38 +08:00
PipelineConnect ( load_s1 . io . out , load_s2 . io . in , true . B , load_s1 . io . out . bits . uop . roqIdx . needFlush ( io . redirect , io . flush ) )
2020-10-17 21:05:46 +08:00
2020-10-25 13:24:10 +08:00
load_s2 . io . dcacheResp <> io . dcache . resp
2020-12-13 21:31:00 +08:00
load_s2 . io . lsq . forwardData <> io . lsq . forward . forwardData
load_s2 . io . lsq . forwardMask <> io . lsq . forward . forwardMask
2021-04-30 10:40:51 +08:00
load_s2 . io . lsq . dataInvalid <> io . lsq . forward . dataInvalid
2020-12-16 14:44:10 +08:00
load_s2 . io . sbuffer . forwardData <> io . sbuffer . forwardData
load_s2 . io . sbuffer . forwardMask <> io . sbuffer . forwardMask
2021-04-30 10:40:51 +08:00
load_s2 . io . sbuffer . dataInvalid <> io . sbuffer . dataInvalid // always false
2021-01-25 19:46:19 +08:00
load_s2 . io . dataForwarded <> io . lsq . loadDataForwarded
2021-04-30 10:40:51 +08:00
io . rsFeedback . bits : = RegNext ( load_s2 . io . rsFeedback . bits )
io . rsFeedback . valid : = RegNext ( load_s2 . io . rsFeedback . valid && ! load_s2 . io . out . bits . uop . roqIdx . needFlush ( io . redirect , io . flush ) )
2021-02-08 20:48:27 +08:00
io . lsq . needReplayFromRS : = load_s2 . io . needReplayFromRS
2020-10-17 21:05:46 +08:00
2021-02-02 00:17:52 +08:00
// pre-calcuate sqIdx mask in s0, then send it to lsq in s1 for forwarding
val sqIdxMaskReg = RegNext ( UIntToMask ( load_s0 . io . in . bits . uop . sqIdx . value , StoreQueueSize ) )
io . lsq . forward . sqIdxMask : = sqIdxMaskReg
2020-10-17 21:05:46 +08:00
2021-03-10 08:26:40 +08:00
// // use s2_hit_way to select data received in s1
// load_s2.io.dcacheResp.bits.data := Mux1H(RegNext(io.dcache.s1_hit_way), RegNext(io.dcache.s1_data))
// assert(load_s2.io.dcacheResp.bits.data === io.dcache.resp.bits.data)
2021-07-19 11:36:58 +08:00
io . fastUop . valid : = io . dcache . s1_hit_way . orR && ! io . dcache . s1_disable_fast_wakeup && load_s1 . io . in . valid &&
2021-04-30 10:40:51 +08:00
! load_s1 . io . dcacheKill && ! io . lsq . forward . dataInvalidFast
2021-03-10 08:26:40 +08:00
io . fastUop . bits : = load_s1 . io . out . bits . uop
2020-10-17 21:05:46 +08:00
XSDebug ( load_s0 . io . out . valid ,
2020-10-31 23:12:13 +08:00
p "S0: pc ${Hexadecimal(load_s0.io.out.bits.uop.cf.pc)}, lId ${Hexadecimal(load_s0.io.out.bits.uop.lqIdx.asUInt)}, " +
2020-10-17 21:05:46 +08:00
p "vaddr ${Hexadecimal(load_s0.io.out.bits.vaddr)}, mask ${Hexadecimal(load_s0.io.out.bits.mask)}\n" )
2020-11-18 20:47:14 +08:00
XSDebug ( load_s1 . io . out . valid ,
2021-08-23 19:33:09 +08:00
p "S1: pc ${Hexadecimal(load_s1.io.out.bits.uop.cf.pc)}, lId ${Hexadecimal(load_s1.io.out.bits.uop.lqIdx.asUInt)}, tlb_miss ${io.dtlb.resp.bits.miss}, " +
2020-10-26 17:31:38 +08:00
p "paddr ${Hexadecimal(load_s1.io.out.bits.paddr)}, mmio ${load_s1.io.out.bits.mmio}\n" )
2020-08-06 16:58:13 +08:00
2020-11-18 20:47:14 +08:00
// writeback to LSQ
2020-08-06 16:58:13 +08:00
// Current dcache use MSHR
2021-01-06 01:09:22 +08:00
// Load queue will be updated at s2 for both hit/miss int/fp load
2020-11-18 20:47:14 +08:00
io . lsq . loadIn . valid : = load_s2 . io . out . valid
io . lsq . loadIn . bits : = load_s2 . io . out . bits
2021-01-15 22:24:39 +08:00
// write to rob and writeback bus
2021-04-24 09:22:59 +08:00
val s2_wb_valid = load_s2 . io . out . valid && ! load_s2 . io . out . bits . miss && ! load_s2 . io . out . bits . mmio
2020-08-06 16:58:13 +08:00
2021-01-06 01:09:22 +08:00
// Int load, if hit, will be writebacked at s2
2021-02-19 22:41:55 +08:00
val hitLoadOut = Wire ( Valid ( new ExuOutput ) )
hitLoadOut . valid : = s2_wb_valid
hitLoadOut . bits . uop : = load_s2 . io . out . bits . uop
hitLoadOut . bits . data : = load_s2 . io . out . bits . data
hitLoadOut . bits . redirectValid : = false . B
hitLoadOut . bits . redirect : = DontCare
hitLoadOut . bits . debug . isMMIO : = load_s2 . io . out . bits . mmio
hitLoadOut . bits . debug . isPerfCnt : = false . B
hitLoadOut . bits . debug . paddr : = load_s2 . io . out . bits . paddr
hitLoadOut . bits . fflags : = DontCare
2020-08-06 16:58:13 +08:00
2020-10-17 21:05:46 +08:00
load_s2 . io . out . ready : = true . B
2021-01-06 01:09:22 +08:00
2021-02-19 22:41:55 +08:00
io . ldout . bits : = Mux ( hitLoadOut . valid , hitLoadOut . bits , io . lsq . ldout . bits )
io . ldout . valid : = hitLoadOut . valid || io . lsq . ldout . valid
2021-01-14 16:18:29 +08:00
2021-02-19 22:41:55 +08:00
io . lsq . ldout . ready : = ! hitLoadOut . valid
2020-08-16 15:59:15 +08:00
2020-08-20 22:46:53 +08:00
when ( io . ldout . fire ( ) ) {
2021-01-06 01:09:22 +08:00
XSDebug ( "ldout %x\n" , io . ldout . bits . uop . cf . pc )
}
2021-01-08 17:17:13 +08:00
}