xref: /XiangShan/src/main/scala/xiangshan/backend/decode/VTypeGen.scala (revision f7fe02a801cbb5cab6a7cbe4887f1f5bf2aec0ff)
1package xiangshan.backend.decode
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import xiangshan._
7import xiangshan.backend.fu.vector.Bundles.{VType, VsetVType}
8import xiangshan.backend.decode.isa.bitfield.{InstVType, Riscv32BitInst, XSInstBitFields}
9import xiangshan.backend.fu.VsetModule
10
11/**
12 * IO of VTypeGen
13 */
14class VTypeGenIO(implicit p: Parameters) extends XSBundle {
15  val insts = Flipped(Vec(DecodeWidth, ValidIO(UInt(32.W))))
16  val walkToArchVType = Input(Bool())
17  val walkVType   = Flipped(Valid(new VType))
18  val canUpdateVType = Input(Bool())
19  val vtype = Output(new VType)
20  val vsetvlVType = Input(new VType)
21  val commitVType = new Bundle {
22    val vtype = Flipped(Valid(new VType))
23    val hasVsetvl = Input(Bool())
24  }
25}
26/**
27 * Vtype is the vector configuration register, which is the main part of vector extension.
28 * It contains the vector length and the vector mask. This class is a module that generates vtype for each instruction.
29 */
30class VTypeGen(implicit p: Parameters) extends XSModule{
31  val io = IO(new VTypeGenIO)
32  /** valid signals of instructions */
33  private val instValidVec = io.insts.map(_.valid)
34  /** instructions code */
35  private val instFieldVec = io.insts.map(_.bits.asTypeOf(new XSInstBitFields))
36  // Only check vsetvli and vsetivli here.
37  // vsetvl will flush pipe, need not to generate new vtype in decode stage.
38  private val isVsetVec = VecInit(instFieldVec.map(fields =>
39    (fields.OPCODE === "b1010111".U) && (fields.WIDTH === "b111".U) && (
40      fields.ALL(31) === "b0".U ||
41      fields.ALL(31, 30) === "b11".U
42    )
43  ).zip(instValidVec).map { case (isVset, valid) => valid && isVset})
44
45  /** one-hot encoded first vset instruction's location */
46  private val firstVsetOH: Vec[Bool] = VecInit(PriorityEncoderOH(isVsetVec))
47  /** instruction field of first vset instruction */
48  private val firstVsetInstField: XSInstBitFields = PriorityMux(firstVsetOH, instFieldVec)
49
50  /** first vset instruction is a vsetvli */
51  private val isVsetvli= (firstVsetInstField.OPCODE === "b1010111".U) &&
52    (firstVsetInstField.WIDTH === "b111".U) &&
53    (firstVsetInstField.ALL(31) === "b0".U)
54
55  /** register of vtype in architectural state */
56  private val vtypeArch = RegInit(VType.initVtype())
57  /** register of vtype in speculative state */
58  private val vtypeSpec = RegInit(VType.initVtype())
59
60  /** next register of vtype in architectural state */
61  private val vtypeArchNext = WireInit(vtypeArch)
62  /** next register of vtype in architectural state */
63  private val vtypeSpecNext = WireInit(vtypeSpec)
64
65  vtypeArch := vtypeArchNext
66  vtypeSpec := vtypeSpecNext
67
68  /** New vtype field set by new vset instruction. Set vtype according to instruction type of vset */
69  private val instVType: InstVType = Mux(isVsetvli, firstVsetInstField.ZIMM_VSETVLI.asTypeOf(new InstVType),
70    firstVsetInstField.ZIMM_VSETIVLI.asTypeOf(new InstVType))
71  /** Convert InstVType to VsetVType */
72  private val vtypei: VsetVType = VsetVType.fromInstVType(instVType)
73
74  /** New vtype configuration set by new vset instruction. */
75  private val vsetModule = Module(new VsetModule)
76  vsetModule.io.in.avl := 0.U
77  vsetModule.io.in.vtype := vtypei
78  vsetModule.io.in.func := VSETOpType.uvsetvcfg_xi
79
80  /** New vtype generated by vsetModule */
81  private val vtypeNew = vsetModule.io.out.vconfig.vtype
82
83  /** Set the source of vtypeArch from commit instructions */
84  when(io.commitVType.hasVsetvl) {
85    vtypeArchNext := io.vsetvlVType
86  }.elsewhen(io.commitVType.vtype.valid) {
87    vtypeArchNext := io.commitVType.vtype.bits
88  }
89
90  /** whether there is a vset instruction among input instructions */
91  private val inHasVset = isVsetVec.asUInt.orR
92
93  /**
94   * Set the source of vtypeSpec from the following sources:
95   * 1. committed vsetvl instruction, which flushes the pipeline.
96   * 2. walk-vtype, which is used to update vtype when walking.
97   * 3. walking to architectural vtype
98   * 4. new vset instruction
99   */
100  when(io.commitVType.hasVsetvl) {
101    // when vsetvl instruction commit, also update vtypeSpec, because vsetvl flush pipe
102    vtypeSpecNext := io.vsetvlVType
103  }.elsewhen(io.walkVType.valid) {
104    vtypeSpecNext := io.walkVType.bits
105  }.elsewhen(io.walkToArchVType) {
106    vtypeSpecNext := vtypeArch
107  }.elsewhen(inHasVset && io.canUpdateVType) {
108    vtypeSpecNext := vtypeNew
109  }
110
111  /** pass speculative vtype to output */
112  io.vtype := vtypeSpec
113
114  // just make verilog more readable
115  dontTouch(isVsetVec)
116}
117