188825c5cSYinan Xu/*************************************************************************************** 288825c5cSYinan Xu* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 388825c5cSYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory 488825c5cSYinan Xu* 588825c5cSYinan Xu* XiangShan is licensed under Mulan PSL v2. 688825c5cSYinan Xu* You can use this software according to the terms and conditions of the Mulan PSL v2. 788825c5cSYinan Xu* You may obtain a copy of Mulan PSL v2 at: 888825c5cSYinan Xu* http://license.coscl.org.cn/MulanPSL2 988825c5cSYinan Xu* 1088825c5cSYinan Xu* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 1188825c5cSYinan Xu* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 1288825c5cSYinan Xu* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 1388825c5cSYinan Xu* 1488825c5cSYinan Xu* See the Mulan PSL v2 for more details. 1588825c5cSYinan Xu***************************************************************************************/ 1688825c5cSYinan Xu 1788825c5cSYinan Xupackage xiangshan.backend.decode 1888825c5cSYinan Xu 198891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 2088825c5cSYinan Xuimport chisel3._ 2188825c5cSYinan Xuimport chisel3.util._ 22361e6d51SJiuyang Liuimport freechips.rocketchip.rocket.Instructions 233c02ee8fSwakafaimport utility._ 243b739f49SXuan Huimport utils._ 25361e6d51SJiuyang Liuimport xiangshan._ 26730cfbc0SXuan Huimport xiangshan.backend.fu.FuType 27730cfbc0SXuan Huimport xiangshan.backend.Bundles.DecodedInst 2898cfe81bSxgkiriimport xiangshan.backend.decode.isa.bitfield.XSInstBitFields 2988825c5cSYinan Xu 306535afbbSYinan Xuabstract class BaseFusionCase(pair: Seq[Valid[UInt]])(implicit p: Parameters) 3188825c5cSYinan Xu extends DecodeUnitConstants { 3288825c5cSYinan Xu require(pair.length == 2) 3388825c5cSYinan Xu 3498cfe81bSxgkiri protected val inst1: XSInstBitFields = instr(0).asTypeOf(new XSInstBitFields) 3598cfe81bSxgkiri protected val inst2: XSInstBitFields = instr(1).asTypeOf(new XSInstBitFields) 3698cfe81bSxgkiri 3788825c5cSYinan Xu protected def instr: Seq[UInt] = pair.map(_.bits) 38a0db5a4bSYinan Xu protected def pairValid: Bool = VecInit(pair.map(_.valid)).asUInt.andR 3998cfe81bSxgkiri protected def instr1Rs1: UInt = inst1.RS1 4098cfe81bSxgkiri protected def instr1Rs2: UInt = inst1.RS2 4198cfe81bSxgkiri protected def instr1Rd: UInt = inst1.RD 4298cfe81bSxgkiri def instr2Rs1: UInt = inst2.RS1 4398cfe81bSxgkiri def instr2Rs2: UInt = inst2.RS2 4498cfe81bSxgkiri protected def instr2Rd: UInt = inst2.RD 4588825c5cSYinan Xu protected def withSameDest: Bool = instr1Rd === instr2Rd 46a0db5a4bSYinan Xu def destToRs1: Bool = instr1Rd === instr2Rs1 4788825c5cSYinan Xu protected def destToRs2: Bool = instr1Rd === instr2Rs2 480de3199cSsinsanction protected def instr2Rs1ToRs2: Bool = instr2Rs1 === instr2Rs2 4988825c5cSYinan Xu 50a0db5a4bSYinan Xu protected def getInstrTable(pat: BitPat): List[BitPat] = { 51a0db5a4bSYinan Xu // Only these instructions can be fused now 52768f5f91SYangyu Chen val allDecodeTable = XDecode.table ++ BitmanipDecode.table ++ ScalarCryptoDecode.table 53a0db5a4bSYinan Xu allDecodeTable.filter(_._1 == pat).map(_._2).head 5488825c5cSYinan Xu } 55a0db5a4bSYinan Xu // Must sync these indices with MicroOp.decode 56a0db5a4bSYinan Xu protected def getInstrFuType(pat: BitPat): BitPat = getInstrTable(pat)(3) 57a0db5a4bSYinan Xu protected def getInstrFuOpType(pat: BitPat): BitPat = getInstrTable(pat)(4) 58a0db5a4bSYinan Xu protected def getInstrSrc1Type(pat: BitPat): BitPat = getInstrTable(pat)(0) 59a0db5a4bSYinan Xu protected def getInstrSrc2Type(pat: BitPat): BitPat = getInstrTable(pat)(1) 6088825c5cSYinan Xu 6188825c5cSYinan Xu def isValid: Bool 62a0db5a4bSYinan Xu // To optimize the timing, only these control signals can be affected by instruction fusion. 63a0db5a4bSYinan Xu def thisInstr: Option[BitPat] = None 64a0db5a4bSYinan Xu def fusedInstr: Option[BitPat] = None 65a0db5a4bSYinan Xu // By default, None means unchanged. 66a0db5a4bSYinan Xu private def compareAndGet(func: BitPat => BitPat): Option[Int] = { 67a0db5a4bSYinan Xu if (fusedInstr.isDefined) { 68a0db5a4bSYinan Xu require(thisInstr.isDefined, "thisInstr must be defined to infer the ctrl signals") 69a0db5a4bSYinan Xu val fused = func(fusedInstr.get) 70a0db5a4bSYinan Xu // Only when the two instructions have different control field, we make it not None. 71a0db5a4bSYinan Xu if (fused != func(thisInstr.get)) Some(fused.value.toInt) else None 72a0db5a4bSYinan Xu } else None 73a0db5a4bSYinan Xu } 74a0db5a4bSYinan Xu // We assume only fuType, fuOpType, lsrc2 may be changed now. 75a0db5a4bSYinan Xu def fuType: Option[Int] = compareAndGet(getInstrFuType) 76a0db5a4bSYinan Xu def fuOpType: Option[UInt => UInt] = { 77a0db5a4bSYinan Xu val t = compareAndGet(getInstrFuOpType) 78a0db5a4bSYinan Xu if (t.isDefined) Some((_: UInt) => t.get.U) else None 79a0db5a4bSYinan Xu } 80a0db5a4bSYinan Xu def src2Type: Option[Int] = compareAndGet(getInstrSrc2Type) 81fe528fd6Ssinsanction def selImm: Option[UInt] = None 82a0db5a4bSYinan Xu def lsrc2NeedZero: Boolean = false 83a0db5a4bSYinan Xu def lsrc2NeedMux: Boolean = false 840febc381SYinan Xu def lsrc2MuxResult: UInt = Mux(destToRs1, instr2Rs2, instr2Rs1) 85a0db5a4bSYinan Xu 8688825c5cSYinan Xu def fusionName: String 8788825c5cSYinan Xu} 8888825c5cSYinan Xu 89a0db5a4bSYinan Xu// There are 2 types of instruction fusion. 90a0db5a4bSYinan Xu// (1) fused into a fixed new instruction with new control signals. 91a0db5a4bSYinan Xu// (2) the first instruction's op is replaced with another one. 92a0db5a4bSYinan Xu 9388825c5cSYinan Xu// Case: clear upper 32 bits / get lower 32 bits 9488825c5cSYinan Xu// Source: `slli r1, r0, 32` + `srli r1, r1, 32` 9588825c5cSYinan Xu// Target: `add.uw r1, r0, zero` (pseudo instruction: `zext.w r1, r0`) 9688825c5cSYinan Xuclass FusedAdduw(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 9798cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SLLI && inst1.SHAMT6 === 32.U 9898cfe81bSxgkiri def inst2Cond = instr(1) === Instructions.SRLI && inst2.SHAMT6 === 32.U 9988825c5cSYinan Xu 10088825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && destToRs1 101a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.SLLI) 102a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.ADD_UW) 103a0db5a4bSYinan Xu override def lsrc2NeedZero: Boolean = true 10488825c5cSYinan Xu 10588825c5cSYinan Xu def fusionName: String = "slli32_srli32" 10688825c5cSYinan Xu} 10788825c5cSYinan Xu 10888825c5cSYinan Xu// Case: clear upper 48 bits / get lower 16 bits 10988825c5cSYinan Xu// Source: `slli r1, r0, 48` + `srli r1, r1, 48` 11088825c5cSYinan Xu// Target: `zext.h r1, r0` 11188825c5cSYinan Xuclass FusedZexth(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 11298cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SLLI && inst1.SHAMT6 === 48.U 11398cfe81bSxgkiri def inst2Cond = instr(1) === Instructions.SRLI && inst2.SHAMT6 === 48.U 11488825c5cSYinan Xu 11588825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && destToRs1 116a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.SLLI) 117a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.PACKW) 118a0db5a4bSYinan Xu override def lsrc2NeedZero: Boolean = true 11988825c5cSYinan Xu 12088825c5cSYinan Xu def fusionName: String = "slli48_srli48" 12188825c5cSYinan Xu} 12288825c5cSYinan Xu 12388825c5cSYinan Xu// Another case of Zext.h 12488825c5cSYinan Xu// Source: `slliw r1, r0, 16` + `srliw r1, r1, 16` 12588825c5cSYinan Xu// Target: `zext.h r1, r0` 12688825c5cSYinan Xuclass FusedZexth1(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends FusedZexth(pair) { 12798cfe81bSxgkiri override def inst1Cond: Bool = instr(0) === Instructions.SLLIW && inst1.SHAMT5 === 16.U 12898cfe81bSxgkiri override def inst2Cond: Bool = instr(1) === Instructions.SRLIW && inst2.SHAMT5 === 16.U 12988825c5cSYinan Xu 130a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.SLLIW) 131a0db5a4bSYinan Xu 13288825c5cSYinan Xu override def fusionName: String = "slliw16_srliw16" 13388825c5cSYinan Xu} 13488825c5cSYinan Xu 13588825c5cSYinan Xu// Case: sign-extend a 16-bit number 13688825c5cSYinan Xu// Source: `slliw r1, r0, 16` + `sraiw r1, r1, 16` 13788825c5cSYinan Xu// Target: `sext.h r1, r0` 13888825c5cSYinan Xuclass FusedSexth(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 13998cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SLLIW && inst1.SHAMT5 === 16.U 14098cfe81bSxgkiri def inst2Cond = instr(1) === Instructions.SRAIW && inst2.SHAMT5 === 16.U 14188825c5cSYinan Xu 14288825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && destToRs1 143a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.SLLIW) 144a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.SEXT_H) 145a0db5a4bSYinan Xu override def lsrc2NeedZero: Boolean = true 14688825c5cSYinan Xu 14788825c5cSYinan Xu def fusionName: String = "slliw16_sraiw16" 14888825c5cSYinan Xu} 14988825c5cSYinan Xu 15088825c5cSYinan Xu// Case: shift left by one and add 15188825c5cSYinan Xu// Source: `slli r1, r0, 1` + `add r1, r1, r2` 15288825c5cSYinan Xu// Target: `sh1add r1, r0, r2` 15388825c5cSYinan Xuclass FusedSh1add(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 15498cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SLLI && inst1.SHAMT6 === 1.U 1550de3199cSsinsanction def inst2Cond = instr(1) === Instructions.ADD && !instr2Rs1ToRs2 15688825c5cSYinan Xu 15788825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && (destToRs1 || destToRs2) 158a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.SLLI) 159a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.SH1ADD) 160a0db5a4bSYinan Xu override def lsrc2NeedMux: Boolean = true 16188825c5cSYinan Xu 16288825c5cSYinan Xu def fusionName: String = "slli1_add" 16388825c5cSYinan Xu} 16488825c5cSYinan Xu 16588825c5cSYinan Xu// Case: shift left by two and add 16688825c5cSYinan Xu// Source: `slli r1, r0, 2` + `add r1, r1, r2` 16788825c5cSYinan Xu// Target: `sh2add r1, r0, r2` 16888825c5cSYinan Xuclass FusedSh2add(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 16998cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SLLI && inst1.SHAMT6 === 2.U 1700de3199cSsinsanction def inst2Cond = instr(1) === Instructions.ADD && !instr2Rs1ToRs2 17188825c5cSYinan Xu 17288825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && (destToRs1 || destToRs2) 173a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.SLLI) 174a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.SH2ADD) 175a0db5a4bSYinan Xu override def lsrc2NeedMux: Boolean = true 17688825c5cSYinan Xu 17788825c5cSYinan Xu def fusionName: String = "slli2_add" 17888825c5cSYinan Xu} 17988825c5cSYinan Xu 18088825c5cSYinan Xu// Case: shift left by three and add 18188825c5cSYinan Xu// Source: `slli r1, r0, 3` + `add r1, r1, r2` 18288825c5cSYinan Xu// Target: `sh3add r1, r0, r2` 18388825c5cSYinan Xuclass FusedSh3add(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 18498cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SLLI && inst1.SHAMT6 === 3.U 1850de3199cSsinsanction def inst2Cond = instr(1) === Instructions.ADD && !instr2Rs1ToRs2 18688825c5cSYinan Xu 18788825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && (destToRs1 || destToRs2) 188a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.SLLI) 189a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.SH3ADD) 190a0db5a4bSYinan Xu override def lsrc2NeedMux: Boolean = true 19188825c5cSYinan Xu 19288825c5cSYinan Xu def fusionName: String = "slli3_add" 19388825c5cSYinan Xu} 19488825c5cSYinan Xu 19588825c5cSYinan Xu// Case: shift zero-extended word left by one 196a0db5a4bSYinan Xu// Source: `slli r1, r0, 32` + `srli r1, r1, 31` 19788825c5cSYinan Xu// Target: `szewl1 r1, r0` (customized internal opcode) 19888825c5cSYinan Xuclass FusedSzewl1(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 19998cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SLLI && inst1.SHAMT6 === 32.U 20098cfe81bSxgkiri def inst2Cond = instr(1) === Instructions.SRLI && inst2.SHAMT6 === 31.U 20188825c5cSYinan Xu 20288825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && destToRs1 203a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.szewl1) 20488825c5cSYinan Xu 20588825c5cSYinan Xu def fusionName: String = "slli32_srli31" 20688825c5cSYinan Xu} 20788825c5cSYinan Xu 20888825c5cSYinan Xu// Case: shift zero-extended word left by two 209a0db5a4bSYinan Xu// Source: `slli r1, r0, 32` + `srli r1, r1, 30` 21088825c5cSYinan Xu// Target: `szewl2 r1, r0` (customized internal opcode) 21188825c5cSYinan Xuclass FusedSzewl2(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 21298cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SLLI && inst1.SHAMT6 === 32.U 21398cfe81bSxgkiri def inst2Cond = instr(1) === Instructions.SRLI && inst2.SHAMT6 === 30.U 21488825c5cSYinan Xu 21588825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && destToRs1 216a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.szewl2) 21788825c5cSYinan Xu 21888825c5cSYinan Xu def fusionName: String = "slli32_srli30" 21988825c5cSYinan Xu} 22088825c5cSYinan Xu 221a792bcf1SYinan Xu// Case: shift zero-extended word left by three 222a0db5a4bSYinan Xu// Source: `slli r1, r0, 32` + `srli r1, r1, 29` 223a792bcf1SYinan Xu// Target: `szewl3 r1, r0` (customized internal opcode) 224a792bcf1SYinan Xuclass FusedSzewl3(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 22598cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SLLI && inst1.SHAMT6 === 32.U 22698cfe81bSxgkiri def inst2Cond = instr(1) === Instructions.SRLI && inst2.SHAMT6 === 29.U 227a792bcf1SYinan Xu 228a792bcf1SYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && destToRs1 229a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.szewl3) 230a792bcf1SYinan Xu 231a792bcf1SYinan Xu def fusionName: String = "slli32_srli29" 232a792bcf1SYinan Xu} 233a792bcf1SYinan Xu 23488825c5cSYinan Xu// Case: get the second byte 23588825c5cSYinan Xu// Source: `srli r1, r0, 8` + `andi r1, r1, 255` 23688825c5cSYinan Xu// Target: `byte2 r1, r0` (customized internal opcode) 23788825c5cSYinan Xuclass FusedByte2(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 23898cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SRLI && inst1.SHAMT6 === 8.U 23998cfe81bSxgkiri def inst2Cond = instr(1) === Instructions.ANDI && inst2.IMM12 === 255.U 24088825c5cSYinan Xu 24188825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && destToRs1 242a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.byte2) 24388825c5cSYinan Xu 24488825c5cSYinan Xu def fusionName: String = "srli8_andi255" 24588825c5cSYinan Xu} 24688825c5cSYinan Xu 24788825c5cSYinan Xu// Case: shift left by four and add 24888825c5cSYinan Xu// Source: `slli r1, r0, 4` + `add r1, r1, r2` 24988825c5cSYinan Xu// Target: `sh4add r1, r0, r2` (customized internal opcode) 25088825c5cSYinan Xuclass FusedSh4add(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 25198cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SLLI && inst1.SHAMT6 === 4.U 2520de3199cSsinsanction def inst2Cond = instr(1) === Instructions.ADD && !instr2Rs1ToRs2 25388825c5cSYinan Xu 25488825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && (destToRs1 || destToRs2) 255a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.SLLI) 256a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.ADD) 257a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.sh4add) 258a0db5a4bSYinan Xu override def lsrc2NeedMux: Boolean = true 25988825c5cSYinan Xu 26088825c5cSYinan Xu def fusionName: String = "slli4_add" 26188825c5cSYinan Xu} 26288825c5cSYinan Xu 263a792bcf1SYinan Xu// Case: shift right by 29 and add 264a792bcf1SYinan Xu// Source: `srli r1, r0, 29` + `add r1, r1, r2` 265a792bcf1SYinan Xu// Target: `sr29add r1, r0, r2` (customized internal opcode) 266a792bcf1SYinan Xuclass FusedSr29add(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 26798cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SRLI && inst1.SHAMT6 === 29.U 2680de3199cSsinsanction def inst2Cond = instr(1) === Instructions.ADD && !instr2Rs1ToRs2 269a792bcf1SYinan Xu 270a792bcf1SYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && (destToRs1 || destToRs2) 271a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.SRLI) 272a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.ADD) 273a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.sr29add) 274a0db5a4bSYinan Xu override def lsrc2NeedMux: Boolean = true 275a792bcf1SYinan Xu 276a792bcf1SYinan Xu def fusionName: String = "srli29_add" 277a792bcf1SYinan Xu} 278a792bcf1SYinan Xu 27988825c5cSYinan Xu// Case: shift right by 30 and add 28088825c5cSYinan Xu// Source: `srli r1, r0, 30` + `add r1, r1, r2` 28188825c5cSYinan Xu// Target: `sr30add r1, r0, r2` (customized internal opcode) 28288825c5cSYinan Xuclass FusedSr30add(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 28398cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SRLI && inst1.SHAMT6 === 30.U 2840de3199cSsinsanction def inst2Cond = instr(1) === Instructions.ADD && !instr2Rs1ToRs2 28588825c5cSYinan Xu 28688825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && (destToRs1 || destToRs2) 287a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.SRLI) 288a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.ADD) 289a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.sr30add) 290a0db5a4bSYinan Xu override def lsrc2NeedMux: Boolean = true 29188825c5cSYinan Xu 29288825c5cSYinan Xu def fusionName: String = "srli30_add" 29388825c5cSYinan Xu} 29488825c5cSYinan Xu 29588825c5cSYinan Xu// Case: shift right by 31 and add 29688825c5cSYinan Xu// Source: `srli r1, r0, 31` + `add r1, r1, r2` 29788825c5cSYinan Xu// Target: `sr31add r1, r0, r2` (customized internal opcode) 29888825c5cSYinan Xuclass FusedSr31add(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 29998cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SRLI && inst1.SHAMT6 === 31.U 3000de3199cSsinsanction def inst2Cond = instr(1) === Instructions.ADD && !instr2Rs1ToRs2 30188825c5cSYinan Xu 30288825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && (destToRs1 || destToRs2) 303a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.SRLI) 304a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.ADD) 305a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.sr31add) 306a0db5a4bSYinan Xu override def lsrc2NeedMux: Boolean = true 30788825c5cSYinan Xu 30888825c5cSYinan Xu def fusionName: String = "srli31_add" 30988825c5cSYinan Xu} 31088825c5cSYinan Xu 31188825c5cSYinan Xu// Case: shift right by 32 and add 31288825c5cSYinan Xu// Source: `srli r1, r0, 32` + `add r1, r1, r2` 31388825c5cSYinan Xu// Target: `sr32add r1, r0, r2` (customized internal opcode) 31488825c5cSYinan Xuclass FusedSr32add(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 31598cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.SRLI && inst1.SHAMT6 === 32.U 3160de3199cSsinsanction def inst2Cond = instr(1) === Instructions.ADD && !instr2Rs1ToRs2 31788825c5cSYinan Xu 31888825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && (destToRs1 || destToRs2) 319a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.SRLI) 320a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.ADD) 321a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.sr32add) 322a0db5a4bSYinan Xu override def lsrc2NeedMux: Boolean = true 32388825c5cSYinan Xu 32488825c5cSYinan Xu def fusionName: String = "srli32_add" 32588825c5cSYinan Xu} 32688825c5cSYinan Xu 32788825c5cSYinan Xu// Case: add one if odd, otherwise unchanged 32888825c5cSYinan Xu// Source: `andi r1, r0, 1`` + `add r1, r1, r2` 32988825c5cSYinan Xu// Target: `oddadd r1, r0, r2` (customized internal opcode) 33088825c5cSYinan Xuclass FusedOddadd(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 33198cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.ANDI && inst1.IMM12 === 1.U 3320de3199cSsinsanction def inst2Cond = instr(1) === Instructions.ADD && !instr2Rs1ToRs2 33388825c5cSYinan Xu 33488825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && (destToRs1 || destToRs2) 335a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.ANDI) 336a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.ADD) 337a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.oddadd) 338a0db5a4bSYinan Xu override def lsrc2NeedMux: Boolean = true 33988825c5cSYinan Xu 34088825c5cSYinan Xu def fusionName: String = "andi1_add" 34188825c5cSYinan Xu} 34288825c5cSYinan Xu 34388825c5cSYinan Xu// Case: add one if odd (in word format), otherwise unchanged 34488825c5cSYinan Xu// Source: `andi r1, r0, 1`` + `addw r1, r1, r2` 34588825c5cSYinan Xu// Target: `oddaddw r1, r0, r2` (customized internal opcode) 34688825c5cSYinan Xuclass FusedOddaddw(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 34798cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.ANDI && inst1.IMM12 === 1.U 3480de3199cSsinsanction def inst2Cond = instr(1) === Instructions.ADDW && !instr2Rs1ToRs2 34988825c5cSYinan Xu 35088825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && (destToRs1 || destToRs2) 351a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.ANDI) 352a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.ADD) 353a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.oddaddw) 354a0db5a4bSYinan Xu override def lsrc2NeedMux: Boolean = true 35588825c5cSYinan Xu 35688825c5cSYinan Xu def fusionName: String = "andi1_addw" 35788825c5cSYinan Xu} 35888825c5cSYinan Xu 35988825c5cSYinan Xu// Case: addw and extract its lower 8 bits (fused into addwbyte) 360a0db5a4bSYinan Xuclass FusedAddwbyte(pair: Seq[Valid[UInt]])(implicit p: Parameters) 3616535afbbSYinan Xu extends BaseFusionCase(pair) { 3626535afbbSYinan Xu // the first instruction is a ALUOpType.addw 3636535afbbSYinan Xu // According to DecodeUnit.scala, only ADDIW and ADDW are ALUOpType.addw, which are used for inst1Cond. 3648a009b1dSLi Qianruo def inst1Cond = instr(0) === Instructions.ADDIW || instr(0) === Instructions.ADDW 36598cfe81bSxgkiri def inst2Cond = instr(1) === Instructions.ANDI && inst2.IMM12 === 0xff.U 36688825c5cSYinan Xu 36788825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && destToRs1 368a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.addwbyte) 36988825c5cSYinan Xu 370675acc68SYinan Xu def fusionName: String = "addw_andi255" 37188825c5cSYinan Xu} 37288825c5cSYinan Xu 37388825c5cSYinan Xu// Case: addw and extract its lower 1 bit (fused into addwbit) 374a0db5a4bSYinan Xuclass FusedAddwbit(pair: Seq[Valid[UInt]])(implicit p: Parameters) 375a0db5a4bSYinan Xu extends FusedAddwbyte(pair) { 376675acc68SYinan Xu 37798cfe81bSxgkiri override def inst2Cond = instr(1) === Instructions.ANDI && inst2.IMM12 === 0x1.U 378a0db5a4bSYinan Xu 379a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.addwbit) 380675acc68SYinan Xu 381675acc68SYinan Xu override def fusionName: String = "addw_andi1" 382675acc68SYinan Xu} 383675acc68SYinan Xu 384675acc68SYinan Xu// Case: addw and zext.h (fused into addwzexth) 385a0db5a4bSYinan Xuclass FusedAddwzexth(pair: Seq[Valid[UInt]])(implicit p: Parameters) 386a0db5a4bSYinan Xu extends FusedAddwbyte(pair) { 387675acc68SYinan Xu 388675acc68SYinan Xu override def inst2Cond = instr(1) === Instructions.ZEXT_H 389a0db5a4bSYinan Xu 390a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.addwzexth) 391675acc68SYinan Xu 392675acc68SYinan Xu override def fusionName: String = "addw_zexth" 393675acc68SYinan Xu} 394675acc68SYinan Xu 395675acc68SYinan Xu// Case: addw and sext.h (fused into addwsexth) 396a0db5a4bSYinan Xuclass FusedAddwsexth(pair: Seq[Valid[UInt]])(implicit p: Parameters) 397a0db5a4bSYinan Xu extends FusedAddwbyte(pair) { 398675acc68SYinan Xu 399675acc68SYinan Xu override def inst2Cond = instr(1) === Instructions.SEXT_H 400a0db5a4bSYinan Xu 401a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.addwsexth) 402675acc68SYinan Xu 403675acc68SYinan Xu override def fusionName: String = "addw_sexth" 40488825c5cSYinan Xu} 40588825c5cSYinan Xu 40688825c5cSYinan Xu// Case: logic operation and extract its LSB 4076535afbbSYinan Xu 408a0db5a4bSYinan Xuclass FusedLogiclsb(pair: Seq[Valid[UInt]])(implicit p: Parameters) 4096535afbbSYinan Xu extends BaseFusionCase(pair) { 4106535afbbSYinan Xu // the first instruction is a logic (and, or, xor, orcb) 4116535afbbSYinan Xu // (1) def ANDI = BitPat("b?????????????????111?????0010011") 4126535afbbSYinan Xu // (2) def AND = BitPat("b0000000??????????111?????0110011") 4136535afbbSYinan Xu // (3) def ORI = BitPat("b?????????????????110?????0010011") 4146535afbbSYinan Xu // (4) def OR = BitPat("b0000000??????????110?????0110011") 4156535afbbSYinan Xu // (5) def XORI = BitPat("b?????????????????100?????0010011") 4166535afbbSYinan Xu // (6) def XOR = BitPat("b0000000??????????100?????0110011") 4176535afbbSYinan Xu // (7) def ORC_B = BitPat("b001010000111?????101?????0010011") 4186535afbbSYinan Xu val logicInstrList = Seq(Instructions.ANDI, Instructions.AND, Instructions.ORI, Instructions.OR, 4196535afbbSYinan Xu Instructions.XORI, Instructions.XOR, Instructions.ORC_B) 4206535afbbSYinan Xu def inst1Cond = VecInit(logicInstrList.map(_ === instr(0))).asUInt.orR 42198cfe81bSxgkiri def inst2Cond = instr(1) === Instructions.ANDI && inst2.IMM12 === 1.U 42288825c5cSYinan Xu 42388825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && destToRs1 424a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some(ALUOpType.logicToLsb) 42588825c5cSYinan Xu 42688825c5cSYinan Xu def fusionName: String = "logic_andi1" 42788825c5cSYinan Xu} 42888825c5cSYinan Xu 429a0db5a4bSYinan Xuclass FusedLogicZexth(pair: Seq[Valid[UInt]])(implicit p: Parameters) 430a0db5a4bSYinan Xu extends FusedLogiclsb(pair) { 431675acc68SYinan Xu 432675acc68SYinan Xu override def inst2Cond = instr(1) === Instructions.ZEXT_H 433a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some(ALUOpType.logicToZexth) 434675acc68SYinan Xu 435675acc68SYinan Xu override def fusionName: String = "logic_zexth" 436675acc68SYinan Xu} 437675acc68SYinan Xu 43888825c5cSYinan Xu// Case: OR(Cat(src1(63, 8), 0.U(8.W)), src2) 43988825c5cSYinan Xu// Source: `andi r1, r0, -256`` + `or r1, r1, r2` 44088825c5cSYinan Xuclass FusedOrh48(pair: Seq[Valid[UInt]])(implicit p: Parameters) extends BaseFusionCase(pair) { 44198cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.ANDI && inst1.IMM12 === 0xf00.U 4420de3199cSsinsanction def inst2Cond = instr(1) === Instructions.OR && !instr2Rs1ToRs2 44388825c5cSYinan Xu 44488825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && (destToRs1 || destToRs2) 445a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.ANDI) 446a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.OR) 447a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.orh48) 448a0db5a4bSYinan Xu override def lsrc2NeedMux: Boolean = true 44988825c5cSYinan Xu 45088825c5cSYinan Xu def fusionName: String = "andi_f00_or" 45188825c5cSYinan Xu} 45288825c5cSYinan Xu 45388825c5cSYinan Xu// Case: mul 7bit data with 32-bit data 45488825c5cSYinan Xu// Source: `andi r1, r0, 127`` + `mulw r1, r1, r2` 45588825c5cSYinan Xu// Target: `mulw7 r1, r0, r2` 4566535afbbSYinan Xuclass FusedMulw7(pair: Seq[Valid[UInt]])(implicit p: Parameters) 4576535afbbSYinan Xu extends BaseFusionCase(pair) { 45898cfe81bSxgkiri def inst1Cond = instr(0) === Instructions.ANDI && inst1.IMM12 === 127.U 4590de3199cSsinsanction def inst2Cond = instr(1) === Instructions.MULW && !instr2Rs1ToRs2 46088825c5cSYinan Xu 46188825c5cSYinan Xu def isValid: Bool = inst1Cond && inst2Cond && withSameDest && (destToRs1 || destToRs2) 462a0db5a4bSYinan Xu override def thisInstr: Option[BitPat] = Some(Instructions.ANDI) 463a0db5a4bSYinan Xu override def fusedInstr: Option[BitPat] = Some(Instructions.MULW) 464a0db5a4bSYinan Xu override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => MDUOpType.mulw7) 465a0db5a4bSYinan Xu override def lsrc2NeedMux: Boolean = true 46688825c5cSYinan Xu 46788825c5cSYinan Xu def fusionName: String = "andi127_mulw" 46888825c5cSYinan Xu} 46988825c5cSYinan Xu 470fe528fd6Ssinsanction// Case: get 32 bits imm 471fe528fd6Ssinsanction// Source: `lui r1, 0xffffa`` + `addi r1, r1, 1` 472fe528fd6Ssinsanction// Target: `lui32 r1, 0xffffa001` (customized internal opcode) 473fe528fd6Ssinsanctionclass FusedLui32(pair: Seq[Valid[UInt]])(implicit p: Parameters) 474fe528fd6Ssinsanction extends BaseFusionCase(pair) { 475fe528fd6Ssinsanction def inst1Cond = instr(0) === Instructions.LUI 476fe528fd6Ssinsanction def inst2Cond = instr(1) === Instructions.ADDI 477fe528fd6Ssinsanction 478fe528fd6Ssinsanction def isValid: Bool = inst1Cond && inst2Cond && withSameDest && destToRs1 479fe528fd6Ssinsanction 480fe528fd6Ssinsanction override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.lui32add) 481fe528fd6Ssinsanction override def selImm: Option[UInt] = Some(SelImm.IMM_LUI32) 482fe528fd6Ssinsanction 483fe528fd6Ssinsanction def fusionName: String = "lui_addi" 484fe528fd6Ssinsanction 485765e58c6Ssinsanction XSDebug(isValid, p"[fusedLui32] instr0=${Hexadecimal(instr(0))} instr1=${Hexadecimal(instr(1))}\n") 486fe528fd6Ssinsanction} 487fe528fd6Ssinsanction 48854711376Ssinsanction// Case: get 32 bits imm (in word format) 48954711376Ssinsanction// Source: `lui r1, 0xffffa`` + `addiw r1, r1, 1` 49054711376Ssinsanction// Target: `lui32 r1, 0xffffa001` (customized internal opcode) 49154711376Ssinsanctionclass FusedLui32w(pair: Seq[Valid[UInt]])(implicit p: Parameters) 49254711376Ssinsanction extends BaseFusionCase(pair) { 49354711376Ssinsanction def inst1Cond = instr(0) === Instructions.LUI 49454711376Ssinsanction def inst2Cond = instr(1) === Instructions.ADDIW 49554711376Ssinsanction 49654711376Ssinsanction def isValid: Bool = inst1Cond && inst2Cond && withSameDest && destToRs1 49754711376Ssinsanction 49854711376Ssinsanction override def fuOpType: Option[UInt => UInt] = Some((_: UInt) => ALUOpType.lui32addw) 49954711376Ssinsanction override def selImm: Option[UInt] = Some(SelImm.IMM_LUI32) 50054711376Ssinsanction 50154711376Ssinsanction def fusionName: String = "lui_addiw" 50254711376Ssinsanction 503765e58c6Ssinsanction XSDebug(isValid, p"[fusedLui32w] instr0=${Hexadecimal(instr(0))} instr1=${Hexadecimal(instr(1))}\n") 50454711376Ssinsanction} 50554711376Ssinsanction 506a0db5a4bSYinan Xuclass FusionDecodeInfo extends Bundle { 507a0db5a4bSYinan Xu val rs2FromRs1 = Output(Bool()) 508a0db5a4bSYinan Xu val rs2FromRs2 = Output(Bool()) 509a0db5a4bSYinan Xu val rs2FromZero = Output(Bool()) 510a0db5a4bSYinan Xu} 511a0db5a4bSYinan Xu 512ad5c9e6eSJunxiong Jiclass FusionDecodeReplace(implicit p: Parameters) extends XSBundle { 5130febc381SYinan Xu val fuType = Valid(FuType()) 5140febc381SYinan Xu val fuOpType = Valid(FuOpType()) 515ad5c9e6eSJunxiong Ji val lsrc2 = Valid(UInt(LogicRegsWidth.W)) 5160febc381SYinan Xu val src2Type = Valid(SrcType()) 517fe528fd6Ssinsanction val selImm = Valid(SelImm()) 5180febc381SYinan Xu 5193b739f49SXuan Hu def update(cs: DecodedInst): Unit = { 5200febc381SYinan Xu when (fuType.valid) { 5210febc381SYinan Xu cs.fuType := fuType.bits 5220febc381SYinan Xu } 5230febc381SYinan Xu when (fuOpType.valid) { 5240febc381SYinan Xu cs.fuOpType := fuOpType.bits 5250febc381SYinan Xu } 5260febc381SYinan Xu when (lsrc2.valid) { 5270febc381SYinan Xu cs.lsrc(1) := lsrc2.bits 5280febc381SYinan Xu } 5290febc381SYinan Xu when (src2Type.valid) { 5300febc381SYinan Xu cs.srcType(1) := src2Type.bits 5310febc381SYinan Xu } 532fe528fd6Ssinsanction when (selImm.valid) { 533fe528fd6Ssinsanction cs.selImm := selImm.bits 534fe528fd6Ssinsanction } 5350febc381SYinan Xu } 5360febc381SYinan Xu} 5370febc381SYinan Xu 53888825c5cSYinan Xuclass FusionDecoder(implicit p: Parameters) extends XSModule { 53988825c5cSYinan Xu val io = IO(new Bundle { 540*bbb50258STang Haojin val disableFusion = Input(Bool()) 5410febc381SYinan Xu // T0: detect instruction fusions in these instructions 54288825c5cSYinan Xu val in = Vec(DecodeWidth, Flipped(ValidIO(UInt(32.W)))) 5430febc381SYinan Xu val inReady = Vec(DecodeWidth - 1, Input(Bool())) // dropRight(1) 5440febc381SYinan Xu // T1: decode result 5453b739f49SXuan Hu val dec = Vec(DecodeWidth - 1, Input(new DecodedInst)) // dropRight(1) 5460febc381SYinan Xu // T1: whether an instruction fusion is found 5470febc381SYinan Xu val out = Vec(DecodeWidth - 1, ValidIO(new FusionDecodeReplace)) // dropRight(1) 5480febc381SYinan Xu val info = Vec(DecodeWidth - 1, new FusionDecodeInfo) // dropRight(1) 5490febc381SYinan Xu // T1: fused instruction needs to be cleared 55088825c5cSYinan Xu val clear = Vec(DecodeWidth, Output(Bool())) 55188825c5cSYinan Xu }) 55288825c5cSYinan Xu 55388825c5cSYinan Xu io.clear.head := false.B 55488825c5cSYinan Xu 55588825c5cSYinan Xu val instrPairs = io.in.dropRight(1).zip(io.in.drop(1)).map(x => Seq(x._1, x._2)) 5560febc381SYinan Xu instrPairs.zip(io.dec).zip(io.out).zipWithIndex.foreach{ case (((pair, dec), out), i) => 55788825c5cSYinan Xu val fusionList = Seq( 55888825c5cSYinan Xu new FusedAdduw(pair), 55988825c5cSYinan Xu new FusedZexth(pair), 56088825c5cSYinan Xu new FusedZexth1(pair), 56188825c5cSYinan Xu new FusedSexth(pair), 56288825c5cSYinan Xu new FusedSh1add(pair), 56388825c5cSYinan Xu new FusedSh2add(pair), 56488825c5cSYinan Xu new FusedSh3add(pair), 56588825c5cSYinan Xu new FusedSzewl1(pair), 56688825c5cSYinan Xu new FusedSzewl2(pair), 567a792bcf1SYinan Xu new FusedSzewl3(pair), 56888825c5cSYinan Xu new FusedByte2(pair), 56988825c5cSYinan Xu new FusedSh4add(pair), 570a792bcf1SYinan Xu new FusedSr29add(pair), 57188825c5cSYinan Xu new FusedSr30add(pair), 57288825c5cSYinan Xu new FusedSr31add(pair), 57388825c5cSYinan Xu new FusedSr32add(pair), 57488825c5cSYinan Xu new FusedOddadd(pair), 57588825c5cSYinan Xu new FusedOddaddw(pair), 5766535afbbSYinan Xu new FusedOrh48(pair), 5776535afbbSYinan Xu new FusedMulw7(pair), 578a0db5a4bSYinan Xu new FusedAddwbyte(pair), 579a0db5a4bSYinan Xu new FusedAddwbit(pair), 580a0db5a4bSYinan Xu new FusedAddwzexth(pair), 581a0db5a4bSYinan Xu new FusedAddwsexth(pair), 582a0db5a4bSYinan Xu new FusedLogiclsb(pair), 583fe528fd6Ssinsanction new FusedLogicZexth(pair), 58454711376Ssinsanction new FusedLui32(pair), 58554711376Ssinsanction new FusedLui32w(pair) 58688825c5cSYinan Xu ) 5870febc381SYinan Xu val fire = io.in(i).valid && io.inReady(i) 5885827388eSYinan Xu val instrPairValid = RegEnable(VecInit(pair.map(_.valid)).asUInt.andR, false.B, io.inReady(i)) 5890febc381SYinan Xu val fusionVec = RegEnable(VecInit(fusionList.map(_.isValid)), fire) 5907d62bb17STang Haojin // HINT instructions are not considered for fusion. 5917d62bb17STang Haojin // NOTE: The RD of some FENCE instructions are not 0, but they are also HINT instructions. 5927d62bb17STang Haojin // However, as FENCE instructions can never be fused, we do not need to consider them. 5937d62bb17STang Haojin val notHint = RegEnable(VecInit(pair.map(_.bits(11, 7) =/= 0.U)).asUInt.andR, fire) 594*bbb50258STang Haojin val enabled = RegEnable(!io.disableFusion, fire) 59588825c5cSYinan Xu val thisCleared = io.clear(i) 596*bbb50258STang Haojin out.valid := instrPairValid && !thisCleared && fusionVec.asUInt.orR && notHint && enabled 5970febc381SYinan Xu XSError(instrPairValid && PopCount(fusionVec) > 1.U, "more then one fusion matched\n") 5980febc381SYinan Xu def connectByInt(field: FusionDecodeReplace => Valid[UInt], replace: Seq[Option[Int]]): Unit = { 5990febc381SYinan Xu field(out.bits).valid := false.B 6000febc381SYinan Xu field(out.bits).bits := DontCare 601a0db5a4bSYinan Xu val replaceVec = fusionVec.zip(replace).filter(_._2.isDefined) 602a0db5a4bSYinan Xu if (replaceVec.nonEmpty) { 603a0db5a4bSYinan Xu // constant values are grouped together for better timing. 6040febc381SYinan Xu val replEnable = VecInit(replaceVec.map(_._1)).asUInt.orR 605a0db5a4bSYinan Xu val replTypes = replaceVec.map(_._2.get).distinct 6060febc381SYinan Xu val replSel = replTypes.map(t => VecInit(replaceVec.filter(_._2.get == t).map(_._1)).asUInt.orR) 6070febc381SYinan Xu field(out.bits).valid := replEnable 6080febc381SYinan Xu field(out.bits).bits := Mux1H(replSel, replTypes.map(_.U)) 609a0db5a4bSYinan Xu } 610a0db5a4bSYinan Xu } 611fe528fd6Ssinsanction def connectByUInt(field: FusionDecodeReplace => Valid[UInt], replace: Seq[Option[UInt]], needReg: Boolean): Unit = { 612fe528fd6Ssinsanction field(out.bits).valid := false.B 613fe528fd6Ssinsanction field(out.bits).bits := DontCare 614fe528fd6Ssinsanction val replaceVec = if (needReg) fusionVec.zip(replace).filter(_._2.isDefined).map(x => (x._1, RegEnable(x._2.get, fire))) else fusionVec.zip(replace).filter(_._2.isDefined).map(x => (x._1, x._2.get)) 615fe528fd6Ssinsanction if (replaceVec.nonEmpty) { 616fe528fd6Ssinsanction val replEnable = VecInit(replaceVec.map(_._1)).asUInt.orR 617fe528fd6Ssinsanction val replTypes = replaceVec.map(_._2).distinct 618fe528fd6Ssinsanction val replSel = replTypes.map(t => VecInit(replaceVec.filter(_._2 == t).map(_._1)).asUInt.orR) 619fe528fd6Ssinsanction field(out.bits).valid := replEnable 620fe528fd6Ssinsanction field(out.bits).bits := Mux1H(replSel, replTypes) 621fe528fd6Ssinsanction } 622fe528fd6Ssinsanction } 6230febc381SYinan Xu def connectByUIntFunc( 6240febc381SYinan Xu field: FusionDecodeReplace => Valid[UInt], 6253b739f49SXuan Hu csField: DecodedInst => UInt, 6260febc381SYinan Xu replace: Seq[Option[UInt => UInt]] 6270febc381SYinan Xu ): Unit = { 6280febc381SYinan Xu field(out.bits).valid := false.B 6290febc381SYinan Xu field(out.bits).bits := DontCare 6300febc381SYinan Xu val replaceVec = fusionVec.zip(replace).filter(_._2.isDefined).map(x => (x._1, x._2.get(csField(dec)))) 631a0db5a4bSYinan Xu if (replaceVec.nonEmpty) { 6320febc381SYinan Xu val replEnable = VecInit(replaceVec.map(_._1)).asUInt.orR 633a0db5a4bSYinan Xu // constant values are grouped together for better timing. 634a0db5a4bSYinan Xu val constReplVec = replaceVec.filter(_._2.isLit).map(x => (x._1, x._2.litValue)) 635a0db5a4bSYinan Xu val constReplTypes = constReplVec.map(_._2).distinct 636a0db5a4bSYinan Xu val constReplEnable = constReplTypes.map(t => VecInit(constReplVec.filter(_._2 == t).map(_._1)).asUInt.orR) 637a0db5a4bSYinan Xu val constReplResult = Mux1H(constReplEnable, constReplTypes.map(_.U)) 638a0db5a4bSYinan Xu // non-constant values have to be processed naively. 639a0db5a4bSYinan Xu val noLitRepl = replaceVec.filterNot(_._2.isLit) 6400febc381SYinan Xu field(out.bits).valid := replEnable 6410febc381SYinan Xu field(out.bits).bits := Mux(VecInit(noLitRepl.map(_._1)).asUInt.orR, Mux1H(noLitRepl), constReplResult) 642a0db5a4bSYinan Xu } 643a0db5a4bSYinan Xu } 6440febc381SYinan Xu connectByInt((x: FusionDecodeReplace) => x.fuType, fusionList.map(_.fuType)) 6453b739f49SXuan Hu connectByUIntFunc((x: FusionDecodeReplace) => x.fuOpType, (x: DecodedInst) => x.fuOpType, fusionList.map(_.fuOpType)) 6460febc381SYinan Xu connectByInt((x: FusionDecodeReplace) => x.src2Type, fusionList.map(_.src2Type)) 647fe528fd6Ssinsanction connectByUInt((x: FusionDecodeReplace) => x.selImm, fusionList.map(_.selImm), false) 648765e58c6Ssinsanction 649a0db5a4bSYinan Xu val src2WithZero = VecInit(fusionVec.zip(fusionList.map(_.lsrc2NeedZero)).filter(_._2).map(_._1)).asUInt.orR 650a0db5a4bSYinan Xu val src2WithMux = VecInit(fusionVec.zip(fusionList.map(_.lsrc2NeedMux)).filter(_._2).map(_._1)).asUInt.orR 651*bbb50258STang Haojin io.info(i).rs2FromZero := enabled && src2WithZero 652*bbb50258STang Haojin io.info(i).rs2FromRs1 := enabled && src2WithMux && !RegEnable(fusionList.head.destToRs1, fire) 653*bbb50258STang Haojin io.info(i).rs2FromRs2 := enabled && src2WithMux && RegEnable(fusionList.head.destToRs1, fire) 654*bbb50258STang Haojin out.bits.lsrc2.valid := enabled && (src2WithMux || src2WithZero) 655a0db5a4bSYinan Xu when (src2WithMux) { 6560febc381SYinan Xu out.bits.lsrc2.bits := RegEnable(fusionList.head.lsrc2MuxResult, fire) 6570febc381SYinan Xu }.otherwise {//elsewhen (src2WithZero) { 6580febc381SYinan Xu out.bits.lsrc2.bits := 0.U 659a0db5a4bSYinan Xu } 66088825c5cSYinan Xu // TODO: assume every instruction fusion clears the second instruction now 66188825c5cSYinan Xu io.clear(i + 1) := out.valid 6620febc381SYinan Xu val lastFire = RegNext(fire) 66388825c5cSYinan Xu fusionList.zip(fusionVec).foreach { case (f, v) => 6640febc381SYinan Xu XSPerfAccumulate(s"case_${f.fusionName}_$i", instrPairValid && !thisCleared && v && lastFire) 66588825c5cSYinan Xu } 6660febc381SYinan Xu XSPerfAccumulate(s"conflict_fusion_$i", instrPairValid && thisCleared && fusionVec.asUInt.orR && lastFire) 66788825c5cSYinan Xu } 66888825c5cSYinan Xu 669765e58c6Ssinsanction XSPerfAccumulate("fused_instr", PopCount(io.out.zipWithIndex.map{ case (x, i) => x.valid && RegNext(io.in(i).valid && io.inReady(i)) })) 67088825c5cSYinan Xu} 671