Alu.scala 4.7 KB
Newer Older
1 2 3 4 5 6 7 8
package xiangshan.backend.exu

import chisel3._
import chisel3.util._
import xiangshan._
import xiangshan.FuType._
import xiangshan.utils._
import xiangshan.backend.regfile.RfWritePort
9
import xiangshan.backend.decode.isa.RV32I_BRUInstr
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

object ALUOpType {
  def add  = "b000000".U
  def sll  = "b000001".U
  def slt  = "b000010".U
  def sltu = "b000011".U
  def xor  = "b000100".U
  def srl  = "b000101".U
  def or   = "b000110".U
  def and  = "b000111".U
  def sub  = "b001000".U
  def sra  = "b001101".U

  def addw = "b100000".U
  def subw = "b101000".U
  def sllw = "b100001".U
  def srlw = "b100101".U
  def sraw = "b101101".U

  def isWordOp(func: UInt) = func(5)

  // TODO: move jal/jalr/call/ret from ALU to BRU&CSR
32 33
  def jal  = "b011000".U
  def jalr = "b011010".U
34 35 36 37 38 39 40 41 42
  // def cjalr= "b111010".U // pc + 2 instead of 4
  def beq  = "b010000".U
  def bne  = "b010001".U
  def blt  = "b010100".U
  def bge  = "b010101".U
  def bltu = "b010110".U
  def bgeu = "b010111".U

  // for RAS
43 44
  def call = "b011100".U
  def ret  = "b011110".U
45 46

  // def pcPlus2(func: UInt) = func(5)//[important]
47 48 49
  def isBranch(func: UInt) = func(4,3)===2.U
  def isBru(func: UInt) = func(4)
  def isJump(func: UInt) = func(4,3)===3.U//isBru(func) && !isBranch(func)
50 51 52 53
  def getBranchType(func: UInt) = func(2, 1)
  def isBranchInvert(func: UInt) = func(0)
}

54
class Alu extends Exu(alu.litValue()) {
55 56 57
  override def toString: String = "Alu"

  val (iovalid, src1, src2, offset, func, pc, uop) = (io.in.valid, io.in.bits.src1, io.in.bits.src2, 
58
    io.in.bits.uop.ctrl.imm, io.in.bits.uop.ctrl.fuOpType, SignExt(io.in.bits.uop.cf.pc, AddrBits), io.in.bits.uop)
59

60
  val redirectHit = (io.redirect.valid && 
61
    ((UIntToOH(io.redirect.bits.brTag) & uop.brMask).orR || io.redirect.bits.isException))
62
  val valid = iovalid && !redirectHit
63

64
  val isAdderSub = (func =/= ALUOpType.add) && (func =/= ALUOpType.addw) && !ALUOpType.isJump(func)
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
  val adderRes = (src1 +& (src2 ^ Fill(XLEN, isAdderSub))) + isAdderSub
  val xorRes = src1 ^ src2
  val sltu = !adderRes(XLEN)
  val slt = xorRes(XLEN-1) ^ sltu

  val shsrc1 = LookupTreeDefault(func, src1, List(
    ALUOpType.srlw -> ZeroExt(src1(31,0), 64),
    ALUOpType.sraw -> SignExt(src1(31,0), 64)
  ))
  val shamt = Mux(ALUOpType.isWordOp(func), src2(4, 0), src2(5, 0))
  val res = LookupTreeDefault(func(3, 0), adderRes, List(
    ALUOpType.sll  -> ((shsrc1  << shamt)(XLEN-1, 0)),
    ALUOpType.slt  -> ZeroExt(slt, XLEN),
    ALUOpType.sltu -> ZeroExt(sltu, XLEN),
    ALUOpType.xor  -> xorRes,
    ALUOpType.srl  -> (shsrc1  >> shamt),
    ALUOpType.or   -> (src1  |  src2),
    ALUOpType.and  -> (src1  &  src2),
    ALUOpType.sra  -> ((shsrc1.asSInt >> shamt).asUInt)
  ))
  val aluRes = Mux(ALUOpType.isWordOp(func), SignExt(res(31,0), 64), res)

  val branchOpTable = List(
    ALUOpType.getBranchType(ALUOpType.beq)  -> !xorRes.orR,
    ALUOpType.getBranchType(ALUOpType.blt)  -> slt,
    ALUOpType.getBranchType(ALUOpType.bltu) -> sltu
  )

93 94 95 96
  val isBru = ALUOpType.isBru(func)
  // val isBranch =  io.in.bits.uop.cf.isBr// ALUOpType.isBranch(func)
  val isBranch =  ALUOpType.isBranch(func)
  val isJump = ALUOpType.isJump(func)
97 98 99 100 101
  val taken = LookupTree(ALUOpType.getBranchType(func), branchOpTable) ^ ALUOpType.isBranchInvert(func)
  val target = Mux(isBranch, pc + offset, adderRes)(VAddrBits-1,0)
  val isRVC = uop.cf.isRVC//(io.in.bits.cf.instr(1,0) =/= "b11".U)

  io.in.ready := io.out.ready
102 103
  val pcLatchSlot = Mux(isRVC, pc + 2.U, pc + 4.U)
  io.out.bits.redirect.valid := io.out.valid && isBru//isBranch
104
  io.out.bits.redirect.bits.pc := uop.cf.pc
105
  io.out.bits.redirect.bits.target := Mux(!taken && isBranch, pcLatchSlot, target)
106
  io.out.bits.redirect.bits.brTag := uop.brTag
107 108
  io.out.bits.redirect.bits._type := LookupTree(func, RV32I_BRUInstr.bruFuncTobtbTypeTable)
  io.out.bits.redirect.bits.taken := taken
109 110
  io.out.bits.redirect.bits.isException := DontCare // false.B
  io.out.bits.redirect.bits.roqIdx := uop.roqIdx
111
  io.out.bits.redirect.bits.freelistAllocPtr := uop.freelistAllocPtr
112 113 114

  io.out.valid := valid
  io.out.bits.uop <> io.in.bits.uop
115 116 117 118 119 120 121 122 123 124 125
  io.out.bits.data := Mux(isJump, pcLatchSlot, aluRes)

  io.dmem <> DontCare
  io.out.bits.debug.isMMIO := DontCare // FIXME: dont know how to do with it
  
  XSDebug(io.in.valid, "In(%d %d) Out(%d %d) Redirect:(%d %d %d) brTag:%x, brMask:%x\n",
    io.in.valid, io.in.ready, io.out.valid, io.out.ready, io.redirect.valid, io.redirect.bits.isException, redirectHit, io.redirect.bits.brTag, uop.brMask)
  XSDebug(io.in.valid, "src1:%x src2:%x offset:%x func:%b pc:%x\n",
    src1, src2, offset, func, pc)
  XSDebug(io.in.valid, "res:%x aluRes:%x isRVC:%d isBru:%d isBranch:%d isJump:%d target:%x taken:%d\n",
     io.out.bits.data, aluRes, isRVC, isBru, isBranch, isJump, target, taken)
126
}