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