xref: /XiangShan/src/main/scala/xiangshan/frontend/IFU.scala (revision b3c92976f4ed5c0d6afe937a703090e7269c487a)
1package xiangshan.frontend
2
3import chisel3._
4import chisel3.util._
5import device.RAMHelper
6import xiangshan._
7import xiangshan.utils._
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
17class FakeIcacheResp extends XSBundle {
18  val icacheOut = Vec(FetchWidth, UInt(32.W))
19  val predecode = new Predecode
20}
21
22
23class IFUIO extends XSBundle
24{
25    val fetchPacket = DecoupledIO(new FetchPacket)
26    val redirectInfo = Input(new RedirectInfo)
27    val icacheReq = DecoupledIO(UInt(VAddrBits.W))
28    val icacheResp = Flipped(DecoupledIO(new FakeIcacheResp))
29}
30
31class FakeBPU extends XSModule{
32  val io = IO(new Bundle() {
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 extends XSModule with HasIFUConst
48{
49    val io = IO(new IFUIO)
50    //val bpu = Module(new BPU)
51    val bpu = Module(new FakeBPU)
52
53    //-------------------------
54    //      IF1  PC update
55    //-------------------------
56    //local
57    val if1_npc = WireInit(0.U(VAddrBits.W))
58    val if1_valid = !reset.asBool //TODO:this is ugly
59    val if1_pc = RegInit(resetVector.U(VAddrBits.W))
60    //next
61    val if2_ready = WireInit(false.B)
62    val if2_snpc = Cat(if1_pc(VAddrBits-1, groupAlign) + 1.U, 0.U(groupAlign.W))
63    val if1_ready = if2_ready
64
65    //pipe fire
66    val if1_fire = if1_valid && if1_ready
67    val if1_pcUpdate = io.redirectInfo.flush() || if1_fire
68
69    when(RegNext(reset.asBool) && !reset.asBool){
70      XSDebug("RESET....\n")
71      if1_npc := resetVector.U(VAddrBits.W)
72    } .otherwise{
73      if1_npc := if2_snpc
74    }
75
76    when(if1_pcUpdate)
77    {
78      if1_pc := if1_npc
79    }
80
81    bpu.io.in.pc.valid := if1_valid
82    bpu.io.in.pc.bits := if1_npc
83
84    XSDebug("[IF1]if1_valid:%d  ||  if1_npc: 0x%x  || if1_pcUpdate:%d if1_pc:0x%x  || if2_ready:%d",if1_valid,if1_npc,if1_pcUpdate,if1_pc,if2_ready)
85    XSDebug(false,if1_fire,"------IF1->fire!!!")
86    XSDebug(false,true.B,"\n")
87
88    //-------------------------
89    //      IF2  btb resonse
90    //           icache visit
91    //-------------------------
92    //local
93    //val if2_flush = WireInit(false.B)
94    val if2_valid = RegEnable(next=if1_valid,init=false.B,enable=if1_fire)
95    val if2_pc = if1_pc
96    val if2_btb_taken = bpu.io.btbOut.valid
97    val if2_btb_insMask = bpu.io.btbOut.bits.instrValid
98    val if2_btb_target = bpu.io.btbOut.bits.target
99
100    //next
101    val if3_ready = WireInit(false.B)
102
103    //pipe fire
104    val if2_fire = if2_valid && if3_ready && io.icacheReq.fire()
105    if2_ready := (if2_fire) || !if2_valid
106
107    io.icacheReq.valid := if2_valid
108    io.icacheReq.bits := groupPC(if2_pc)
109
110    when(if2_valid && if2_btb_taken)
111    {
112      if1_npc := if2_btb_target
113    }
114
115    XSDebug("[IF2]if2_valid:%d  ||  if2_pc:0x%x  || if3_ready:%d",if2_valid,if2_pc,if3_ready)
116    //XSDebug("[IF2-BPU-out]if2_btbTaken:%d || if2_btb_insMask:%b || if2_btb_target:0x%x \n",if2_btb_taken,if2_btb_insMask.asUInt,if2_btb_target)
117    XSDebug(false,if2_fire,"------IF2->fire!!!")
118    XSDebug(false,true.B,"\n")
119    XSDebug("[IF2-Icache-Req] icache_in_valid:%d  icache_in_ready:%d\n",io.icacheReq.valid,io.icacheReq.ready)
120
121    //-------------------------
122    //      IF3  icache hit check
123    //-------------------------
124    //local
125    val if3_valid = RegEnable(next=if2_valid,init=false.B,enable=if2_fire)
126    val if3_pc = RegEnable(if2_pc,if2_fire)
127    val if3_btb_target = RegEnable(if2_btb_target,if2_fire)
128    val if3_btb_taken = RegEnable(if2_btb_taken,if2_fire)
129
130    //next
131    val if4_ready = WireInit(false.B)
132
133    //pipe fire
134    val if3_fire = if3_valid && if4_ready
135    if3_ready := if3_fire  || !if3_valid
136
137
138    XSDebug("[IF3]if3_valid:%d  ||  if3_pc:0x%x  || if4_ready:%d",if3_valid,if3_pc,if4_ready)
139    XSDebug(false,if3_fire,"------IF3->fire!!!")
140    XSDebug(false,true.B,"\n")
141
142    //-------------------------
143    //      IF4  icache resonse
144    //           RAS result
145    //           taget generate
146    //-------------------------
147    val if4_valid = RegEnable(next=if3_valid,init=false.B,enable=if3_fire)
148    val if4_pc = RegEnable(if3_pc,if3_fire)
149    val if4_btb_target = RegEnable(if3_btb_target,if3_fire)
150    val if4_btb_taken = RegEnable(if3_btb_taken,if3_fire)
151    val if4_tage_target = bpu.io.tageOut.bits.target
152    val if4_tage_taken = bpu.io.tageOut.valid
153    val if4_tage_insMask = bpu.io.tageOut.bits.instrValid
154    XSDebug("[IF4]if4_valid:%d ||  if4_pc:0x%x  \n",if4_valid,if4_pc)
155    //XSDebug("[IF4-TAGE-out]if4_tage_taken:%d || if4_btb_insMask:%b || if4_tage_target:0x%x \n",if4_tage_taken,if4_tage_insMask.asUInt,if4_tage_target)
156    XSDebug("[IF4-ICACHE-RESP]icacheResp.valid:%d   icacheResp.ready:%d\n",io.icacheResp.valid,io.icacheResp.ready)
157
158    when(if4_valid && io.icacheResp.fire() && if4_tage_taken)
159    {
160      if1_npc := if4_tage_target
161    }
162
163
164    //redirect: miss predict
165    when(io.redirectInfo.flush()){
166      if1_npc := io.redirectInfo.redirect.target
167      if3_valid := false.B
168      if4_valid := false.B
169    }
170
171
172
173    //Output -> iBuffer
174    io.fetchPacket <> DontCare
175    if4_ready := io.fetchPacket.ready && (io.icacheResp.valid || !if4_valid)
176    io.fetchPacket.valid := if4_valid && !io.redirectInfo.flush()
177    io.fetchPacket.bits.instrs := io.icacheResp.bits.icacheOut
178    io.fetchPacket.bits.mask := Fill(FetchWidth*2, 1.U(1.W)) << if4_pc(2+log2Up(FetchWidth)-1, 1)
179    io.fetchPacket.bits.pc := if4_pc
180
181    //to BPU
182    bpu.io.predecode.valid := io.icacheResp.fire() && if4_valid
183    bpu.io.predecode.bits <> io.icacheResp.bits.predecode
184    bpu.io.predecode.bits.mask := Fill(FetchWidth, 1.U(1.W)) << if4_pc(2+log2Up(FetchWidth)-1, 2) //TODO: consider RVC
185
186    io.icacheResp.ready := io.fetchPacket.ready
187
188}
189
190