IFU.scala 4.3 KB
Newer Older
Z
Zihao Yu 已提交
1
package noop
Z
Zihao Yu 已提交
2 3 4

import chisel3._
import chisel3.util._
5
import chisel3.util.experimental.BoringUtils
Z
Zihao Yu 已提交
6

7
import utils._
8
import bus.simplebus._
Z
Zihao Yu 已提交
9

Z
Zihao Yu 已提交
10
trait HasResetVector {
11
  val resetVector = 0x40000000L//TODO: set reset vec
Z
Zihao Yu 已提交
12 13
}

Z
Zihao Yu 已提交
14
class IFU extends NOOPModule with HasResetVector {
Z
Zihao Yu 已提交
15
  val io = IO(new Bundle {
W
William Wang 已提交
16

17
    val imem = new SimpleBusUC(userBits = VAddrBits*2 + 4, addrBits = VAddrBits)
18
    // val pc = Input(UInt(VAddrBits.W))
Z
Zihao Yu 已提交
19
    val out = Decoupled(new CtrlFlowIO)
W
William Wang 已提交
20

Z
Zihao Yu 已提交
21
    val redirect = Flipped(new RedirectIO)
22
    val flushVec = Output(UInt(4.W))
23
    val bpFlush = Output(Bool())
24
    val ipf = Input(Bool())
Z
Zihao Yu 已提交
25 26
  })

Z
Zihao Yu 已提交
27
  // pc
Z
zhangzifei 已提交
28
  val pc = RegInit(resetVector.U(VAddrBits.W))
29
  val pcUpdate = io.redirect.valid || io.imem.req.fire()
30
  val snpc = Mux(pc(1), pc + 2.U, pc + 4.U)  // sequential next pc
31 32

  val bp1 = Module(new BPU1)
33 34 35 36

