Rename.scala 8.9 KB
Newer Older
1 2 3 4 5
package xiangshan.backend.rename

import chisel3._
import chisel3.util._
import xiangshan._
Y
Yinan Xu 已提交
6
import utils._
7

8 9 10 11 12 13 14
class RenameBypassInfo extends XSBundle {
  val lsrc1_bypass = MixedVec(List.tabulate(RenameWidth-1)(i => UInt((i+1).W)))
  val lsrc2_bypass = MixedVec(List.tabulate(RenameWidth-1)(i => UInt((i+1).W)))
  val lsrc3_bypass = MixedVec(List.tabulate(RenameWidth-1)(i => UInt((i+1).W)))
  val ldest_bypass = MixedVec(List.tabulate(RenameWidth-1)(i => UInt((i+1).W)))
}

15
class Rename extends XSModule {
16 17
  val io = IO(new Bundle() {
    val redirect = Flipped(ValidIO(new Redirect))
Y
Yinan Xu 已提交
18
    val roqCommits = Flipped(new RoqCommitIO)
19
    // from decode buffer
20
    val in = Vec(RenameWidth, Flipped(DecoupledIO(new CfCtrl)))
21
    // to dispatch1
22
    val out = Vec(RenameWidth, DecoupledIO(new MicroOp))
23
    val renameBypass = Output(new RenameBypassInfo)
24
  })
25

L
LinJiawei 已提交
26 27
  def printRenameInfo(in: DecoupledIO[CfCtrl], out: DecoupledIO[MicroOp]) = {
    XSInfo(
28
      in.valid && in.ready,
L
LinJiawei 已提交
29
      p"pc:${Hexadecimal(in.bits.cf.pc)} in v:${in.valid} in rdy:${in.ready} " +
L
LinJiawei 已提交
30 31 32 33
        p"lsrc1:${in.bits.ctrl.lsrc1} -> psrc1:${out.bits.psrc1} " +
        p"lsrc2:${in.bits.ctrl.lsrc2} -> psrc2:${out.bits.psrc2} " +
        p"lsrc3:${in.bits.ctrl.lsrc3} -> psrc3:${out.bits.psrc3} " +
        p"ldest:${in.bits.ctrl.ldest} -> pdest:${out.bits.pdest} " +
L
LinJiawei 已提交
34
        p"old_pdest:${out.bits.old_pdest} " +
L
LinJiawei 已提交
35
        p"out v:${out.valid} r:${out.ready}\n"
L
LinJiawei 已提交
36 37 38 39 40 41 42
    )
  }

  for((x,y) <- io.in.zip(io.out)){
    printRenameInfo(x, y)
  }

Y
Yinan Xu 已提交
43
  val intFreeList, fpFreeList = Module(new FreeList).io
44
  val intRat = Module(new RenameTable(float = false)).io
Y
Yinan Xu 已提交
45 46
  val fpRat = Module(new RenameTable(float = true)).io
  val allPhyResource = Seq((intRat, intFreeList, false), (fpRat, fpFreeList, true))
47

Y
Yinan Xu 已提交
48 49 50 51 52 53
  allPhyResource.map{ case (rat, freelist, _) =>
    rat.redirect := io.redirect
    rat.walkWen := io.roqCommits.isWalk
    freelist.redirect := io.redirect
    freelist.walk.valid := io.roqCommits.isWalk
  }
54 55 56 57

  def needDestReg[T <: CfCtrl](fp: Boolean, x: T): Bool = {
    {if(fp) x.ctrl.fpWen else x.ctrl.rfWen && (x.ctrl.ldest =/= 0.U)}
  }
Y
Yinan Xu 已提交
58 59 60
  def needDestRegCommit[T <: RoqCommitInfo](fp: Boolean, x: T): Bool = {
    {if(fp) x.fpWen else x.rfWen && (x.ldest =/= 0.U)}
  }
Y
Yinan Xu 已提交
61 62
  fpFreeList.walk.bits := PopCount(io.roqCommits.valid.zip(io.roqCommits.info).map{case (v, i) => v && needDestRegCommit(true, i)})
  intFreeList.walk.bits := PopCount(io.roqCommits.valid.zip(io.roqCommits.info).map{case (v, i) => v && needDestRegCommit(false, i)})
63
  // walk has higher priority than allocation and thus we don't use isWalk here
64 65
  fpFreeList.req.doAlloc := intFreeList.req.canAlloc && io.out(0).ready
  intFreeList.req.doAlloc := fpFreeList.req.canAlloc && io.out(0).ready
66

Y
Yinan Xu 已提交
67 68 69
  /**
    * Rename: allocate free physical register and update rename table
    */
70 71 72
  val uops = Wire(Vec(RenameWidth, new MicroOp))

