xref: /XiangShan/src/main/scala/xiangshan/frontend/IFU.scala (revision 3b0f4538045bafc7cc5282c6c8da60370c616b0e)
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
30class FakeBPU extends XSModule {
31  val io = IO(new Bundle() {
32    val redirect = Flipped(ValidIO(new Redirect))
33    val in = new Bundle { val pc = Flipped(Valid(UInt(VAddrBits.W))) }
34    val btbOut = ValidIO(new BranchPrediction)
35    val tageOut = ValidIO(new BranchPrediction)
36    val predecode = Flipped(ValidIO(new Predecode))
37  })
38
39  io.btbOut.valid := false.B
40  io.btbOut.bits <> DontCare
41  io.tageOut.valid := false.B
42  io.tageOut.bits <> DontCare
43}
44
45
46
47class IFU(implicit val p: XSConfig) extends IFUModule
48{
49    val io = IO(new IFUIO)
50    val bpu = Module(new FakeBPU)
51
52    //-------------------------
53    //      IF1  PC update
54    //-------------------------
55    //local
56    val if1_npc = WireInit(0.U(VAddrBits.W))
57    val if1_valid = WireInit(false.B)
58    val if1_pc = RegInit(resetVector.U(VAddrBits.W))
59    //next
60    val if2_ready = WireInit(false.B)
61    val if1_ready = if2_ready
62
63    //pipe fire
64    val if1_fire = if1_valid && if1_ready
65    val if1_pcUpdate = io.redirect.valid || if1_fire
66
67    when(RegNext(reset.asBool) && !reset.asBool)
68    {
69      if1_npc := resetVector
70      if1_valid := true.B
71    }
72
73    when(if1_pcUpdate)
74    {
75      if1_pc := if1_npc
76    }
77
78    bpu.io.in.valid := if1_valid
79    bpu.io.in.pc := if1_npc
80
81    //-------------------------
82    //      IF2  btb resonse
83    //           icache visit
84    //-------------------------
85    //local
86    val if2_flush = WireInit(false.B)
87    val if2_update = if1_fire && !if2_flush
88    val if2_valid = RegNext(if2_update)
89    val if2_pc = if1_pc
90    val if2_btb_taken = bpu.io.btbOut.valid
91    val if2_btb_insMask = bpu.io.btbOut.bits.instrValid
92    val if2_btb_target = bpu.io.btbOut.bits.target
93    val if2_snpc = Cat(if2_pc(VAddrBits-1, groupAlign) + 1.U, 0.U(groupAlign.W))
94    val if2_flush = WireInit(false.B)
95
96    //next
97    val if3_ready = WireInit(false.B)
98
99    //pipe fire
100    val if2_fire = if2_valid && if3_ready
101    val if2_ready = (if2_fire && io.icacheReq.fire()) || !if2_valid
102
103    io.icacheReq.valid := if2_fire
104    io.icacheReq.bits := groupPC(if2_pc)
105
106    when(if2_valid && if2_btb_taken)
107    {
108      if1_npc := if2_btb_target
109    } .otherwise
110    {
111      if1_npc := if2_snpc
112    }
113
114    //-------------------------
115    //      IF3  icache hit check
116    //-------------------------
117    //local
118    val if3_flush = WireInit(false.B)
119    val if3_update = if2_fire && !if3_flush
120    val if3_valid = RegNext(if3_update)
121    val if3_pc = RegEnable(if2_pc,if3_update)
122    val if3_btb_target = RegEnable(if2_btb_target,if3_update)
123    val if3_btb_taken = RegEnable(if2_btb_taken,if3_update)
124
125    //next
126    val if4_ready = WireInit(false.B)
127
128    //pipe fire
129    val if3_fire = if3_valid && if4_ready
130    val if3_ready = if3_fire  || !if3_valid
131
132    //-------------------------
133    //      IF4  icache resonse
134    //           RAS result
135    //           taget generate
136    //-------------------------
137    val if4_flush = WireInit(false.B)
138    val if4_update = if3_fire && !if4_flush
139    val if4_valid = RegNext(if4_update)
140    val if4_pc = RegEnable(if3_pc,if4_update)
141    val if4_btb_target = RegEnable(if3_btb_target,if4_update)
142    val if4_btb_taken = RegEnable(if3_btb_taken,if4_update)
143
144
145
146    when(if4_valid && io.icacheResp.fire())
147    {
148      if1_npc := if4_btb_target
149    }
150
151
152    //redirect
153    when(io.redirect.valid){
154      if1_npc := io.redirect.bits.target
155      if2_flush := true.B
156      if3_flush := true.B
157      if4_flush := true.B
158    }
159
160
161    //Output -> iBuffer
162    if4_ready := io.fetchPacket.ready && io.icacheResp.valid
163    io.fetchPacket.valid := if4_valid && !if4_flush
164    io.fetchPacket.instrs := io.icacheResp.bits.icacheOut
165    io.fetchPacket.mask := Fill(FetchWidth*2, 1.U(1.W)) << if4_pc(2+log2Up(FetchWidth)-1, 1)
166    io.fetchPacket.pc := if4_pc
167
168    //to BPU
169    bpu.io.predecode.valid := if4_valid
170    bpu.io.predecode.bits <> io.icacheResp.bits.predecode
171    bpu.io.predecode.bits.mask := Fill(FetchWidth, 1.U(1.W)) << if4_pc(2+log2Up(FetchWidth)-1, 2) //TODO: consider RVC
172
173    io.icacheResp.ready := io.fetchPacket.ready
174
175}
176
177