  //
  val lateJump = bp1.io.lateJump
  val lateJumpLatch = RegInit(false.B) 
W
William Wang 已提交
37 38
  when(pcUpdate || bp1.io.flush) {
    lateJumpLatch := Mux(bp1.io.flush, false.B, lateJump && !lateJumpLatch)
39 40 41 42 43
  }
  val lateJumpTarget = RegEnable(bp1.io.out.target, lateJump)
  val lateJumpForceSeq = lateJump && bp1.io.out.valid
  val lateJumpForceTgt = lateJumpLatch && !bp1.io.flush

44
  // predicted next pc
45
  val pnpc = Mux(lateJump, snpc, bp1.io.out.target)
W
William Wang 已提交
46
  val pbrIdx = bp1.io.brIdx
47
  val npc = Mux(io.redirect.valid, io.redirect.target, Mux(lateJumpLatch, lateJumpTarget, Mux(bp1.io.out.valid, pnpc, snpc)))
48
  val npcIsSeq = Mux(io.redirect.valid , false.B, Mux(lateJumpLatch, false.B, Mux(lateJump, true.B, Mux(bp1.io.out.valid, false.B, true.B))))
49 50 51
  // Debug(){
  //   printf("[NPC] %x %x %x %x %x %x\n",lateJumpLatch, lateJumpTarget, lateJump, bp1.io.out.valid, pnpc, snpc)
  // }
52

53
  // val npc = Mux(io.redirect.valid, io.redirect.target, Mux(io.redirectRVC.valid, io.redirectRVC.target, snpc))
54
  val brIdx = Wire(UInt(4.W)) 
55 56
  // brIdx(0) -> branch at pc offset 0 (mod 4)
  // brIdx(1) -> branch at pc offset 2 (mod 4)
57
  // brIdx(2) -> branch at pc offset 6 (mod 8), and this inst is not rvc inst
58
  brIdx := Cat(npcIsSeq, Mux(io.redirect.valid, 0.U, pbrIdx))
59
  //TODO: BP will be disabled shortly after a redirect request
60

61
  bp1.io.in.pc.valid := io.imem.req.fire() // only predict when Icache accepts a request
62
  bp1.io.in.pc.bits := npc  // predict one cycle early
63
  // bp1.io.flush := io.redirect.valid 
64
  bp1.io.flush := io.redirect.valid
Z
Zihao Yu 已提交
65 66 67
  //val bp2 = Module(new BPU2)
  //bp2.io.in.bits := io.out.bits
  //bp2.io.in.valid := io.imem.resp.fire()
68

69 70 71 72
  when (pcUpdate) { 
    pc := npc 
    // printf("[IF1] pc=%x\n", pc)
  }
Z
Zihao Yu 已提交
73

74 75 76 77 78 79 80
  Debug(){
    when(pcUpdate) {
      printf("[IFUPC] pc:%x pcUpdate:%d npc:%x RedValid:%d RedTarget:%x LJL:%d LJTarget:%x LJ:%d snpc:%x bpValid:%d pnpn:%x \n",pc, pcUpdate, npc, io.redirect.valid,io.redirect.target,lateJumpLatch,lateJumpTarget,lateJump,snpc,bp1.io.out.valid,pnpc)
      //printf(p"[IFUIN] redirect: ${io.redirect} \n")
    }
  }

81
  io.flushVec := Mux(io.redirect.valid, "b1111".U, 0.U)
82
  io.bpFlush := false.B
Z
Zihao Yu 已提交
83

84
  io.imem.req.bits.apply(addr = Cat(pc(VAddrBits-1,1),0.U(1.W)), //cache will treat it as Cat(pc(63,3),0.U(3.W))
85
    size = "b11".U, cmd = SimpleBusCmd.read, wdata = 0.U, wmask = 0.U, user = Cat(brIdx(3,0), npc(VAddrBits-1, 0), pc(VAddrBits-1, 0)))
Z
Zihao Yu 已提交
86
  io.imem.req.valid := io.out.ready
87
  //TODO: add ctrlFlow.exceptionVec
88
  io.imem.resp.ready := io.out.ready || io.flushVec(0)
89

Z
Zihao Yu 已提交
90
  io.out.bits := DontCare
Z
Zihao Yu 已提交
91
    //inst path only uses 32bit inst, get the right inst according to pc(2)
92

93
  Debug(){
94
    when(io.imem.req.fire()){
95
      printf("[IFI] pc=%x user=%x %x %x %x \n", io.imem.req.bits.addr, io.imem.req.bits.user.getOrElse(0.U), io.redirect.valid, pbrIdx, brIdx)
96
    }
97
    when (io.out.fire()) {
98
          printf("[IFO] pc=%x inst=%x\n", io.out.bits.pc, io.out.bits.instr)
99
    }
100 101
  }

W
William Wang 已提交
102 103 104
  // io.out.bits.instr := (if (XLEN == 64) io.imem.resp.bits.rdata.asTypeOf(Vec(2, UInt(32.W)))(io.out.bits.pc(2))
                      //  else io.imem.resp.bits.rdata)
  io.out.bits.instr := io.imem.resp.bits.rdata
Z
Zihao Yu 已提交
105
  io.imem.resp.bits.user.map{ case x =>
106 107 108
    io.out.bits.pc := x(VAddrBits-1,0)
    io.out.bits.pnpc := x(VAddrBits*2-1,VAddrBits)
    io.out.bits.brIdx := x(VAddrBits*2 + 3, VAddrBits*2)
Z
Zihao Yu 已提交
109
  }
110
  io.out.bits.exceptionVec(instrPageFault) := io.ipf
Z
Zihao Yu 已提交
111
  io.out.valid := io.imem.resp.valid && !io.flushVec(0)
112

113 114
  BoringUtils.addSource(BoolStopWatch(io.imem.req.valid, io.imem.resp.fire()), "perfCntCondMimemStall")
  BoringUtils.addSource(io.flushVec.orR, "perfCntCondMifuFlush")
Z
Zihao Yu 已提交
115
}