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