Example #1
0
class CPURegisters(Elaboratable):
    def __init__(self):
        self.rs1_addr = Signal(unsigned(5))
        self.rs1_read_data = Signal(unsigned(32))

        self.rs2_addr = Signal(unsigned(5))
        self.rs2_read_data = Signal(unsigned(32))

        self.rd_addr = Signal(unsigned(5))
        self.rd_write_enable = Signal()
        self.rd_write_data = Signal(unsigned(32))

        self.regs = [Signal(unsigned(32), name=f"x{i}") for i in range(32)]

    def elaborate(self, platform):
        m = Module()
        with m.Switch(self.rs1_addr):
            for i in range(32):
                with m.Case(i):
                    m.d.comb += self.rs1_read_data.eq(self.regs[i])

        with m.Switch(self.rs2_addr):
            for i in range(32):
                with m.Case(i):
                    m.d.comb += self.rs2_read_data.eq(self.regs[i])

        with m.Switch(self.rd_addr):
            for i in range(32):
                with m.Case(i):
                    if i != 0:
                        with m.If(self.rd_write_enable):
                            m.d.sync += self.regs[i].eq(self.rd_write_data)

        return m
Example #2
0
    def __init__(self):
        self.rs1_addr = Signal(unsigned(5))
        self.rs1_read_data = Signal(unsigned(32))

        self.rs2_addr = Signal(unsigned(5))
        self.rs2_read_data = Signal(unsigned(32))

        self.rd_addr = Signal(unsigned(5))
        self.rd_write_enable = Signal()
        self.rd_write_data = Signal(unsigned(32))

        self.regs = [Signal(unsigned(32), name=f"x{i}") for i in range(32)]
Example #3
0
class CPUMemory(Elaboratable):
    def __init__(self, initial_words: List[int]):
        # data port
        self.address = Signal(unsigned(32))
        self.read_data = Signal(unsigned(32))
        self.write_data = Signal(unsigned(32))
        self.write_byte_enables = Signal(unsigned(4))

        # instruction port
        self.instruction_address = Signal(unsigned(32))
        self.instruction_read_data = Signal(unsigned(32))

        self._memory = Memory(width=32,
                              depth=len(initial_words),
                              init=initial_words)

        self.output_port_data = Signal(unsigned(8))
        self.output_port_valid = Signal()

    def elaborate(self, platform):
        m = Module()

        # data read port
        read_port = self._memory.read_port(domain="comb")
        m.submodules += read_port
        m.d.comb += read_port.addr.eq((self.address -
                                       MEMORY_START_ADDRESS) >> 2)
        m.d.comb += self.read_data.eq(read_port.data)

        # data write port
        write_port = self._memory.write_port(granularity=8)
        m.submodules += write_port
        m.d.comb += write_port.addr.eq((self.address -
                                        MEMORY_START_ADDRESS) >> 2)
        m.d.comb += write_port.data.eq(self.write_data)
        with m.If((self.address >= MEMORY_START_ADDRESS)
                  & (self.address < MEMORY_END_ADDRESS)):
            m.d.comb += write_port.en.eq(self.write_byte_enables)
        with m.If(self.address == OUTPUT_PORT_ADDRESS):
            m.d.comb += self.output_port_data.eq(self.write_data[0:8])
            m.d.comb += self.output_port_valid.eq(self.write_byte_enables[0])

        # instruction read port
        instruction_read_port = self._memory.read_port(domain="comb")
        m.submodules += instruction_read_port
        m.d.comb += instruction_read_port.addr.eq((self.instruction_address -
                                                   MEMORY_START_ADDRESS) >> 2)
        m.d.comb += self.instruction_read_data.eq(instruction_read_port.data)
        return m
Example #4
0
 def __init__(self, initial_words):
     self.memory = CPUMemory(initial_words=initial_words)
     self.decoder = CPUDecoder()
     self.registers = CPURegisters()
     self.pc = Signal(unsigned(32), reset=RESET_ADDRESS)
     self.next_pc = Signal(unsigned(32))
     self.next_pc_fallthrough = Signal(unsigned(32))
     self.load_data = Signal(unsigned(32))
     self.load_data_byte = Signal(unsigned(8))
     self.load_data_half = Signal(unsigned(16))
     self.load_store_address = Signal(unsigned(32))
     self.store_byte_enables = Signal(unsigned(4))
     self.store_half_enables = Signal(unsigned(2))
     self.rs1_read_data_signed = Signal(signed(32))
     self.rs2_read_data_signed = Signal(signed(32))
     self.immediate_signed = Signal(signed(32))
     self.output_port_data = Signal(unsigned(8))
     self.output_port_valid = Signal()
