blob: 2f9cb8996c3eba68f6eeefc313b4fc697d333572 [file] [log] [blame]
package components
import chisel3._
import chisel3.experimental.ChiselEnum
import utils.MathUtils.BinStrToInt
object CCMode extends ChiselEnum {
// ALU = use CC values from ALU
// WB = use ZN from write-back value, C = 0, V = 0
// NONE = don't change CC flags
val ALU, WB, NONE = Value
}
class Instruction extends Bundle {
val rs1 = UInt(3.W)
val rs2 = UInt(3.W)
val rd = UInt(3.W)
val imm = UInt(16.W)
val cc_mode = CCMode()
val alu_op = ALUOp()
val bra_mask = new ZCNV // Which CC bits to branch on
val has_jump = Bool()
val has_stop = Bool()
val has_branch = Bool()
val has_mem = Bool()
val has_wb = Bool()
val has_imm = Bool()
val is_valid = Bool()
}
object OpCode {
val ADD = b"0000 000"
val ADDI = b"0011 000"
val AND = b"1001 000"
val BRA = b"1111 100"
val BRC = b"1010 100"
val BRN = b"1001 100"
val BRNZ = b"1101 100"
val BRV = b"1011 100"
val BRZ = b"1100 100"
// LI = ADDI
val LW = b"0010 100"
val MV = b"0010 000"
val NOT = b"1000 000"
val OR = b"1010 000"
val SLL = b"1100 000"
val SLLI = b"1100 001"
val SLT = b"0101 000"
val SLTI = b"0101 001"
val SRA = b"1111 000"
val SRAI = b"1111 001"
val SRL = b"1110 000"
val SRLI = b"1110 001"
val STOP = b"1111 111"
val SUB = b"0001 000"
val SW = b"0011 100"
val XOR = b"1011 000"
}
class InstrDecoder extends Module {
val io = IO(new Bundle {
val instr = Input(UInt(16.W))
val imm = Input(UInt(16.W))
val decoded = Output(new Instruction)
})
val instructions = Map(
// Opcode ALU op CC mode BRA mask jmp stp bra mem wb imm
OpCode.ADD -> (Some(ALUOp.ADD), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // ADD
OpCode.ADDI -> (Some(ALUOp.ADD), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 1 ), // ADDI
OpCode.AND -> (Some(ALUOp.AND), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // AND
OpCode.BRA -> (None, CCMode.NONE, b"0000", 1, 0, 0, 0, 0, 1 ), // BRA
OpCode.BRC -> (None, CCMode.NONE, b"0100", 0, 0, 1, 0, 0, 1 ), // BRC
OpCode.BRN -> (None, CCMode.NONE, b"0010", 0, 0, 1, 0, 0, 1 ), // BRN
OpCode.BRNZ -> (None, CCMode.NONE, b"1010", 0, 0, 1, 0, 0, 1 ), // BRNZ
OpCode.BRV -> (None, CCMode.NONE, b"0001", 0, 0, 1, 0, 0, 1 ), // BRV
OpCode.BRZ -> (None, CCMode.NONE, b"1000", 0, 0, 1, 0, 0, 1 ), // BRZ
// LI does not have its own encoding, it uses ADDI with rs1 = 0
OpCode.LW -> (Some(ALUOp.ADD), CCMode.WB, b"0000", 0, 0, 0, 1, 1, 1 ), // LW
OpCode.MV -> (Some(ALUOp.ADD), CCMode.NONE, b"0000", 0, 0, 0, 0, 1, 0 ), // MV (ADD, rs2 = 0)
OpCode.NOT -> (Some(ALUOp.NOT), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // NOT
OpCode.OR -> (Some(ALUOp.OR), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // OR
OpCode.SLL -> (Some(ALUOp.SLL), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // SLL
OpCode.SLLI -> (Some(ALUOp.SLL), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 1 ), // SLLI
OpCode.SLT -> (Some(ALUOp.SLT), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // SLT
OpCode.SLTI -> (Some(ALUOp.SLT), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 1 ), // SLTI
OpCode.SRA -> (Some(ALUOp.SRA), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // SRA
OpCode.SRAI -> (Some(ALUOp.SRA), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 1 ), // SRAI
OpCode.SRL -> (Some(ALUOp.SRL), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // SRL
OpCode.SRLI -> (Some(ALUOp.SRL), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 1 ), // SRLI
OpCode.STOP -> (None, CCMode.NONE, b"0000", 0, 1, 0, 0, 0, 0 ), // STOP
OpCode.SUB -> (Some(ALUOp.SUB), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // SUB
OpCode.SW -> (Some(ALUOp.ADD), CCMode.NONE, b"0000", 0, 0, 0, 1, 0, 1 ), // SW
OpCode.XOR -> (Some(ALUOp.XOR), CCMode.ALU, b"0000", 0, 0, 0, 0, 1, 0 ), // XOR
)
val opcode = io.instr(15, 9)
// Operands
io.decoded.imm := io.imm
io.decoded.rd := io.instr(8, 6) // When instruction has no write-back it's always zero - useful feature of the ISA
io.decoded.rs1 := io.instr(5, 3)
io.decoded.rs2 := io.instr(2, 0)
// Default values
io.decoded.cc_mode := CCMode.NONE
io.decoded.alu_op := ALUOp.ADD
io.decoded.bra_mask.z := false.B
io.decoded.bra_mask.c := false.B
io.decoded.bra_mask.n := false.B
io.decoded.bra_mask.v := false.B
io.decoded.has_jump := false.B
io.decoded.has_stop := false.B
io.decoded.has_branch := false.B
io.decoded.has_mem := false.B
io.decoded.has_wb := false.B
io.decoded.has_imm := false.B
io.decoded.is_valid := false.B
for ((inst_opcode, (aluop, ccmode, bramask, jmp, stp, bra, mem, wb, imm)) <- instructions) {
when (inst_opcode.U === opcode) {
io.decoded.cc_mode := ccmode
io.decoded.alu_op := aluop getOrElse ALUOp.ADD
io.decoded.bra_mask.z := ((bramask & b"1000") != 0).B
io.decoded.bra_mask.c := ((bramask & b"0100") != 0).B
io.decoded.bra_mask.n := ((bramask & b"0010") != 0).B
io.decoded.bra_mask.v := ((bramask & b"0001") != 0).B
io.decoded.has_jump := jmp.B
io.decoded.has_stop := stp.B
io.decoded.has_branch := bra.B
io.decoded.has_mem := mem.B
io.decoded.has_wb := wb.B
io.decoded.has_imm := imm.B
io.decoded.is_valid := true.B
}
}
}