提交 a32c56f4 编写于 作者: X Xuan Hu

backend,vector: rewrite vset uop and base module

* Add unit-test for vset base module
上级 b52d4755
......@@ -557,9 +557,9 @@ object VecDecoder extends DecodeConstants {
)
val vset: Array[(BitPat, XSDecodeBase)] = Array(
VSETVLI -> VSET(F, T, VSETOpType.uvset_xi, F, SelImm.IMM_VSETVLI),
VSETIVLI -> VSET(T, T, VSETOpType.uvset_ii, F, SelImm.IMM_VSETIVLI),
VSETVL -> VSET(F, F, VSETOpType.uvset_xx, T, SelImm.X), // flush pipe
VSETVLI -> VSET(vli = F, vtypei = T, VSETOpType.uvsetvcfg_xi, F, SelImm.IMM_VSETVLI),
VSETIVLI -> VSET(vli = T, vtypei = T, VSETOpType.uvsetvcfg_ii, F, SelImm.IMM_VSETIVLI),
VSETVL -> VSET(vli = F, vtypei = F, VSETOpType.uvsetvcfg_xx, T, SelImm.X), // flush pipe
)
val vls: Array[(BitPat, XSDecodeBase)] = Array(
......
......@@ -17,7 +17,7 @@ object FuType {
val div = OHInt(6)
val fence = OHInt(7)
val bku = OHInt(8)
val vsetiwi = OHInt(9)
val vsetiwi = OHInt(9) // vset read rs write rd
val fmac = OHInt(10)
val fmisc = OHInt(11)
val fDivSqrt = OHInt(12)
......@@ -30,8 +30,8 @@ object FuType {
val vldu = OHInt(19)
val vstu = OHInt(20)
val vppu = OHInt(21)
val vsetiwf = OHInt(22)
val vsetfwf = OHInt(23)
val vsetiwf = OHInt(22) // vset read rs write vconfig
val vsetfwf = OHInt(23) // vset read old vl write vconfig
def X = BitPat.N(num) // Todo: Don't Care
......
......@@ -19,46 +19,91 @@ package xiangshan.backend.fu
import chipsalliance.rocketchip.config.Parameters
import chisel3._
import chisel3.util._
import utility.{ParallelMux, ZeroExt}
import utility.ZeroExt
import xiangshan._
class VsetModule(implicit p: Parameters) extends XSModule {
val io = IO(new Bundle() {
val src0 = Input(UInt(XLEN.W))
val src1 = Input(UInt(XLEN.W))
val func = Input(FuOpType())
val oldVConfig = Input(UInt(16.W))
val vconfig = Output(UInt(XLEN.W))
val vl = Output(UInt(XLEN.W))
import xiangshan.backend.fu.vector.Bundles.{VConfig, VType, Vl}
class VsetModuleIO(implicit p: Parameters) extends XSBundle {
private val vlWidth = p(XSCoreParamsKey).vlWidth
val in = Input(new Bundle {
val avl : UInt = Vl()
val vtype : VType = VType()
val func : UInt = FuOpType()
val oldVl : UInt = Vl() // Todo: check if it can be optimized
})
val out = Output(new Bundle {
val vconfig: VConfig = VConfig()
})
private val vtypeWidth = 8
private val vlWidth = 8
// test bundle for internal state
val testOut = Output(new Bundle {
val log2Vlmax : UInt = UInt(3.W)
val vlmax : UInt = UInt(vlWidth.W)
})
}
class VsetModule(implicit p: Parameters) extends XSModule {
val io = IO(new VsetModuleIO)
private val setOldVLFlag = VSETOpType.oldvlFlag(io.func)
private val setVLMAXFlag = VSETOpType.vlmaxFlag(io.func)
private val isVsetivli = VSETOpType.isVsetivli(io.func)
private val avl = io.in.avl
private val oldVL = io.in.oldVl
private val func = io.in.func
private val vtype = io.in.vtype
private val vtype = io.src1(7, 0)
private val vlmul = vtype(2, 0)
private val vsew = vtype(5, 3)
private val outVConfig = io.out.vconfig
private val vlWidth = p(XSCoreParamsKey).vlWidth
private val isKeepVl = VSETOpType.isKeepVl(func)
private val isSetVlmax = VSETOpType.isSetVlmax(func)
private val isVsetivli = VSETOpType.isVsetivli(func)
private val vlmul: UInt = vtype.vlmul
private val vsew : UInt = vtype.vsew
private val avlImm = ZeroExt(io.src1(14, 10), XLEN)
private val avl = Mux(VSETOpType.isVsetivli(io.func), avlImm, io.src0)
private val oldVL = io.oldVConfig(vtypeWidth + vlWidth - 1, vtypeWidth)
private val vl = WireInit(0.U(XLEN.W))
// VLMAX = VLEN * LMUL / SEW
// = VLEN << (Cat(~vlmul(2), vlmul(1,0)) >> (vsew + 1.U)
// = VLEN >> shamt
// shamt = (vsew + 1.U) - (Cat(~vlmul(2), vlmul(1,0))
// vlen = 128
private val vlmaxVec = (0 to 7).map(i => if(i < 4) (16 << i).U(8.W) else (16 >> (8 - i)).U(8.W))
private val shamt = vlmul + (~vsew).asUInt + 1.U
private val vlmax = ParallelMux((0 to 7).map(_.U === shamt), vlmaxVec)
private val log2Vlen = log2Up(VLEN)
println(s"[VsetModule] log2Vlen: $log2Vlen")
println(s"[VsetModule] vlWidth: $vlWidth")
// mf8-->b001, m1-->b100, m8-->b111
private val ilmul = Cat(!vlmul(2), vlmul(1, 0))
// vlen = 128, lmul = 8, sew = 8, log2Vlen = 7,
// vlmul = b011, ilmul - 4 = b111 - 4 = 3, vsew = 0, vsew + 3 = 3, 7 + (7 - 4) - (0 + 3) = 7
// vlen = 128, lmul = 2, sew = 16
// vlmul = b001, ilmul - 4 = b101 - 4 = 3, vsew = 1, 7 + (5 - 4) - (1 + 3) = 4
private val log2Vlmax: UInt = log2Vlen.U(3.W) + (ilmul - "b100".U) - (vsew + "b011".U)
private val vlmax = (1.U(vlWidth.W) << (log2Vlmax - 1.U)).asUInt
// private val vlmaxVec: Seq[UInt] = (0 to 7).map(i => if(i < 4) (16 << i).U(8.W) else (16 >> (8 - i)).U(8.W))
// private val shamt = vlmul + (~vsew).asUInt + 1.U
// private val vlmax = ParallelMux((0 to 7).map(_.U === shamt), vlmaxVec)
private val normalVL = Mux(avl > vlmax, vlmax, avl)
vl := Mux(isVsetivli, normalVL,
Mux(setOldVLFlag, ZeroExt(oldVL, XLEN),
Mux(setVLMAXFlag, vlmax, normalVL)))
io.vl := vl
io.vconfig := ZeroExt(Cat(vl(7, 0), vtype), XLEN)
vl := MuxCase(normalVL, Seq(
isVsetivli -> normalVL,
isKeepVl -> ZeroExt(oldVL, XLEN),
isSetVlmax -> vlmax,
))
outVConfig.vl := vl
outVConfig.vtype.illegal := false.B // Todo
outVConfig.vtype.vta := vtype.vta
outVConfig.vtype.vma := vtype.vma
outVConfig.vtype.vlmul := vtype.vlmul
outVConfig.vtype.vsew := vtype.vsew
io.testOut.vlmax := vlmax
io.testOut.log2Vlmax := log2Vlmax
}
......@@ -2,58 +2,94 @@ package xiangshan.backend.fu.wrapper
import chipsalliance.rocketchip.config.Parameters
import chisel3._
import utility.ZeroExt
import xiangshan.VSETOpType
import xiangshan.backend.decode.Imm_VSETIVLI
import xiangshan.backend.decode.isa.bitfield.InstVType
import xiangshan.backend.fu.vector.Bundles.VType
import xiangshan.backend.fu.{FuConfig, FuncUnit, VsetModule}
class VSetIVL(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg) {
private val vsetModule = Module(new VsetModule)
class VSetBase(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg) {
protected val in = io.in.bits
protected val out = io.out.bits
private val flushed = io.in.bits.robIdx.needFlush(io.flush)
protected val vsetModule = Module(new VsetModule)
io.out.valid := io.in.valid
io.in.ready := io.out.ready
protected val flushed = io.in.bits.robIdx.needFlush(io.flush)
private val in = io.in.bits
private val out = io.out.bits
vsetModule.io.src0 := in.src(0)
vsetModule.io.src1 := in.src(1)
vsetModule.io.func := in.fuOpType
vsetModule.io.oldVConfig := 0.U
out.data := vsetModule.io.vl
connectNonPipedCtrlSingal
}
protected val avlImm = Imm_VSETIVLI().getAvl(in.src(1))
protected val avl = Mux(VSETOpType.isVsetivli(in.fuOpType), avlImm, in.src(0))
class VSetIVConfig(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg) {
private val vsetModule = Module(new VsetModule)
protected val instVType: InstVType = Imm_VSETIVLI().getVType(in.src(1))
protected val vtypeImm: VType = VType.fromInstVType(instVType)
protected val vtype: VType = Mux(VSETOpType.isVsetvl(in.fuOpType), in.src(1)(7, 0).asTypeOf(new VType), vtypeImm)
private val flushed = io.in.bits.robIdx.needFlush(io.flush)
vsetModule.io.in.func := in.fuOpType
io.out.valid := io.in.valid
io.in.ready := io.out.ready
}
/**
* Wrapper of VsetModule
* This fu is uop of vset which reads two int regs and writes one int regs.<br>
* uop: <br/>
* [[VSETOpType.uvsetrd_ii]], <br/>
* [[VSETOpType.uvsetrd_xi]], <br/>
* [[VSETOpType.uvsetrd_xx]], <br/>
* [[VSETOpType.uvsetrd_vlmax_i]], <br/>
* [[VSETOpType.uvsetrd_vlmax_x]], <br/>
* @param cfg [[FuConfig]]
* @param p [[Parameters]]
*/
class VSetIVL(cfg: FuConfig)(implicit p: Parameters) extends VSetBase(cfg) {
vsetModule.io.in.avl := avl
vsetModule.io.in.vtype := vtype
vsetModule.io.in.oldVl := 0.U
out.data := vsetModule.io.out.vconfig.vl
private val in = io.in.bits
private val out = io.out.bits
vsetModule.io.src0 := in.src(0)
vsetModule.io.src1 := in.src(1)
vsetModule.io.func := in.fuOpType
vsetModule.io.oldVConfig := 0.U
out.data := vsetModule.io.vconfig
connectNonPipedCtrlSingal
}
class VSetFVConfig(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg) {
private val vsetModule = Module(new VsetModule)
/**
* Wrapper of VsetModule
* This fu is uop of vset which reads two int regs and writes one vf regs.<br>
* uop: <br/>
* [[VSETOpType.uvsetvcfg_ii]], <br/>
* [[VSETOpType.uvsetvcfg_xi]], <br/>
* [[VSETOpType.uvsetvcfg_xx]], <br/>
* [[VSETOpType.uvsetvcfg_vlmax_i]], <br/>
* [[VSETOpType.uvsetvcfg_vlmax_x]], <br/>
* @param cfg [[FuConfig]]
* @param p [[Parameters]]
*/
class VSetIVConfig(cfg: FuConfig)(implicit p: Parameters) extends VSetBase(cfg) {
vsetModule.io.in.avl := avl
vsetModule.io.in.vtype := vtype
vsetModule.io.in.oldVl := 0.U
private val flushed = io.in.bits.robIdx.needFlush(io.flush)
out.data := ZeroExt(vsetModule.io.out.vconfig.asUInt, XLEN)
io.out.valid := io.in.valid
io.in.ready := io.out.ready
connectNonPipedCtrlSingal
}
/**
* Wrapper of VsetModule
* This fu is uop of vset which reads two int regs and writes one vf regs.<br>
* uop: <br/>
* [[VSETOpType.uvsetvcfg_vv]], <br/>
* [[VSETOpType.uvsetvcfg_keep_v]], <br/>
* @param cfg [[FuConfig]]
* @param p [[Parameters]]
*/
class VSetFVConfig(cfg: FuConfig)(implicit p: Parameters) extends VSetBase(cfg) {
vsetModule.io.in.avl := 0.U
vsetModule.io.in.vtype := vtype
vsetModule.io.in.oldVl := in.src(0)
out.data := ZeroExt(vsetModule.io.out.vconfig.asUInt, XLEN)
private val in = io.in.bits
private val out = io.out.bits
vsetModule.io.src0 := 0.U
vsetModule.io.src1 := in.src(1)
vsetModule.io.func := in.fuOpType
vsetModule.io.oldVConfig := in.src(0)
out.data := vsetModule.io.vconfig
connectNonPipedCtrlSingal
}
\ No newline at end of file
}
......@@ -277,26 +277,56 @@ package object xiangshan {
}
object VSETOpType {
// o: set vl to old vl
// m: set vl to vlmax
def uvset_xi = "b0000_0000".U
def uvset_xi_o = "b0000_1000".U
def uvset_xi_m = "b0001_0000".U
def uvsetvl_xi = "b0000_0100".U
def uvsetvl_xi_o = "b0000_1100".U
def uvset_xx = "b0000_0001".U
def uvset_xx_o = "b0000_1001".U
def uvset_xx_m = "b0001_0001".U
def uvsetvl_xx = "b0000_0101".U
def uvsetvl_xx_o = "b0000_1101".U
def uvset_ii = "b0000_0010".U
def uvsetvl_ii = "b0000_0110".U
def isVsetvl(func: UInt) = func(0)
def isVsetvli(func: UInt) = !func(1, 0).orR
def isVsetivli(func: UInt) = func(1)
def oldvlFlag(func: UInt) = func(3)
def vlmaxFlag(func: UInt) = func(4)
// vsetvli's uop
// rs1!=x0, normal
// uop0: r(rs1), w(vconfig) | x[rs1],vtypei -> vconfig
// uop1: r(rs1), w(rd) | x[rs1],vtypei -> x[rd]
def uvsetvcfg_xi = "b1010_0000".U
def uvsetrd_xi = "b1000_0000".U
// rs1==x0, rd!=x0, set vl to vlmax, set rd to vlmax, set vtype
// uop0: w(vconfig) | vlmax, vtypei -> vconfig
// uop1: w(rd) | vlmax, vtypei -> x[rd]
def uvsetvcfg_vlmax_i = "b1010_0001".U
def uvsetrd_vlmax_i = "b1000_0001".U
// rs1==x0, rd==x0, keep vl, set vtype
// uop0: r(vconfig), w(vconfig) | ld_vconfig.vl, vtypei -> vconfig
def uvsetvcfg_keep_v = "b1010_0010".U
// vsetvl's uop
// rs1!=x0, normal
// uop0: r(rs1,rs2), w(vconfig) | x[rs1],x[rs2] -> vconfig
// uop1: r(rs1,rs2), w(rd) | x[rs1],x[rs2] -> x[rd]
def uvsetvcfg_xx = "b0110_0000".U
def uvsetrd_xx = "b0100_0000".U
// rs1==x0, rd!=x0, set vl to vlmax, set rd to vlmax, set vtype
// uop0: r(rs2), w(vconfig) | vlmax, vtypei -> vconfig
// uop1: r(rs2), w(rd) | vlmax, vtypei -> x[rd]
def uvsetvcfg_vlmax_x = "b0110_0001".U
def uvsetrd_vlmax_x = "b0100_0001".U
// rs1==x0, rd==x0, keep vl, set vtype
// uop0: r(rs2), w(vtmp) | x[rs2] -> vtmp
// uop0: r(vconfig,vtmp), w(vconfig) | old_vconfig.vl, vtmp -> vconfig
def uvmv_v_x = "b0110_0010".U
def uvsetvcfg_vv = "b0111_0010".U
// vsetivli's uop
// uop0: w(vconfig) | vli, vtypei -> vconfig
// uop1: w(rd) | vli, vtypei -> x[rd]
def uvsetvcfg_ii = "b0010_0000".U
def uvsetrd_ii = "b0000_0000".U
def isVsetvl (func: UInt) = func(6)
def isVsetvli (func: UInt) = func(7)
def isVsetivli(func: UInt) = func(7, 6) === 0.U
def isNormal (func: UInt) = func(1, 0) === 0.U
def isSetVlmax(func: UInt) = func(0)
def isKeepVl (func: UInt) = func(1)
// RG: region
def writeIntRG(func: UInt) = !func(5)
def writeVecRG(func: UInt) = func(5)
def readIntRG (func: UInt) = !func(4)
def readVecRG (func: UInt) = func(4)
// Todo: @fdy fix it
def convert2uvsetvl(func: UInt) = Cat(func(7, 3), "b1".U, func(1, 0))
def convert2oldvl(func: UInt) = Cat(func(7, 4), "b1".U, func(2, 0))
def convert2vlmax(func: UInt) = Cat(func(7, 5), "b1".U, func(3, 0))
......
package xiangshan.backend.fu
import chisel3._
import chiseltest.{ChiselScalatestTester, _}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.must.Matchers
import top.DefaultConfig
import xiangshan.backend.fu.vector.Bundles.{VLmul, VSew}
import xiangshan.{VSETOpType, XSCoreParameters, XSCoreParamsKey, XSTileKey}
class VsetModuleMain extends AnyFlatSpec with ChiselScalatestTester with Matchers {
val defaultConfig = (new DefaultConfig).alterPartial({
case XSCoreParamsKey => XSCoreParameters()
})
def F = false.B
def T = true.B
private val (ill, vta, vma, vsew, vlmul) = (F, F, F, VSew.e8, VLmul.m8)
private val avl = 30.U
println("Test started!")
behavior of "VsetModule"
it should "run" in {
test(new VsetModule()(defaultConfig)) { m: VsetModule =>
m.io.in.func.poke(VSETOpType.uvsetvcfg_xi)
m.io.in.avl.poke(avl)
m.io.in.vtype.illegal.poke(ill)
m.io.in.vtype.vta.poke(vta)
m.io.in.vtype.vma.poke(vma)
m.io.in.vtype.vsew.poke(vsew)
m.io.in.vtype.vlmul.poke(vlmul)
m.io.in.oldVl.poke(0)
m.io.out.vconfig.vtype.illegal.expect(false.B)
m.io.out.vconfig.vtype.vta.expect(vta)
m.io.out.vconfig.vtype.vma.expect(vma)
m.io.out.vconfig.vtype.vsew.expect(vsew)
m.io.out.vconfig.vtype.vlmul.expect(vlmul)
m.io.out.vconfig.vl.expect((32).U)
println(s"log2Vlmax : ${m.io.testOut.log2Vlmax.peek().litValue}")
println(s"vlmax : ${m.io.testOut.vlmax.peek().litValue} ")
println(s"vta: ${m.io.out.vconfig.vtype.vta.peek().litToBoolean} ")
println(s"vma: ${m.io.out.vconfig.vtype.vma.peek().litToBoolean} ")
println(s"vsew: ${m.io.out.vconfig.vtype.vsew.peek().litValue} ")
println(s"vlmul: ${m.io.out.vconfig.vtype.vlmul.peek().litValue} ")
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册