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