xref: /XiangShan/src/main/scala/xiangshan/frontend/IFU.scala (revision 5f1f5d4d7aac0bbdecf6d07f9a7480a5aa269310)
1package xiangshan.frontend
2
3import chisel3._
4import chisel3.util._
5import chisel3.core.{withReset}
6import device.RAMHelper
7import xiangshan._
8
9trait HasIFUConst { this: XSModule =>
10  val resetVector = 0x80000000L//TODO: set reset vec
11
12  val groupAlign = log2Up(FetchWidth * 4)
13  def groupPC(pc: UInt): UInt = Cat(pc(VAddrBits-1, groupAlign), 0.U(groupAlign.W))
14
15}
16
17sealed abstract IFUBundle extends XSBundle with HasIFUConst
18sealed abstract IFUModule extends XSModule with HasIFUConst with NeedImpl
19
20
21
22class IFUIO extends IFUBundle
23{
24    val fetchPacket = DecoupledIO(new FetchPacket)
25    val redirect = Flipped(ValidIO(new Redirect))
26    val icacheReq = DecoupledIO(UInt(VAddrBits.W)
27    val icacheResp = Flipped(DecoupledIO(new FakeIcacheResp))
28}
29
30
31
32class IFU(implicit val p: XSConfig) extends IFUModule
33{
34    val io = IO(new IFUIO)
35    val bpu = Module(new BPU)
36
37    //-------------------------
38    //      IF1  PC update
39    //-------------------------
40    //local
41    val if1_npc = WireInit(0.U(VAddrBits.W))
42    val if1_valid = WireInit(false.B)
43    val if1_pc = RegInit(resetVector.U(VAddrBits.W))
44    //next
45    val if2_ready = WireInit(false.B)
46    val if1_ready = bpu.io.in.ready &&  if2_ready
47
48    //pipe fire
49    val if1_fire = if1_valid && if1_ready
50    val if1_pcUpdate = io.redirect.valid || if1_fire
51
52    when(RegNext(reset.asBool) && !reset.asBool)
53    {
54      if1_npc := resetVector
55      if1_valid := true.B
56    }
57
58    when(if1_pcUpdate)
59    {
60      if1_pc := if1_npc
61    }
62
63    bpu.io.in.valid := if1_valid
64    bpu.io.in.pc := if1_npc
65
66    //-------------------------
67    //      IF2  btb resonse
68    //           icache visit
69    //-------------------------
70    //local
71    val if2_flush = WireInit(false.B)
72    val if2_update = if1_fire && !if2_flush
73    val if2_valid = RegNext(if2_update)
74    val if2_pc = if1_pc
75    val if2_btb_taken = bpu.io.btbOut.valid
76    val if2_btb_insMask = bpu.io.btbOut.bits.instrValid
77    val if2_btb_target = bpu.io.btbOut.bits.target
78    val if2_snpc = Cat(if2_pc(VAddrBits-1, groupAlign) + 1.U, 0.U(groupAlign.W))
79    val if2_flush = WireInit(false.B)
80
81    //next
82    val if3_ready = WireInit(false.B)
83
84    //pipe fire
85    val if2_fire = if2_valid && if3_ready
86    val if2_ready = (if2_fire && io.icacheReq.fire()) || !if2_valid
87
88    io.icacheReq.valid := if2_fire
89    io.icacheReq.bits := groupPC(if2_pc)
90
91    when(if2_valid && if2_btb_taken)
92    {
93      if1_npc := if2_btb_target
94    } .otherwise
95    {
96      if1_npc := if2_snpc
97    }
98
99    //-------------------------
100    //      IF3  icache hit check
101    //-------------------------
102    //local
103    val if3_flush = WireInit(false.B)
104    val if3_update = if2_fire && !if3_flush
105    val if3_valid = RegNext(if3_update)
106    val if3_pc = RegEnable(if2_pc,if3_update)
107    val if3_btb_target = RegEnable(if2_btb_target,if3_update)
108    val if3_btb_taken = RegEnable(if2_btb_taken,if3_update)
109
110    //next
111    val if4_ready = WireInit(false.B)
112
113    //pipe fire
114    val if3_fire = if3_valid && if4_ready
115    val if3_ready = if3_fire  || !if3_valid
116
117    //-------------------------
118    //      IF4  icache resonse
119    //           RAS result
120    //           taget generate
121    //-------------------------
122    val if4_flush = WireInit(false.B)
123    val if4_update = if3_fire && !if4_flush
124    val if4_valid = RegNext(if4_update)
125    val if4_pc = RegEnable(if3_pc,if4_update)
126    val if4_btb_target = RegEnable(if3_btb_target,if4_update)
127    val if4_btb_taken = RegEnable(if3_btb_taken,if4_update)
128
129
130
131    when(if4_valid && io.icacheResp.fire())
132    {
133      if1_npc := if4_btb_target
134    }
135
136
137    //redirect
138    when(io.redirect.valid){
139      if1_npc := io.redirect.bits.target
140      if2_flush := true.B
141      if3_flush := true.B
142      if4_flush := true.B
143    }
144
145
146    //Output -> iBuffer
147    if4_ready := io.fetchPacket.ready
148    io.fetchPacket.valid := if4_valid && !if4_flush
149    io.fetchPacket.instrs := io.icacheResp.bits.icacheOut
150    io.fetchPacket.mask := Fill(FetchWidth*2, 1.U(1.W)) << if4_pc(2+log2Up(FetchWidth)-1, 1)
151    io.fetchPacket.pc := if4_pc
152
153    //to BPU
154    bpu.io.predecode.valid := if4_valid
155    bpu.io.predecode.bits <> io.icacheResp.bits.predecode
156    bpu.io.predecode.bits.mask := ?
157
158
159
160}
161
162