Example #5
0
class CPU(Elaboratable):
    def __init__(self, initial_words):
        self.memory = CPUMemory(initial_words=initial_words)
        self.decoder = CPUDecoder()
        self.registers = CPURegisters()
        self.pc = Signal(unsigned(32), reset=RESET_ADDRESS)
        self.next_pc = Signal(unsigned(32))
        self.next_pc_fallthrough = Signal(unsigned(32))
        self.load_data = Signal(unsigned(32))
        self.load_data_byte = Signal(unsigned(8))
        self.load_data_half = Signal(unsigned(16))
        self.load_store_address = Signal(unsigned(32))
        self.store_byte_enables = Signal(unsigned(4))
        self.store_half_enables = Signal(unsigned(2))
        self.rs1_read_data_signed = Signal(signed(32))
        self.rs2_read_data_signed = Signal(signed(32))
        self.immediate_signed = Signal(signed(32))
        self.output_port_data = Signal(unsigned(8))
        self.output_port_valid = Signal()

    def elaborate(self, platform):
        m = Module()
        m.submodules.memory = self.memory
        m.submodules.decoder = self.decoder
        m.submodules.registers = self.registers

        m.d.comb += self.output_port_data.eq(self.memory.output_port_data)
        m.d.comb += self.output_port_valid.eq(self.memory.output_port_valid)

        m.d.comb += self.memory.instruction_address.eq(self.pc)
        m.d.comb += self.decoder.instruction_in.eq(
            self.memory.instruction_read_data)
        m.d.comb += self.immediate_signed.eq(self.decoder.immediate)
        m.d.comb += self.registers.rd_addr.eq(self.decoder.rd)
        m.d.comb += self.registers.rs1_addr.eq(self.decoder.rs1)
        m.d.comb += self.rs1_read_data_signed.eq(self.registers.rs1_read_data)
        m.d.comb += self.registers.rs2_addr.eq(self.decoder.rs2)
        m.d.comb += self.rs2_read_data_signed.eq(self.registers.rs2_read_data)
        m.d.comb += self.registers.rd_write_enable.eq(0)
        m.d.comb += self.load_store_address.eq(self.registers.rs1_read_data +
                                               self.decoder.immediate)
        m.d.comb += self.memory.address.eq(self.load_store_address & ~0x3)

        with m.Switch(self.decoder.load_store_size):
            with m.Case(LoadStoreSize.Byte):
                byte_index = self.load_store_address[0:2]
                m.d.comb += self.store_byte_enables.eq(1 << byte_index)
                m.d.comb += self.load_data_byte.eq(
                    self.memory.read_data.word_select(byte_index, 8))
                m.d.comb += self.memory.write_data.eq(
                    Repl(self.registers.rs2_read_data[0:8], 4))
                m.d.comb += self.load_data.eq(
                    Cat(
                        self.load_data_byte,
                        Repl(self.decoder.load_signed & self.load_data_byte[7],
                             24)))
            with m.Case(LoadStoreSize.Half):
                half_index = self.load_store_address[1]
                m.d.comb += self.store_half_enables.eq(1 << half_index)
                m.d.comb += self.store_byte_enables.eq(
                    Cat(
                        self.store_half_enables[0],
                        self.store_half_enables[0],
                        self.store_half_enables[1],
                        self.store_half_enables[1],
                    ))
                m.d.comb += self.load_data_half.eq(
                    self.memory.read_data.word_select(half_index, 16))
                m.d.comb += self.memory.write_data.eq(
                    Repl(self.registers.rs2_read_data[0:16], 2))
                m.d.comb += self.load_data.eq(
                    Cat(
                        self.load_data_half,
                        Repl(
                            self.decoder.load_signed & self.load_data_half[15],
                            16)))
            with m.Case(LoadStoreSize.Word):
                m.d.comb += self.store_byte_enables.eq(0xF)
                m.d.comb += self.memory.write_data.eq(
                    self.registers.rs2_read_data)
                m.d.comb += self.load_data.eq(self.memory.read_data)

        m.d.comb += self.next_pc_fallthrough.eq(self.pc + 4)
        m.d.comb += self.next_pc.eq(self.next_pc_fallthrough)
        m.d.sync += self.pc.eq(self.next_pc)

        with m.Switch(self.decoder.op):
            with m.Case(Op.Invalid):
                m.d.comb += self.next_pc.eq(self.pc)
            with m.Case(Op.LoadUpperImm):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.decoder.immediate)
            with m.Case(Op.AddUpperImmPC):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.decoder.immediate + self.pc)
            with m.Case(Op.JumpAndLink):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.next_pc_fallthrough)
                m.d.comb += self.next_pc.eq(self.pc + self.decoder.immediate)
            with m.Case(Op.JumpAndLinkReg):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.next_pc_fallthrough)
                m.d.comb += self.next_pc.eq((self.registers.rs1_read_data +
                                             self.decoder.immediate) & ~0x1)
            with m.Case(Op.BranchEQ):
                with m.If(self.registers.rs1_read_data ==
                          self.registers.rs2_read_data):
                    m.d.comb += self.next_pc.eq(self.pc +
                                                self.decoder.immediate)
            with m.Case(Op.BranchNE):
                with m.If(self.registers.rs1_read_data !=
                          self.registers.rs2_read_data):
                    m.d.comb += self.next_pc.eq(self.pc +
                                                self.decoder.immediate)
            with m.Case(Op.BranchLT):
                with m.If(
                        self.rs1_read_data_signed < self.rs2_read_data_signed):
                    m.d.comb += self.next_pc.eq(self.pc +
                                                self.decoder.immediate)
            with m.Case(Op.BranchGE):
                with m.If(
                        self.rs1_read_data_signed >= self.rs2_read_data_signed
                ):
                    m.d.comb += self.next_pc.eq(self.pc +
                                                self.decoder.immediate)
            with m.Case(Op.BranchLTUnsigned):
                with m.If(self.registers.rs1_read_data <
                          self.registers.rs2_read_data):
                    m.d.comb += self.next_pc.eq(self.pc +
                                                self.decoder.immediate)
            with m.Case(Op.BranchGEUnsigned):
                with m.If(self.registers.rs1_read_data >=
                          self.registers.rs2_read_data):
                    m.d.comb += self.next_pc.eq(self.pc +
                                                self.decoder.immediate)
            with m.Case(Op.LoadByte, Op.LoadHalf, Op.LoadWord,
                        Op.LoadByteUnsigned, Op.LoadHalfUnsigned):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(self.load_data)
            with m.Case(Op.StoreByte, Op.StoreHalf, Op.StoreWord):
                m.d.comb += self.memory.write_byte_enables.eq(
                    self.store_byte_enables)
            with m.Case(Op.AddImm):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.registers.rs1_read_data + self.decoder.immediate)
            with m.Case(Op.SetLTImm):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    Mux(self.rs1_read_data_signed < self.immediate_signed, 1,
                        0))
            with m.Case(Op.SetLTImmUnsigned):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    Mux(self.registers.rs1_read_data < self.decoder.immediate,
                        1, 0))
            with m.Case(Op.XorImm):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.registers.rs1_read_data ^ self.decoder.immediate)
            with m.Case(Op.OrImm):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.registers.rs1_read_data | self.decoder.immediate)
            with m.Case(Op.AndImm):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.registers.rs1_read_data & self.decoder.immediate)
            with m.Case(Op.ShiftLeftImm):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.registers.rs1_read_data << self.decoder.immediate[0:5]
                )
            with m.Case(Op.ShiftRightImm):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                with m.If(self.decoder.variant == OpVariant.Sub_ShiftSigned):
                    m.d.comb += self.registers.rd_write_data.eq(
                        self.rs1_read_data_signed >>
                        self.decoder.immediate[0:5])
                with m.Else():
                    m.d.comb += self.registers.rd_write_data.eq(
                        self.registers.rs1_read_data >>
                        self.decoder.immediate[0:5])
            with m.Case(Op.AddOrSub):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                with m.If(self.decoder.variant == OpVariant.Sub_ShiftSigned):
                    m.d.comb += self.registers.rd_write_data.eq(
                        self.registers.rs1_read_data -
                        self.registers.rs2_read_data)
                with m.Else():
                    m.d.comb += self.registers.rd_write_data.eq(
                        self.registers.rs1_read_data +
                        self.registers.rs2_read_data)
            with m.Case(Op.SetLT):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    Mux(self.rs1_read_data_signed < self.rs2_read_data_signed,
                        1, 0))
            with m.Case(Op.SetLTUnsigned):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    Mux(
                        self.registers.rs1_read_data <
                        self.registers.rs2_read_data, 1, 0))
            with m.Case(Op.Xor):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.registers.rs1_read_data
                    ^ self.registers.rs2_read_data)
            with m.Case(Op.Or):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.registers.rs1_read_data
                    | self.registers.rs2_read_data)
            with m.Case(Op.And):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.registers.rs1_read_data
                    & self.registers.rs2_read_data)
            with m.Case(Op.ShiftLeft):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                m.d.comb += self.registers.rd_write_data.eq(
                    self.registers.rs1_read_data <<
                    self.registers.rs2_read_data[0:5])
            with m.Case(Op.ShiftRight):
                m.d.comb += self.registers.rd_write_enable.eq(True)
                with m.If(self.decoder.variant == OpVariant.Sub_ShiftSigned):
                    m.d.comb += self.registers.rd_write_data.eq(
                        self.rs1_read_data_signed >>
                        self.registers.rs2_read_data[0:5])
                with m.Else():
                    m.d.comb += self.registers.rd_write_data.eq(
                        self.registers.rs1_read_data >>
                        self.registers.rs2_read_data[0:5])
        return m