  uops.foreach( uop => {
Y
Yinan Xu 已提交
73 74
//    uop.brMask := DontCare
//    uop.brTag := DontCare
75 76 77 78
    uop.src1State := DontCare
    uop.src2State := DontCare
    uop.src3State := DontCare
    uop.roqIdx := DontCare
79
    uop.diffTestDebugLrScValid := DontCare
Y
Yinan Xu 已提交
80
    uop.debugInfo := DontCare
81 82
    uop.lqIdx := DontCare
    uop.sqIdx := DontCare
83 84
  })

85 86
  val needFpDest = Wire(Vec(RenameWidth, Bool()))
  val needIntDest = Wire(Vec(RenameWidth, Bool()))
87 88
  val hasValid = Cat(io.in.map(_.valid)).orR
  val canOut = io.out(0).ready && fpFreeList.req.canAlloc && intFreeList.req.canAlloc && !io.roqCommits.isWalk
Y
Yinan Xu 已提交
89
  for (i <- 0 until RenameWidth) {
90 91
    uops(i).cf := io.in(i).bits.cf
    uops(i).ctrl := io.in(i).bits.ctrl
Y
Yinan Xu 已提交
92
    uops(i).brTag := io.in(i).bits.brTag
93

94
    val inValid = io.in(i).valid
L
LinJiawei 已提交
95

96
    // alloc a new phy reg
97 98
    needFpDest(i) := inValid && needDestReg(fp = true, io.in(i).bits)
    needIntDest(i) := inValid && needDestReg(fp = false, io.in(i).bits)
99 100
    fpFreeList.req.allocReqs(i) := needFpDest(i)
    intFreeList.req.allocReqs(i) := needIntDest(i)
L
LinJiawei 已提交
101

102
    io.in(i).ready := !hasValid || canOut
L
LinJiawei 已提交
103 104

    // do checkpoints when a branch inst come
Y
Yinan Xu 已提交
105 106 107 108
    // for(fl <- Seq(fpFreeList, intFreeList)){
    //   fl.cpReqs(i).valid := inValid
    //   fl.cpReqs(i).bits := io.in(i).bits.brTag
    // }
L
LinJiawei 已提交
109

110
    uops(i).pdest := Mux(needIntDest(i),
111
      intFreeList.req.pdests(i),
L
LinJiawei 已提交
112 113
      Mux(
        uops(i).ctrl.ldest===0.U && uops(i).ctrl.rfWen,
114
        0.U, fpFreeList.req.pdests(i)
L
LinJiawei 已提交
115 116
      )
    )
117

118
    io.out(i).valid := io.in(i).valid && intFreeList.req.canAlloc && fpFreeList.req.canAlloc && !io.roqCommits.isWalk
119 120
    io.out(i).bits := uops(i)

Y
Yinan Xu 已提交
121 122 123
    // write speculative rename table
    allPhyResource.map{ case (rat, freelist, _) =>
      val specWen = freelist.req.allocReqs(i) && freelist.req.canAlloc && freelist.req.doAlloc && !io.roqCommits.isWalk
L
LinJiawei 已提交
124

Y
Yinan Xu 已提交
125 126 127
      rat.specWritePorts(i).wen := specWen
      rat.specWritePorts(i).addr := uops(i).ctrl.ldest
      rat.specWritePorts(i).wdata := freelist.req.pdests(i)
128

Y
Yinan Xu 已提交
129
      freelist.deallocReqs(i) := specWen
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
    }

    // read rename table
    def readRat(lsrcList: List[UInt], ldest: UInt, fp: Boolean) = {
      val rat = if(fp) fpRat else intRat
      val srcCnt = lsrcList.size
      val psrcVec = Wire(Vec(srcCnt, UInt(PhyRegIdxWidth.W)))
      val old_pdest = Wire(UInt(PhyRegIdxWidth.W))
      for(k <- 0 until srcCnt+1){
        val rportIdx = i * (srcCnt+1) + k
        if(k != srcCnt){
          rat.readPorts(rportIdx).addr := lsrcList(k)
          psrcVec(k) := rat.readPorts(rportIdx).rdata
        } else {
          rat.readPorts(rportIdx).addr := ldest
          old_pdest := rat.readPorts(rportIdx).rdata
        }
      }
      (psrcVec, old_pdest)
    }
    val lsrcList = List(uops(i).ctrl.lsrc1, uops(i).ctrl.lsrc2, uops(i).ctrl.lsrc3)
    val ldest = uops(i).ctrl.ldest
    val (intPhySrcVec, intOldPdest) = readRat(lsrcList.take(2), ldest, fp = false)
    val (fpPhySrcVec, fpOldPdest) = readRat(lsrcList, ldest, fp = true)
    uops(i).psrc1 := Mux(uops(i).ctrl.src1Type === SrcType.reg, intPhySrcVec(0), fpPhySrcVec(0))
L
LinJiawei 已提交
155
    uops(i).psrc2 := Mux(uops(i).ctrl.src2Type === SrcType.reg, intPhySrcVec(1), fpPhySrcVec(1))
156 157 158 159
    uops(i).psrc3 := fpPhySrcVec(2)
    uops(i).old_pdest := Mux(uops(i).ctrl.rfWen, intOldPdest, fpOldPdest)
  }

160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
  // We don't bypass the old_pdest from valid instructions with the same ldest currently in rename stage.
  // Instead, we determine whether there're some dependences between the valid instructions.
  for (i <- 1 until RenameWidth) {
    io.renameBypass.lsrc1_bypass(i-1) := Cat((0 until i).map(j => {
      val fpMatch  = needFpDest(j) && io.in(i).bits.ctrl.src1Type === SrcType.fp
      val intMatch = needIntDest(j) && io.in(i).bits.ctrl.src1Type === SrcType.reg
      (fpMatch || intMatch) && io.in(j).bits.ctrl.ldest === io.in(i).bits.ctrl.lsrc1
    }).reverse)
    io.renameBypass.lsrc2_bypass(i-1) := Cat((0 until i).map(j => {
      val fpMatch  = needFpDest(j) && io.in(i).bits.ctrl.src2Type === SrcType.fp
      val intMatch = needIntDest(j) && io.in(i).bits.ctrl.src2Type === SrcType.reg
      (fpMatch || intMatch) && io.in(j).bits.ctrl.ldest === io.in(i).bits.ctrl.lsrc2
    }).reverse)
    io.renameBypass.lsrc3_bypass(i-1) := Cat((0 until i).map(j => {
      val fpMatch  = needFpDest(j) && io.in(i).bits.ctrl.src3Type === SrcType.fp
      val intMatch = needIntDest(j) && io.in(i).bits.ctrl.src3Type === SrcType.reg
      (fpMatch || intMatch) && io.in(j).bits.ctrl.ldest === io.in(i).bits.ctrl.lsrc3
    }).reverse)
    io.renameBypass.ldest_bypass(i-1) := Cat((0 until i).map(j => {
      val fpMatch  = needFpDest(j) && needFpDest(i)
      val intMatch = needIntDest(j) && needIntDest(i)
      (fpMatch || intMatch) && io.in(j).bits.ctrl.ldest === io.in(i).bits.ctrl.ldest
    }).reverse)
183
  }
Y
Yinan Xu 已提交
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221

