import chisel3._ import chisel3.util._ class Decoder(p: CoreParams = CoreParams()) extends Module { val io = IO(new Bundle { val pc = Input(UInt(p.xlen.W)) val inst = Input(UInt(32.W)) val out = Output(new DecodedInst(p)) }) val opcode = io.inst(6, 0) val rd = io.inst(11, 7) val funct3 = io.inst(14, 12) val rs1 = io.inst(19, 15) val rs2 = io.inst(24, 20) val funct7 = io.inst(31, 25) val immI = Consts.signExtend(io.inst(31, 20), 12) val immS = Consts.signExtend(Cat(io.inst(31, 25), io.inst(11, 7)), 12) val immB = Consts.signExtend(Cat(io.inst(31), io.inst(7), io.inst(30, 25), io.inst(11, 8), 0.U(1.W)), 13) val immU = Consts.signExtend(Cat(io.inst(31, 12), 0.U(12.W)), 32) val immJ = Consts.signExtend(Cat(io.inst(31), io.inst(19, 12), io.inst(20), io.inst(30, 21), 0.U(1.W)), 21) val d = WireDefault(0.U.asTypeOf(new DecodedInst(p))) d.valid := true.B d.pc := io.pc d.inst := io.inst d.rs1 := rs1 d.rs2 := rs2 d.rd := rd d.funct3 := funct3 d.funct7 := funct7 d.amoOp := io.inst(31, 27) d.immI := immI d.immS := immS d.immB := immB d.immU := immU d.immJ := immJ d.memWidth := MuxLookup(funct3, 3.U)(Seq( "b000".U -> 0.U, "b001".U -> 1.U, "b010".U -> 2.U, "b011".U -> 3.U, "b100".U -> 0.U, "b101".U -> 1.U, "b110".U -> 2.U )) d.memSigned := !funct3(2) d.illegal := false.B val isSystemOpcode = opcode === "b1110011".U val isFenceOpcode = opcode === "b0001111".U val isEcall = io.inst === "h00000073".U val isEbreak = io.inst === "h00100073".U val isMret = io.inst === "h30200073".U val isSret = io.inst === "h10200073".U val isUret = io.inst === "h00200073".U val isWfi = io.inst === "h10500073".U val isSfenceVma = isSystemOpcode && funct3 === 0.U && funct7 === "b0001001".U val isKnownPrivInst = isEcall || isEbreak || isMret || isSret || isSfenceVma || isWfi d.isEcall := isEcall d.isEbreak := isEbreak d.isMret := isMret d.isSret := isSret d.isUret := isUret d.isSfenceVma := isSfenceVma d.isXret := isMret || isSret d.isWfi := isWfi switch(opcode) { is("b0110111".U) { d.isLui := true.B d.writesRd := rd =/= 0.U d.opClass := Consts.OP_ALU d.aluFn := Consts.ALU_COPY_B } is("b0010111".U) { d.isAuipc := true.B d.writesRd := rd =/= 0.U d.opClass := Consts.OP_ALU d.aluFn := Consts.ALU_ADD } is("b1101111".U) { d.isJal := true.B d.writesRd := rd =/= 0.U d.opClass := Consts.OP_BRANCH } is("b1100111".U) { d.isJalr := true.B d.writesRd := rd =/= 0.U d.opClass := Consts.OP_BRANCH } is("b1100011".U) { d.isBranch := true.B d.opClass := Consts.OP_BRANCH } is("b0000011".U) { d.isLoad := true.B d.writesRd := rd =/= 0.U d.opClass := Consts.OP_LOAD } is("b0100011".U) { d.isStore := true.B d.opClass := Consts.OP_STORE } is("b0010011".U, "b0011011".U) { d.isOpImm := true.B d.isWord := opcode === "b0011011".U d.writesRd := rd =/= 0.U d.opClass := Consts.OP_ALU d.aluFn := MuxLookup(funct3, Consts.ALU_ADD)(Seq( "b000".U -> Consts.ALU_ADD, "b001".U -> Consts.ALU_SLL, "b010".U -> Consts.ALU_SLT, "b011".U -> Consts.ALU_SLTU, "b100".U -> Consts.ALU_XOR, "b101".U -> Mux(funct7(5), Consts.ALU_SRA, Consts.ALU_SRL), "b110".U -> Consts.ALU_OR, "b111".U -> Consts.ALU_AND )) } is("b0110011".U, "b0111011".U) { d.isOp := true.B d.isWord := opcode === "b0111011".U d.writesRd := rd =/= 0.U d.opClass := Consts.OP_ALU d.aluFn := Mux(funct7 === "b0000001".U, MuxLookup(funct3, Consts.ALU_MUL)(Seq( "b000".U -> Consts.ALU_MUL, "b001".U -> Consts.ALU_MULH, "b010".U -> Consts.ALU_MULHSU, "b011".U -> Consts.ALU_MULHU, "b100".U -> Consts.ALU_DIV, "b101".U -> Consts.ALU_DIVU, "b110".U -> Consts.ALU_REM, "b111".U -> Consts.ALU_REMU )), MuxLookup(funct3, Consts.ALU_ADD)(Seq( "b000".U -> Mux(funct7(5), Consts.ALU_SUB, Consts.ALU_ADD), "b001".U -> Consts.ALU_SLL, "b010".U -> Consts.ALU_SLT, "b011".U -> Consts.ALU_SLTU, "b100".U -> Consts.ALU_XOR, "b101".U -> Mux(funct7(5), Consts.ALU_SRA, Consts.ALU_SRL), "b110".U -> Consts.ALU_OR, "b111".U -> Consts.ALU_AND ))) } is("b0001111".U) { d.opClass := Consts.OP_SYSTEM d.isFenceI := funct3 === "b001".U d.illegal := funct3 =/= 0.U && funct3 =/= "b001".U } is("b1110011".U) { d.isSystem := true.B d.writesRd := rd =/= 0.U && funct3 =/= 0.U d.opClass := Consts.OP_SYSTEM when(funct3 === 0.U) { d.illegal := !(isKnownPrivInst && !isUret) } } is("b0101111".U) { d.isLoad := true.B d.isAmo := true.B d.writesRd := rd =/= 0.U d.memWidth := Mux(funct3 === "b010".U, 2.U, 3.U) d.opClass := Consts.OP_LOAD } } when(opcode =/= "b0110111".U && opcode =/= "b0010111".U && opcode =/= "b1101111".U && opcode =/= "b1100111".U && opcode =/= "b1100011".U && opcode =/= "b0000011".U && opcode =/= "b0100011".U && opcode =/= "b0010011".U && opcode =/= "b0011011".U && opcode =/= "b0110011".U && opcode =/= "b0111011".U && opcode =/= "b0001111".U && opcode =/= "b1110011".U && opcode =/= "b0101111".U) { d.illegal := true.B } when(isSystemOpcode && isUret) { d.illegal := true.B } io.out := d }