Example #6
0
    def __init__(self, initial_words: List[int]):
        # data port
        self.address = Signal(unsigned(32))
        self.read_data = Signal(unsigned(32))
        self.write_data = Signal(unsigned(32))
        self.write_byte_enables = Signal(unsigned(4))

        # instruction port
        self.instruction_address = Signal(unsigned(32))
        self.instruction_read_data = Signal(unsigned(32))

        self._memory = Memory(width=32,
                              depth=len(initial_words),
                              init=initial_words)

        self.output_port_data = Signal(unsigned(8))
        self.output_port_valid = Signal()
Example #7
0
 def __init__(self):
     self.instruction_in = Signal(unsigned(32))
     self.op = Signal(Op)
     self.immediate = Signal(unsigned(32))
     self.i_type_immediate = Signal(unsigned(32))
     self.s_type_immediate = Signal(unsigned(32))
     self.b_type_immediate = Signal(unsigned(32))
     self.u_type_immediate = Signal(unsigned(32))
     self.j_type_immediate = Signal(unsigned(32))
     self.rd = Signal(unsigned(5))
     self.rs1 = Signal(unsigned(5))
     self.rs2 = Signal(unsigned(5))
     self.variant = Signal(OpVariant)
     self.load_store_size = Signal(LoadStoreSize)
     self.load_signed = Signal()