  /**
    * Instructions commit: update freelist and rename table
    */
  for (i <- 0 until CommitWidth) {
    if (i >= RenameWidth) {
      allPhyResource.map{ case (rat, _, _) =>
        rat.specWritePorts(i).wen   := false.B
        rat.specWritePorts(i).addr  := DontCare
        rat.specWritePorts(i).wdata := DontCare
      }
    }

    allPhyResource.map{ case (rat, freelist, fp) =>
      // walk back write
      val commitDestValid = io.roqCommits.valid(i) && needDestRegCommit(fp, io.roqCommits.info(i))

      when (commitDestValid && io.roqCommits.isWalk) {
        rat.specWritePorts(i).wen := true.B
        rat.specWritePorts(i).addr := io.roqCommits.info(i).ldest
        rat.specWritePorts(i).wdata := io.roqCommits.info(i).old_pdest
        XSInfo({if(fp) p"fp" else p"int "} + p"walk: " +
          p" ldest:${rat.specWritePorts(i).addr} old_pdest:${rat.specWritePorts(i).wdata}\n")
      }

      rat.archWritePorts(i).wen := commitDestValid && !io.roqCommits.isWalk
      rat.archWritePorts(i).addr := io.roqCommits.info(i).ldest
      rat.archWritePorts(i).wdata := io.roqCommits.info(i).pdest

      XSInfo(rat.archWritePorts(i).wen,
        {if(fp) p"fp" else p"int "} + p" rat arch: ldest:${rat.archWritePorts(i).addr}" +
          p" pdest:${rat.archWritePorts(i).wdata}\n"
      )

      freelist.deallocReqs(i) := rat.archWritePorts(i).wen
      freelist.deallocPregs(i) := io.roqCommits.info(i).old_pdest
    }
  }
222
}