Example #8
0
class CPUDecoder(Elaboratable):
    def __init__(self):
        self.instruction_in = Signal(unsigned(32))
        self.op = Signal(Op)
        self.immediate = Signal(unsigned(32))
        self.i_type_immediate = Signal(unsigned(32))
        self.s_type_immediate = Signal(unsigned(32))
        self.b_type_immediate = Signal(unsigned(32))
        self.u_type_immediate = Signal(unsigned(32))
        self.j_type_immediate = Signal(unsigned(32))
        self.rd = Signal(unsigned(5))
        self.rs1 = Signal(unsigned(5))
        self.rs2 = Signal(unsigned(5))
        self.variant = Signal(OpVariant)
        self.load_store_size = Signal(LoadStoreSize)
        self.load_signed = Signal()

    def elaborate(self, platform):
        m = Module()

        m.d.comb += self.rd.eq(self.instruction_in[7:12])
        m.d.comb += self.rs1.eq(self.instruction_in[15:20])
        m.d.comb += self.rs2.eq(self.instruction_in[20:25])

        m.d.comb += self.i_type_immediate.eq(
            Cat(self.instruction_in[20:32], Repl(self.instruction_in[31], 20)))

        m.d.comb += self.s_type_immediate.eq(
            Cat(self.instruction_in[7:12], self.instruction_in[25:32],
                Repl(self.instruction_in[31], 20)))

        m.d.comb += self.b_type_immediate.eq(
            Cat(Const(0, shape=unsigned(1)), self.instruction_in[8:12],
                self.instruction_in[25:31], self.instruction_in[7],
                Repl(self.instruction_in[31], 20)))

        m.d.comb += self.u_type_immediate.eq(
            Cat(Const(0, shape=unsigned(12)), self.instruction_in[12:32]))

        m.d.comb += self.j_type_immediate.eq(
            Cat(Const(0, shape=unsigned(1)), self.instruction_in[21:31],
                self.instruction_in[20], self.instruction_in[12:20],
                Repl(self.instruction_in[31], 12)))

        with m.Switch(self.instruction_in):
            with m.Case('------- ----- ----- --- ----- 0110111'):
                m.d.comb += self.op.eq(Op.LoadUpperImm)
                m.d.comb += self.immediate.eq(self.u_type_immediate)
            with m.Case('------- ----- ----- --- ----- 0010111'):
                m.d.comb += self.op.eq(Op.AddUpperImmPC)
                m.d.comb += self.immediate.eq(self.u_type_immediate)

            with m.Case('------- ----- ----- --- ----- 1101111'):
                m.d.comb += self.op.eq(Op.JumpAndLink)
                m.d.comb += self.immediate.eq(self.j_type_immediate)

            with m.Case('------- ----- ----- 000 ----- 1100111'):
                m.d.comb += self.op.eq(Op.JumpAndLinkReg)
                m.d.comb += self.immediate.eq(self.i_type_immediate)

            with m.Case('------- ----- ----- 000 ----- 1100011'):
                m.d.comb += self.op.eq(Op.BranchEQ)
                m.d.comb += self.immediate.eq(self.b_type_immediate)
            with m.Case('------- ----- ----- 001 ----- 1100011'):
                m.d.comb += self.op.eq(Op.BranchNE)
                m.d.comb += self.immediate.eq(self.b_type_immediate)
            with m.Case('------- ----- ----- 100 ----- 1100011'):
                m.d.comb += self.op.eq(Op.BranchLT)
                m.d.comb += self.immediate.eq(self.b_type_immediate)
            with m.Case('------- ----- ----- 101 ----- 1100011'):
                m.d.comb += self.op.eq(Op.BranchGE)
                m.d.comb += self.immediate.eq(self.b_type_immediate)
            with m.Case('------- ----- ----- 110 ----- 1100011'):
                m.d.comb += self.op.eq(Op.BranchLTUnsigned)
                m.d.comb += self.immediate.eq(self.b_type_immediate)
            with m.Case('------- ----- ----- 111 ----- 1100011'):
                m.d.comb += self.op.eq(Op.BranchGEUnsigned)
                m.d.comb += self.immediate.eq(self.b_type_immediate)

            with m.Case('------- ----- ----- 000 ----- 0000011'):
                m.d.comb += self.op.eq(Op.LoadByte)
                m.d.comb += self.immediate.eq(self.i_type_immediate)
                m.d.comb += self.load_store_size.eq(LoadStoreSize.Byte)
                m.d.comb += self.load_signed.eq(True)
            with m.Case('------- ----- ----- 001 ----- 0000011'):
                m.d.comb += self.op.eq(Op.LoadHalf)
                m.d.comb += self.immediate.eq(self.i_type_immediate)
                m.d.comb += self.load_store_size.eq(LoadStoreSize.Half)
                m.d.comb += self.load_signed.eq(True)
            with m.Case('------- ----- ----- 010 ----- 0000011'):
                m.d.comb += self.op.eq(Op.LoadWord)
                m.d.comb += self.immediate.eq(self.i_type_immediate)
                m.d.comb += self.load_store_size.eq(LoadStoreSize.Word)
                m.d.comb += self.load_signed.eq(True)
            with m.Case('------- ----- ----- 100 ----- 0000011'):
                m.d.comb += self.op.eq(Op.LoadByteUnsigned)
                m.d.comb += self.immediate.eq(self.i_type_immediate)
                m.d.comb += self.load_store_size.eq(LoadStoreSize.Byte)
                m.d.comb += self.load_signed.eq(False)
            with m.Case('------- ----- ----- 101 ----- 0000011'):
                m.d.comb += self.op.eq(Op.LoadHalfUnsigned)
                m.d.comb += self.immediate.eq(self.i_type_immediate)
                m.d.comb += self.load_store_size.eq(LoadStoreSize.Half)
                m.d.comb += self.load_signed.eq(False)

            with m.Case('------- ----- ----- 000 ----- 0100011'):
                m.d.comb += self.op.eq(Op.StoreByte)
                m.d.comb += self.immediate.eq(self.s_type_immediate)
                m.d.comb += self.load_store_size.eq(LoadStoreSize.Byte)
            with m.Case('------- ----- ----- 001 ----- 0100011'):
                m.d.comb += self.op.eq(Op.StoreHalf)
                m.d.comb += self.immediate.eq(self.s_type_immediate)
                m.d.comb += self.load_store_size.eq(LoadStoreSize.Half)
            with m.Case('------- ----- ----- 010 ----- 0100011'):
                m.d.comb += self.op.eq(Op.StoreWord)
                m.d.comb += self.immediate.eq(self.s_type_immediate)
                m.d.comb += self.load_store_size.eq(LoadStoreSize.Word)

            with m.Case('------- ----- ----- 000 ----- 0010011'):
                m.d.comb += self.op.eq(Op.AddImm)
                m.d.comb += self.immediate.eq(self.i_type_immediate)
            with m.Case('0000000 ----- ----- 001 ----- 0010011'):
                m.d.comb += self.op.eq(Op.ShiftLeftImm)
                m.d.comb += self.immediate.eq(self.i_type_immediate)
            with m.Case('------- ----- ----- 010 ----- 0010011'):
                m.d.comb += self.op.eq(Op.SetLTImm)
                m.d.comb += self.immediate.eq(self.i_type_immediate)
            with m.Case('------- ----- ----- 011 ----- 0010011'):
                m.d.comb += self.op.eq(Op.SetLTImmUnsigned)
                m.d.comb += self.immediate.eq(self.i_type_immediate)
            with m.Case('------- ----- ----- 100 ----- 0010011'):
                m.d.comb += self.op.eq(Op.XorImm)
                m.d.comb += self.immediate.eq(self.i_type_immediate)
            with m.Case('0-00000 ----- ----- 101 ----- 0010011'):
                m.d.comb += self.op.eq(Op.ShiftRightImm)
                m.d.comb += self.immediate.eq(self.i_type_immediate)
                m.d.comb += self.variant.eq(
                    Mux(self.instruction_in[30], OpVariant.Sub_ShiftSigned,
                        OpVariant.Add_ShiftUnsigned))
            with m.Case('------- ----- ----- 110 ----- 0010011'):
                m.d.comb += self.op.eq(Op.OrImm)
                m.d.comb += self.immediate.eq(self.i_type_immediate)
            with m.Case('------- ----- ----- 111 ----- 0010011'):
                m.d.comb += self.op.eq(Op.AndImm)
                m.d.comb += self.immediate.eq(self.i_type_immediate)

            with m.Case('0-00000 ----- ----- 000 ----- 0110011'):
                m.d.comb += self.op.eq(Op.AddOrSub)
                m.d.comb += self.variant.eq(
                    Mux(self.instruction_in[30], OpVariant.Sub_ShiftSigned,
                        OpVariant.Add_ShiftUnsigned))
            with m.Case('0000000 ----- ----- 001 ----- 0110011'):
                m.d.comb += self.op.eq(Op.ShiftLeft)
            with m.Case('0000000 ----- ----- 010 ----- 0110011'):
                m.d.comb += self.op.eq(Op.SetLT)
            with m.Case('0000000 ----- ----- 011 ----- 0110011'):
                m.d.comb += self.op.eq(Op.SetLTUnsigned)
            with m.Case('0000000 ----- ----- 100 ----- 0110011'):
                m.d.comb += self.op.eq(Op.Xor)
            with m.Case('0-00000 ----- ----- 101 ----- 0110011'):
                m.d.comb += self.op.eq(Op.ShiftRight)
                m.d.comb += self.variant.eq(
                    Mux(self.instruction_in[30], OpVariant.Sub_ShiftSigned,
                        OpVariant.Add_ShiftUnsigned))
            with m.Case('0000000 ----- ----- 110 ----- 0110011'):
                m.d.comb += self.op.eq(Op.Or)
            with m.Case('0000000 ----- ----- 111 ----- 0110011'):
                m.d.comb += self.op.eq(Op.And)

            with m.Default():
                m.d.comb += self.op.eq(Op.Invalid)
        return m