Exemplo n.º 1
0
    def decode_const(self, m: Module):
        const_sig = Signal(32)

        with m.Switch(self._const):
            with m.Case(ConstSelect.EXC_INSTR_ADDR_MISALIGN):
                m.d.comb += const_sig.eq(
                    TrapCause.EXC_INSTR_ADDR_MISALIGN)
            with m.Case(ConstSelect.EXC_ILLEGAL_INSTR):
                m.d.comb += const_sig.eq(TrapCause.EXC_ILLEGAL_INSTR)
            with m.Case(ConstSelect.EXC_BREAKPOINT):
                m.d.comb += const_sig.eq(TrapCause.EXC_BREAKPOINT)
            with m.Case(ConstSelect.EXC_LOAD_ADDR_MISALIGN):
                m.d.comb += const_sig.eq(
                    TrapCause.EXC_LOAD_ADDR_MISALIGN)
            with m.Case(ConstSelect.EXC_STORE_AMO_ADDR_MISALIGN):
                m.d.comb += const_sig.eq(
                    TrapCause.EXC_STORE_AMO_ADDR_MISALIGN)
            with m.Case(ConstSelect.EXC_ECALL_FROM_MACH_MODE):
                m.d.comb += const_sig.eq(
                    TrapCause.EXC_ECALL_FROM_MACH_MODE)
            with m.Case(ConstSelect.INT_MACH_EXTERNAL):
                m.d.comb += const_sig.eq(TrapCause.INT_MACH_EXTERNAL)
            with m.Case(ConstSelect.INT_MACH_TIMER):
                m.d.comb += const_sig.eq(TrapCause.INT_MACH_TIMER)
            with m.Case(ConstSelect.SHAMT_0):
                m.d.comb += const_sig.eq(0)
            with m.Case(ConstSelect.SHAMT_4):
                m.d.comb += const_sig.eq(4)
            with m.Case(ConstSelect.SHAMT_8):
                m.d.comb += const_sig.eq(8)
            with m.Case(ConstSelect.SHAMT_16):
                m.d.comb += const_sig.eq(16)
            with m.Case(ConstSelect.SHAMT_24):
                m.d.comb += const_sig.eq(24)
            with m.Default():
                m.d.comb += const_sig.eq(0)

        return const_sig
Exemplo n.º 2
0
    def handle_store(self, m: Module):
        """Adds the STORE logic to the given module.

        Note that byte stores are byte-aligned, half-word stores
        are 16-bit aligned, and word stores are 32-bit aligned.
        Attempting to stores unaligned will lead to undefined
        behavior.

        addr <- rs1 + imm
        data <- rs2
        PC <- PC + 4

        rs1     -> X
        imm     -> Y
        ALU ADD -> Z
        Z       -> memaddr
        ---------------------
        rs2     -> X
        shamt   -> Y
        ALU SLL -> Z
        Z       -> wrdata
                -> wrmask
        ---------------------
        PC + 4  -> PC
        PC + 4  -> memaddr
        """
        with m.If(self._instr_phase == 0):
            m.d.comb += [
                self.reg_to_x.eq(1),
                self._x_reg_select.eq(InstrReg.RS1),
                self.y_mux_select.eq(SeqMuxSelect.IMM),
                self.alu_op_to_z.eq(AluOp.ADD),
                self.memaddr_mux_select.eq(SeqMuxSelect.Z),
                self._next_instr_phase.eq(1),
            ]

        with m.Elif(self._instr_phase == 1):
            # Check for exception conditions first
            with m.If((self._funct3 == MemAccessWidth.H)
                      & self.memaddr_2_lsb[0]):
                self.set_exception(m,
                                   ConstSelect.EXC_STORE_AMO_ADDR_MISALIGN,
                                   mtval=SeqMuxSelect.MEMADDR)

            with m.Elif((self._funct3 == MemAccessWidth.W)
                        & (self.memaddr_2_lsb != 0)):
                self.set_exception(m,
                                   ConstSelect.EXC_STORE_AMO_ADDR_MISALIGN,
                                   mtval=SeqMuxSelect.MEMADDR)

            with m.Elif(~self._funct3.matches(
                    MemAccessWidth.B, MemAccessWidth.H, MemAccessWidth.W)):
                self.handle_illegal_instr(m)

            with m.Else():
                m.d.comb += [
                    self.reg_to_x.eq(1),
                    self._x_reg_select.eq(InstrReg.RS2),
                    self.y_mux_select.eq(SeqMuxSelect.CONST),
                    self.alu_op_to_z.eq(AluOp.SLL),
                    self.memdata_wr_mux_select.eq(SeqMuxSelect.Z),
                    self._next_instr_phase.eq(2),
                ]

                with m.Switch(self._funct3):

                    with m.Case(MemAccessWidth.B):
                        with m.Switch(self.memaddr_2_lsb):
                            with m.Case(0):
                                m.d.comb += self._const.eq(ConstSelect.SHAMT_0)
                            with m.Case(1):
                                m.d.comb += self._const.eq(ConstSelect.SHAMT_8)
                            with m.Case(2):
                                m.d.comb += self._const.eq(
                                    ConstSelect.SHAMT_16)
                            with m.Case(3):
                                m.d.comb += self._const.eq(
                                    ConstSelect.SHAMT_24)

                    with m.Case(MemAccessWidth.H):
                        with m.Switch(self.memaddr_2_lsb):
                            with m.Case(0):
                                m.d.comb += self._const.eq(ConstSelect.SHAMT_0)
                            with m.Case(2):
                                m.d.comb += self._const.eq(
                                    ConstSelect.SHAMT_16)

                    with m.Case(MemAccessWidth.W):
                        m.d.comb += self._const.eq(ConstSelect.SHAMT_0)

        with m.Else():
            with m.Switch(self._funct3):

                with m.Case(MemAccessWidth.B):
                    with m.Switch(self.memaddr_2_lsb):
                        with m.Case(0):
                            m.d.comb += self.mem_wr_mask.eq(0b0001)
                        with m.Case(1):
                            m.d.comb += self.mem_wr_mask.eq(0b0010)
                        with m.Case(2):
                            m.d.comb += self.mem_wr_mask.eq(0b0100)
                        with m.Case(3):
                            m.d.comb += self.mem_wr_mask.eq(0b1000)

                with m.Case(MemAccessWidth.H):
                    with m.Switch(self.memaddr_2_lsb):
                        with m.Case(0):
                            m.d.comb += self.mem_wr_mask.eq(0b0011)
                        with m.Case(2):
                            m.d.comb += self.mem_wr_mask.eq(0b1100)

                with m.Case(MemAccessWidth.W):
                    m.d.comb += self.mem_wr_mask.eq(0b1111)

            m.d.comb += self.mem_wr.eq(1)
            self.next_instr(m)
Exemplo n.º 3
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        opcode = Signal(Opcode)
        funct3 = Signal(Funct3)
        funct7 = Signal(Funct7)
        funct12 = Signal(Funct12)
        iimm12 = Signal((12, True))
        simm12 = Signal((12, True))
        bimm12 = Signal((13, True))
        uimm20 = Signal(20)
        jimm20 = Signal((21, True))
        itype = Signal(Type)
        instruction = self.instruction

        with m.Switch(opcode):
            with m.Case(Opcode.LUI):
                m.d.comb += itype.eq(Type.U)
            with m.Case(Opcode.AUIPC):
                m.d.comb += itype.eq(Type.U)
            with m.Case(Opcode.JAL):
                m.d.comb += itype.eq(Type.J)
            with m.Case(Opcode.JALR):
                m.d.comb += itype.eq(Type.I)
            with m.Case(Opcode.BRANCH):
                m.d.comb += itype.eq(Type.B)
            with m.Case(Opcode.LOAD):
                m.d.comb += itype.eq(Type.I)
            with m.Case(Opcode.STORE):
                m.d.comb += itype.eq(Type.S)
            with m.Case(Opcode.OP_IMM):
                m.d.comb += itype.eq(Type.I)
            with m.Case(Opcode.OP):
                m.d.comb += itype.eq(Type.R)
            with m.Case(Opcode.FENCE):
                m.d.comb += itype.eq(Type.I)
            with m.Case(Opcode.SYSTEM):
                m.d.comb += itype.eq(Type.I)

        with m.Switch(itype):
            with m.Case(Type.I):
                m.d.comb += self.immediate.eq(iimm12)
            with m.Case(Type.S):
                m.d.comb += self.immediate.eq(simm12)
            with m.Case(Type.B):
                m.d.comb += self.immediate.eq(bimm12)
            with m.Case(Type.U):
                m.d.comb += self.immediate.eq(uimm20 << 12)
            with m.Case(Type.J):
                m.d.comb += self.immediate.eq(jimm20)

        m.d.comb += [
            opcode.eq(instruction[:7]),
            funct3.eq(instruction[12:15]),
            funct7.eq(instruction[25:32]),
            funct12.eq(instruction[20:32]),
            iimm12.eq(instruction[20:32]),
            simm12.eq(Cat(instruction[7:12], instruction[25:32])),
            bimm12.eq(
                Cat(0, instruction[8:12], instruction[25:31], instruction[7],
                    instruction[31])),
            uimm20.eq(instruction[12:32]),
            jimm20.eq(
                Cat(0, instruction[21:31], instruction[20], instruction[12:20],
                    instruction[31]))
        ]

        m.d.comb += [
            self.gpr_rs1.eq(instruction[15:20]),
            self.gpr_rs1_use.eq(
                reduce(
                    or_,
                    [itype == tmp
                     for tmp in (Type.R, Type.I, Type.S, Type.B)])),
            self.gpr_rs2.eq(instruction[20:25]),
            self.gpr_rs2_use.eq(
                reduce(or_,
                       [itype == tmp for tmp in (Type.R, Type.S, Type.B)])),
            self.gpr_rd.eq(instruction[7:12]),
            self.gpr_we.eq(
                reduce(
                    or_,
                    [itype == tmp
                     for tmp in (Type.R, Type.I, Type.U, Type.J)])),
            self.funct3.eq(funct3)
        ]

        m.d.comb += [
            self.needed_in_x.eq(self.lui | self.aiupc | self.jump
                                | self.aritmetic | self.logic | self.multiply),
            self.needed_in_m.eq(self.compare | self.shift | self.divide),
        ]

        # ----------------------------------------------------------------------
        # define functions to handle the match
        Fields = List[Tuple[int, Optional[int], Optional[int],
                            Optional[int]]]  # Tuple: (Opcode, F3, F7, F12)

        def match(fields: Fields) -> bool:
            def __check(op, f3=None, f7=None, f12=None):
                op_match = opcode == op
                f3_match = funct3 == f3 if f3 is not None else 1
                f7_match = funct7 == f7 if f7 is not None else 1
                f12_match = funct12 == f12 if f12 is not None else 1
                return op_match & f3_match & f7_match & f12_match

            return reduce(or_, [__check(*instr) for instr in fields])

        # ----------------------------------------------------------------------

        m.d.comb += [
            self.lui.eq(opcode == Opcode.LUI),
            self.aiupc.eq(opcode == Opcode.AUIPC),
            self.jump.eq(
                match([(Opcode.JAL, None, None, None),
                       (Opcode.JALR, 0, None, None)])),
            self.branch.eq(
                match([(Opcode.BRANCH, Funct3.BEQ, None, None),
                       (Opcode.BRANCH, Funct3.BNE, None, None),
                       (Opcode.BRANCH, Funct3.BLT, None, None),
                       (Opcode.BRANCH, Funct3.BGE, None, None),
                       (Opcode.BRANCH, Funct3.BLTU, None, None),
                       (Opcode.BRANCH, Funct3.BGEU, None, None)])),
            self.load.eq(
                match([(Opcode.LOAD, Funct3.B, None, None),
                       (Opcode.LOAD, Funct3.H, None, None),
                       (Opcode.LOAD, Funct3.W, None, None),
                       (Opcode.LOAD, Funct3.BU, None, None),
                       (Opcode.LOAD, Funct3.HU, None, None)])),
            self.store.eq(
                match([(Opcode.STORE, Funct3.B, None, None),
                       (Opcode.STORE, Funct3.H, None, None),
                       (Opcode.STORE, Funct3.W, None, None)])),
            self.aritmetic.eq(
                match([(Opcode.OP_IMM, Funct3.ADD, None, None),
                       (Opcode.OP, Funct3.ADD, Funct7.ADD, None),
                       (Opcode.OP, Funct3.ADD, Funct7.SUB, None)])),
            self.logic.eq(
                match([(Opcode.OP_IMM, Funct3.XOR, None, None),
                       (Opcode.OP_IMM, Funct3.OR, None, None),
                       (Opcode.OP_IMM, Funct3.AND, None, None),
                       (Opcode.OP, Funct3.XOR, 0, None),
                       (Opcode.OP, Funct3.OR, 0, None),
                       (Opcode.OP, Funct3.AND, 0, None)])),
            self.compare.eq(
                match([(Opcode.OP_IMM, Funct3.SLT, None, None),
                       (Opcode.OP_IMM, Funct3.SLTU, None, None),
                       (Opcode.OP, Funct3.SLT, 0, None),
                       (Opcode.OP, Funct3.SLTU, 0, None)])),
            self.shift.eq(
                match([(Opcode.OP_IMM, Funct3.SLL, 0, None),
                       (Opcode.OP_IMM, Funct3.SR, Funct7.SRL, None),
                       (Opcode.OP_IMM, Funct3.SR, Funct7.SRA, None),
                       (Opcode.OP, Funct3.SLL, 0, None),
                       (Opcode.OP, Funct3.SR, Funct7.SRL, None),
                       (Opcode.OP, Funct3.SR, Funct7.SRA, None)])),
            self.csr.eq(
                match([
                    (Opcode.SYSTEM, Funct3.CSRRW, None, None),
                    (Opcode.SYSTEM, Funct3.CSRRS, None, None),
                    (Opcode.SYSTEM, Funct3.CSRRC, None, None),
                    (Opcode.SYSTEM, Funct3.CSRRWI, None, None),
                    (Opcode.SYSTEM, Funct3.CSRRSI, None, None),
                    (Opcode.SYSTEM, Funct3.CSRRCI, None, None),
                ])),
            self.ecall.eq(
                match([(Opcode.SYSTEM, Funct3.PRIV, None, Funct12.ECALL)])),
            self.ebreak.eq(
                match([(Opcode.SYSTEM, Funct3.PRIV, None, Funct12.EBREAK)])),
            self.mret.eq((self.privmode == PrivMode.Machine)
                         & match([(Opcode.SYSTEM, Funct3.PRIV, None,
                                   Funct12.MRET)])),
            self.fence_i.eq(match([(Opcode.FENCE, Funct3.FENCEI, None, None)
                                   ])),
            self.fence.eq(match([(Opcode.FENCE, Funct3.FENCE, None, None)])),
            self.substract.eq(
                match([(Opcode.OP, Funct3.ADD, Funct7.SUB, None)])),
            self.shift_direction.eq(funct3 == Funct3.SR),
            self.shit_signed.eq(funct7 == Funct7.SRA),
            self.csr_we.eq(~funct3[1] | (self.gpr_rs1 != 0)),
        ]

        if (self.enable_rv32m):
            m.d.comb += [
                self.multiply.eq(
                    match([(Opcode.OP, Funct3.MUL, Funct7.MULDIV, None),
                           (Opcode.OP, Funct3.MULH, Funct7.MULDIV, None),
                           (Opcode.OP, Funct3.MULHU, Funct7.MULDIV, None),
                           (Opcode.OP, Funct3.MULHSU, Funct7.MULDIV, None)])),
                self.divide.eq(
                    match([(Opcode.OP, Funct3.DIV, Funct7.MULDIV, None),
                           (Opcode.OP, Funct3.DIVU, Funct7.MULDIV, None),
                           (Opcode.OP, Funct3.REM, Funct7.MULDIV, None),
                           (Opcode.OP, Funct3.REMU, Funct7.MULDIV, None)]))
            ]

        m.d.comb += self.illegal.eq(~reduce(or_, [
            self.lui, self.aiupc, self.jump, self.branch, self.load,
            self.store, self.aritmetic, self.logic, self.shift, self.compare,
            self.csr, self.ecall, self.ebreak, self.mret, self.fence_i,
            self.fence, self.multiply, self.divide
        ]))

        return m
Exemplo n.º 4
0
Arquivo: standard.py Projeto: zyp/luna
    def elaborate(self, platform):
        m = Module()
        interface = self.interface

        # Create convenience aliases for our interface components.
        setup = interface.setup
        handshake_generator = interface.handshakes_out
        tx = interface.tx

        #
        # Submodules
        #

        # Handler for Get Descriptor requests; responds with our various fixed descriptors.
        m.submodules.get_descriptor = get_descriptor_handler = GetDescriptorHandler(
            self.descriptors)
        m.d.comb += [
            get_descriptor_handler.value.eq(setup.value),
            get_descriptor_handler.length.eq(setup.length),
        ]

        # Handler for various small-constant-response requests (GET_CONFIGURATION, GET_STATUS).
        m.submodules.transmitter = transmitter = \
            StreamSerializer(data_length=2, domain="usb", stream_type=USBInStreamInterface, max_length_width=2)

        #
        # Handlers.
        #
        with m.If(setup.type == USBRequestType.STANDARD):
            with m.FSM(domain="usb"):

                # IDLE -- not handling any active request
                with m.State('IDLE'):

                    # If we've received a new setup packet, handle it.
                    with m.If(setup.received):

                        # Select which standard packet we're going to handler.
                        with m.Switch(setup.request):

                            with m.Case(USBStandardRequests.GET_STATUS):
                                m.next = 'GET_STATUS'
                            with m.Case(USBStandardRequests.SET_ADDRESS):
                                m.next = 'SET_ADDRESS'
                            with m.Case(USBStandardRequests.SET_CONFIGURATION):
                                m.next = 'SET_CONFIGURATION'
                            with m.Case(USBStandardRequests.GET_DESCRIPTOR):
                                m.next = 'GET_DESCRIPTOR'
                            with m.Case(USBStandardRequests.GET_CONFIGURATION):
                                m.next = 'GET_CONFIGURATION'
                            with m.Case():
                                m.next = 'UNHANDLED'

                # GET_STATUS -- Fetch the device's status.
                # For now, we'll always return '0'.
                with m.State('GET_STATUS'):
                    # TODO: handle reporting endpoint stall status
                    # TODO: copy the remote wakeup and bus-powered attributes from bmAttributes of the relevant descriptor?
                    self.handle_simple_data_request(m,
                                                    transmitter,
                                                    0,
                                                    length=2)

                # SET_ADDRESS -- The host is trying to assign us an address.
                with m.State('SET_ADDRESS'):
                    self.handle_register_write_request(
                        m, interface.new_address, interface.address_changed)

                # SET_CONFIGURATION -- The host is trying to select an active configuration.
                with m.State('SET_CONFIGURATION'):
                    # TODO: stall if we don't have a relevant configuration
                    self.handle_register_write_request(
                        m, interface.new_config, interface.config_changed)

                # GET_DESCRIPTOR -- The host is asking for a USB descriptor -- for us to "self describe".
                with m.State('GET_DESCRIPTOR'):
                    m.d.comb += [
                        get_descriptor_handler.tx.attach(tx),
                        handshake_generator.stall.eq(
                            get_descriptor_handler.stall)
                    ]

                    # Respond to our data stage with a descriptor...
                    with m.If(interface.data_requested):
                        m.d.comb += get_descriptor_handler.start.eq(1),

                    # ... and ACK our status stage.
                    with m.If(interface.status_requested):
                        m.d.comb += handshake_generator.ack.eq(1)
                        m.next = 'IDLE'

                # GET_CONFIGURATION -- The host is asking for the active configuration number.
                with m.State('GET_CONFIGURATION'):
                    self.handle_simple_data_request(m, transmitter,
                                                    interface.active_config)

                # UNHANDLED -- we've received a request we're not prepared to handle
                with m.State('UNHANDLED'):

                    # When we next have an opportunity to stall, do so,
                    # and then return to idle.
                    with m.If(interface.data_requested
                              | interface.status_requested):
                        m.d.comb += handshake_generator.stall.eq(1)
                        m.next = 'IDLE'

        return m
Exemplo n.º 5
0
    def elaborate(self, _: Platform) -> Module:
        """Implements the logic of the sequencer card."""
        m = Module()

        # Defaults
        m.d.comb += [
            self._next_instr_phase.eq(0),
            self.reg_to_x.eq(0),
            self.reg_to_y.eq(0),
            self.alu_op_to_z.eq(AluOp.NONE),
            self.mem_rd.eq(0),
            self.mem_wr.eq(0),
            self.mem_wr_mask.eq(0),
            self.csr_to_x.eq(0),
            self.z_to_csr.eq(0),
            self._funct12_to_csr_num.eq(0),
            self._mepc_num_to_csr_num.eq(0),
            self._mcause_to_csr_num.eq(0),
            self._x_reg_select.eq(0),
            self._y_reg_select.eq(0),
            self._z_reg_select.eq(0),
            self.enter_trap.eq(0),
            self.exit_trap.eq(0),
            self.save_trap_csrs.eq(0),
            self.pc_mux_select.eq(SeqMuxSelect.PC),
            self.memaddr_mux_select.eq(SeqMuxSelect.MEMADDR),
            self.memdata_wr_mux_select.eq(SeqMuxSelect.MEMDATA_WR),
            self.tmp_mux_select.eq(SeqMuxSelect.TMP),
            self.x_mux_select.eq(SeqMuxSelect.X),
            self.y_mux_select.eq(SeqMuxSelect.Y),
            self.z_mux_select.eq(SeqMuxSelect.Z),
            self._const.eq(0),
        ]

        m.d.comb += [
            self.load_trap.eq(0),
            self.next_trap.eq(0),
            self.load_exception.eq(0),
            self.next_exception.eq(0),
            self.next_fatal.eq(0),
        ]

        with m.If(self.enable_sequencer_rom):

            # Output control signals
            with m.Switch(self.opcode_select):
                with m.Case(OpcodeSelect.LUI):
                    self.handle_lui(m)

                with m.Case(OpcodeSelect.AUIPC):
                    self.handle_auipc(m)

                with m.Case(OpcodeSelect.OP_IMM):
                    self.handle_op_imm(m)

                with m.Case(OpcodeSelect.OP):
                    self.handle_op(m)

                with m.Case(OpcodeSelect.JAL):
                    self.handle_jal(m)

                with m.Case(OpcodeSelect.JALR):
                    self.handle_jalr(m)

                with m.Case(OpcodeSelect.BRANCH):
                    self.handle_branch(m)

                with m.Case(OpcodeSelect.LOAD):
                    self.handle_load(m)

                with m.Case(OpcodeSelect.STORE):
                    self.handle_store(m)

                with m.Case(OpcodeSelect.CSRS):
                    self.handle_csrs(m)

                with m.Case(OpcodeSelect.MRET):
                    self.handle_MRET(m)

                with m.Case(OpcodeSelect.ECALL):
                    self.handle_ECALL(m)

                with m.Case(OpcodeSelect.EBREAK):
                    self.handle_EBREAK(m)

                with m.Default():
                    self.handle_illegal_instr(m)

        return m
Exemplo n.º 6
0
    def elaborate(self, platform):
        m = Module()

        cpu = Core()
        m.submodules += cpu
        m.domains.ph1 = ph1 = ClockDomain("ph1")
        m.domains.ph2 = ph2 = ClockDomain("ph2", clk_edge="neg")

        # Hook up clocks and reset to pins

        if not SLOWCLK:
            clk1 = platform.request("clk1")
            clk2 = platform.request("clk2")
            rst = platform.request("rst")
            m.d.comb += [
                ph1.rst.eq(rst.i),
                ph2.rst.eq(rst.i),
                ph1.clk.eq(clk1.i),
                ph2.clk.eq(clk2.i),
            ]

        if SLOWCLK:
            clk_freq = platform.default_clk_frequency
            timer = Signal(range(0, int(clk_freq // 2)),
                           reset=int(clk_freq // 2) - 1)
            tick = Signal()
            sync = ClockDomain()

            with m.If(timer == 0):
                m.d.sync += timer.eq(timer.reset)
                m.d.sync += tick.eq(~tick)
            with m.Else():
                m.d.sync += timer.eq(timer - 1)
            m.d.comb += [
                ph1.rst.eq(sync.rst),
                ph2.rst.eq(sync.rst),
                ph1.clk.eq(tick),
                ph2.clk.eq(~tick),
            ]

        # Hook up address lines to pins
        for i in range(16):
            pin = platform.request("addr", i)
            m.d.comb += pin.o.eq(cpu.Addr[i])

        if not FAKEMEM:
            # Hook up data in/out + direction to pins
            for i in range(8):
                pin = platform.request("data", i)
                m.d.comb += pin.o.eq(cpu.Dout[i])
                m.d.ph2 += cpu.Din[i].eq(pin.i)
                m.d.comb += pin.oe.eq(~cpu.RW)

        if FAKEMEM:
            with m.Switch(cpu.Addr):
                for addr, data in mem.items():
                    with m.Case(addr):
                        m.d.comb += cpu.Din.eq(data)
                with m.Default():
                    m.d.comb += cpu.Din.eq(0xFF)
            for i in range(8):
                pin = platform.request("led", i)
                m.d.comb += pin.o.eq(cpu.Addr[i])

        for i in range(2):
            pin = platform.request("reset_state", i)
            m.d.comb += pin.o.eq(cpu.reset_state[i])

        rw = platform.request("rw")
        m.d.comb += rw.o.eq(cpu.RW)

        return m
Exemplo n.º 7
0
    def elaborate(self, platform):
        m = Module()
        interface = self.interface

        # Create convenience aliases for our interface components.
        setup = interface.setup
        handshake_generator = interface.handshakes_out
        tx = interface.tx

        #
        # Submodules
        #

        # Handler for Get Descriptor requests; responds with our various fixed descriptors.
        m.submodules.get_descriptor = get_descriptor_handler = GetDescriptorHandler(
            self.descriptors)
        m.d.comb += [
            get_descriptor_handler.value.eq(setup.value),
            get_descriptor_handler.length.eq(setup.length),
        ]

        # Handler for various small-constant-response requests (GET_CONFIGURATION, GET_STATUS).
        m.submodules.transmitter = transmitter = \
            StreamSerializer(data_length=2, domain="usb", stream_type=USBInStreamInterface, max_length_width=2)

        #
        # Handlers.
        #
        with m.If(setup.type == USBRequestType.STANDARD):
            with m.FSM(domain="usb"):

                # IDLE -- not handling any active request
                with m.State('IDLE'):

                    m.d.usb += [
                        # Start at the beginning of our next / fresh GET_DESCRIPTOR request.
                        get_descriptor_handler.start_position.eq(0),

                        # Always start our responses with DATA1 pids, per [USB 2.0: 8.5.3].
                        self.interface.tx_data_pid.eq(1)
                    ]

                    # If we've received a new setup packet, handle it.
                    with m.If(setup.received):

                        # Select which standard packet we're going to handler.
                        with m.Switch(setup.request):

                            with m.Case(USBStandardRequests.GET_STATUS):
                                m.next = 'GET_STATUS'
                            with m.Case(USBStandardRequests.SET_ADDRESS):
                                m.next = 'SET_ADDRESS'
                            with m.Case(USBStandardRequests.SET_CONFIGURATION):
                                m.next = 'SET_CONFIGURATION'
                            with m.Case(USBStandardRequests.GET_DESCRIPTOR):
                                m.next = 'GET_DESCRIPTOR'
                            with m.Case(USBStandardRequests.GET_CONFIGURATION):
                                m.next = 'GET_CONFIGURATION'
                            with m.Case():
                                m.next = 'UNHANDLED'

                # GET_STATUS -- Fetch the device's status.
                # For now, we'll always return '0'.
                with m.State('GET_STATUS'):
                    # TODO: handle reporting endpoint stall status
                    # TODO: copy the remote wakeup and bus-powered attributes from bmAttributes of the relevant descriptor?
                    self.handle_simple_data_request(m,
                                                    transmitter,
                                                    0,
                                                    length=2)

                # SET_ADDRESS -- The host is trying to assign us an address.
                with m.State('SET_ADDRESS'):
                    self.handle_register_write_request(
                        m, interface.new_address, interface.address_changed)

                # SET_CONFIGURATION -- The host is trying to select an active configuration.
                with m.State('SET_CONFIGURATION'):
                    # TODO: stall if we don't have a relevant configuration
                    self.handle_register_write_request(
                        m, interface.new_config, interface.config_changed)

                # GET_DESCRIPTOR -- The host is asking for a USB descriptor -- for us to "self describe".
                with m.State('GET_DESCRIPTOR'):
                    m.d.comb += [
                        get_descriptor_handler.tx.attach(tx),
                        handshake_generator.stall.eq(
                            get_descriptor_handler.stall)
                    ]

                    # Respond to our data stage with a descriptor...
                    with m.If(interface.data_requested):
                        m.d.comb += get_descriptor_handler.start.eq(1)

                    # Each time we receive an ACK, advance in our descriptor.
                    # This allows us to send descriptors with >64B of content.
                    with m.If(interface.handshakes_in.ack):

                        # NOTE: this logic might need to be scaled by bytes-per-word for USB3, if it's ever used.
                        # For now, we're not using it on USB3 at all, since we assume descriptors always fit in a
                        # USB3 packet.
                        next_start_position = get_descriptor_handler.start_position + self._max_packet_size
                        m.d.usb += [

                            # We've received an ACK; so mark the section we've sent of the descriptor as
                            # received, and move forward...
                            get_descriptor_handler.start_position.eq(
                                next_start_position),

                            # ... and toggle our data PID.
                            self.interface.tx_data_pid.eq(
                                ~self.interface.tx_data_pid)
                        ]

                    # ... and ACK our status stage.
                    with m.If(interface.status_requested):
                        m.d.comb += handshake_generator.ack.eq(1)
                        m.next = 'IDLE'

                # GET_CONFIGURATION -- The host is asking for the active configuration number.
                with m.State('GET_CONFIGURATION'):
                    self.handle_simple_data_request(m, transmitter,
                                                    interface.active_config)

                # UNHANDLED -- we've received a request we're not prepared to handle
                with m.State('UNHANDLED'):

                    # When we next have an opportunity to stall, do so,
                    # and then return to idle.
                    with m.If(interface.data_requested
                              | interface.status_requested):
                        m.d.comb += handshake_generator.stall.eq(1)
                        m.next = 'IDLE'

        return m
Exemplo n.º 8
0
    def elaborate(self, platform):
        m = Module()

        #######################################################################
        # Line State Recovery State Machine
        #
        # The receive path doesn't use a differential receiver.  Because of
        # this there is a chance that one of the differential pairs will appear
        # to have changed to the new state while the other is still in the old
        # state.  The following state machine detects transitions and waits an
        # extra sampling clock before decoding the state on the differential
        # pair.  This transition period # will only ever last for one clock as
        # long as there is no noise on the line.  If there is enough noise on
        # the line then the data may be corrupted and the packet will fail the
        # data integrity checks.
        #
        dpair = Signal(2)
        m.d.comb += dpair.eq(Cat(self._usbn, self._usbp))

        # output signals for use by the clock recovery stage
        line_state_dt = Signal()
        line_state_dj = Signal()
        line_state_dk = Signal()
        line_state_se0 = Signal()
        line_state_se1 = Signal()

        # If we are in a transition state, then we can sample the pair and
        # move to the next corresponding line state.
        with m.FSM(domain="usb_io"):
            with m.State("DT"):
                m.d.comb += line_state_dt.eq(1)

                with m.Switch(dpair):
                    with m.Case(0b10):
                        m.next = "DJ"
                    with m.Case(0b01):
                        m.next = "DK"
                    with m.Case(0b00):
                        m.next = "SE0"
                    with m.Case(0b11):
                        m.next = "SE1"

            # If we are in a valid line state and the value of the pair changes,
            # then we need to move to the transition state.
            with m.State("DJ"):
                m.d.comb += line_state_dj.eq(1)
                with m.If(dpair != 0b10):
                    m.next = "DT"

            with m.State("DK"):
                m.d.comb += line_state_dk.eq(1)
                with m.If(dpair != 0b01):
                    m.next = "DT"

            with m.State("SE0"):
                m.d.comb += line_state_se0.eq(1)
                with m.If(dpair != 0b00):
                    m.next = "DT"

            with m.State("SE1"):
                m.d.comb += line_state_se1.eq(1)
                with m.If(dpair != 0b11):
                    m.next = "DT"

        #######################################################################
        # Clock and Data Recovery
        #
        # The DT state from the line state recovery state machine is used to align to
        # transmit clock.  The line state is sampled in the middle of the bit time.
        #
        # Example of signal relationships
        # -------------------------------
        # line_state        DT  DJ  DJ  DJ  DT  DK  DK  DK  DK  DK  DK  DT  DJ  DJ  DJ
        # line_state_valid  ________----____________----____________----________----____
        # bit_phase         0   0   1   2   3   0   1   2   3   0   1   2   0   1   2
        #

        # We 4x oversample, so make the line_state_phase have
        # 4 possible values.
        line_state_phase = Signal(2)

        m.d.usb_io += [
            self.line_state_valid.eq(line_state_phase == 1),

            # flop all the outputs to help with timing
            self.line_state_dj.eq(line_state_dj),
            self.line_state_dk.eq(line_state_dk),
            self.line_state_se0.eq(line_state_se0),
            self.line_state_se1.eq(line_state_se1),
        ]

        with m.If(line_state_dt):
            m.d.usb_io += [

                # re-align the phase with the incoming transition
                line_state_phase.eq(0),

                # make sure we never assert valid on a transition
                self.line_state_valid.eq(0),
            ]
        with m.Else():
            # keep tracking the clock by incrementing the phase
            m.d.usb_io += line_state_phase.eq(line_state_phase + 1)

        return m
Exemplo n.º 9
0
    def elaborate(self, platform):
        m = Module()

        # Move the pipeline along
        m.d.sync += [
            self.o_x_coord.eq(self.i_x_coord),
            self.o_y_coord.eq(self.i_y_coord),
            self.o_z_coord.eq(self.i_z_coord),

            self.o_red.eq(self.i_red),
            self.o_green.eq(self.i_green),
            self.o_blue.eq(self.i_blue),
            self.o_alpha.eq(self.i_alpha)
        ]

        # Alpha Test, relative to AREF.
        test = Signal()

        with m.If(self.i_enable):
            with m.Switch(self.i_test):
                with m.Case(AlphaTestMode.NEVER):
                    m.d.comb += test.eq(0)
                with m.Case(AlphaTestMode.ALWAYS):
                    m.d.comb += test.eq(1)
                with m.Case(AlphaTestMode.LESS):
                    m.d.comb += test.eq(self.i_alpha < self.i_aref)
                with m.Case(AlphaTestMode.LEQUAL):
                    m.d.comb += test.eq(self.i_alpha <= self.i_aref)
                with m.Case(AlphaTestMode.EQUAL):
                    m.d.comb += test.eq(self.i_alpha == self.i_aref)
                with m.Case(AlphaTestMode.GEQUAL):
                    m.d.comb += test.eq(self.i_alpha >= self.i_aref)
                with m.Case(AlphaTestMode.GREATER):
                    m.d.comb += test.eq(self.i_alpha > self.i_aref)
                with m.Case(AlphaTestMode.NOTEQUAL):
                    m.d.comb += test.eq(self.i_alpha != self.i_aref)
        with m.Else():
            m.d.comb += test.eq(1)

        with m.Switch(self.i_failmod):
            with m.Case(AlphaFailMode.KEEP):
                m.d.sync += [
                    self.o_rgbrndr.eq(self.i_rgbrndr & test),
                    self.o_arndr.eq(self.i_arndr & test),
                    self.o_zrndr.eq(self.i_zrndr & test)
                ]
            with m.Case(AlphaFailMode.FB_ONLY):
                m.d.sync += [
                    self.o_rgbrndr.eq(self.i_rgbrndr),
                    self.o_arndr.eq(self.i_arndr),
                    self.o_zrndr.eq(self.i_zrndr & test)
                ]
            with m.Case(AlphaFailMode.ZB_ONLY):
                m.d.sync += [
                    self.o_rgbrndr.eq(self.i_rgbrndr & test),
                    self.o_arndr.eq(self.i_arndr & test),
                    self.o_zrndr.eq(self.i_zrndr)
                ]
            with m.Case(AlphaFailMode.RGB_ONLY):
                # "RGB_ONLY is effective only when the color format is RGBA32.
                # In other formats, operation is made with FB_ONLY." - GS User's Manual
                with m.If(self.i_fbpxfmt == PixelFormat.PSMCT32):
                    m.d.sync += [
                        self.o_rgbrndr.eq(self.i_rgbrndr),
                        self.o_arndr.eq(self.i_arndr & test),
                        self.o_zrndr.eq(self.i_zrndr & test)
                    ]
                with m.Else():
                    m.d.sync += [
                        self.o_rgbrndr.eq(self.i_rgbrndr),
                        self.o_arndr.eq(self.i_arndr),
                        self.o_zrndr.eq(self.i_zrndr & test)
                    ]

        return m
Exemplo n.º 10
0
    def elaborate(self, platform):
        m = Module()

        # Synchronize the USB signals at our I/O boundary.
        # Despite the assumptions made in ValentyUSB, this line rate recovery FSM
        # isn't enough to properly synchronize these inputs. We'll explicitly synchronize.
        sync_dp = synchronize(m, self._usbp, o_domain="usb_io")
        sync_dn = synchronize(m, self._usbn, o_domain="usb_io")

        #######################################################################
        # Line State Recovery State Machine
        #
        # The receive path doesn't use a differential receiver.  Because of
        # this there is a chance that one of the differential pairs will appear
        # to have changed to the new state while the other is still in the old
        # state.  The following state machine detects transitions and waits an
        # extra sampling clock before decoding the state on the differential
        # pair.  This transition period  will only ever last for one clock as
        # long as there is no noise on the line.  If there is enough noise on
        # the line then the data may be corrupted and the packet will fail the
        # data integrity checks.
        #
        dpair = Cat(sync_dp, sync_dn)

        # output signals for use by the clock recovery stage
        line_state_in_transition = Signal()

        with m.FSM(domain="usb_io") as fsm:
            m.d.usb_io += [
                self.line_state_se0.eq(fsm.ongoing("SE0")),
                self.line_state_se1.eq(fsm.ongoing("SE1")),
                self.line_state_dj.eq(fsm.ongoing("DJ")),
                self.line_state_dk.eq(fsm.ongoing("DK")),
            ]

            # If we are in a transition state, then we can sample the pair and
            # move to the next corresponding line state.
            with m.State("DT"):
                m.d.comb += line_state_in_transition.eq(1)

                with m.Switch(dpair):
                    with m.Case(0b10):
                        m.next = "DJ"
                    with m.Case(0b01):
                        m.next = "DK"
                    with m.Case(0b00):
                        m.next = "SE0"
                    with m.Case(0b11):
                        m.next = "SE1"

            # If we are in a valid line state and the value of the pair changes,
            # then we need to move to the transition state.
            with m.State("DJ"):
                with m.If(dpair != 0b10):
                    m.next = "DT"

            with m.State("DK"):
                with m.If(dpair != 0b01):
                    m.next = "DT"

            with m.State("SE0"):
                with m.If(dpair != 0b00):
                    m.next = "DT"

            with m.State("SE1"):
                with m.If(dpair != 0b11):
                    m.next = "DT"

        #######################################################################
        # Clock and Data Recovery
        #
        # The DT state from the line state recovery state machine is used to align to
        # transmit clock.  The line state is sampled in the middle of the bit time.
        #
        # Example of signal relationships
        # -------------------------------
        # line_state        DT  DJ  DJ  DJ  DT  DK  DK  DK  DK  DK  DK  DT  DJ  DJ  DJ
        # line_state_valid  ________----____________----____________----________----____
        # bit_phase         0   0   1   2   3   0   1   2   3   0   1   2   0   1   2
        #

        # We 4x oversample, so make the line_state_phase have
        # 4 possible values.
        line_state_phase = Signal(2)
        m.d.usb_io += self.line_state_valid.eq(line_state_phase == 1)

        with m.If(line_state_in_transition):
            m.d.usb_io += [
                # re-align the phase with the incoming transition
                line_state_phase.eq(0),

                # make sure we never assert valid on a transition
                self.line_state_valid.eq(0),
            ]
        with m.Else():
            # keep tracking the clock by incrementing the phase
            m.d.usb_io += line_state_phase.eq(line_state_phase + 1)

        return m
Exemplo n.º 11
0
    def elaborate(self, platform):
        """
        """
        m = Module()

        # pins
        ft_clkout_i = platform.request("ft_clkout_i")
        ft_wr_n_o = platform.request("ft_wr_n_o")
        ft_txe_n_i = platform.request("ft_txe_n_i")
        ft_suspend_n_i = platform.request("ft_suspend_n_i")
        ft_oe_n_o = platform.request("ft_oe_n_o")
        ft_rd_n_o = platform.request("ft_rd_n_o")
        ft_siwua_n_o = platform.request("ft_siwua_n_o")
        ft_data_io = platform.request("ft_data_io")
        adc_d_i = platform.request("adc_d_i")
        adc_oe_o = platform.request("adc_oe_o")
        adc_shdn_o = platform.request("adc_shdn_o")
        ext1 = platform.request("ext1")
        pa_en_n_o = platform.request("pa_en_n_o")
        mix_en_n_o = platform.request("mix_en_n_o")

        # signals
        clk80 = Signal()
        pll_fb = Signal()
        chan_a = Signal(self.ADC_WIDTH)
        chan_b = Signal(self.ADC_WIDTH)
        lsb = Signal()
        lock = Signal(RAW_STATE)
        sample_ctr = Signal(range(self.DECIMATE * self.FFT_LEN))
        sample_ctr_max = Const(self.DECIMATE * self.FFT_LEN - 1)
        cons_done = Signal()
        cons_done_clk80_dom = Signal()
        send_start = Signal()
        send_stop = Signal()
        wait_prod = Signal()
        lock_ftclk_dom = Signal()
        lock_ftclk_dom_last = Signal()

        # clock domains
        clk40_neg = ClockDomain("clk40_neg", clk_edge="neg")
        m.domains.clk40_neg = clk40_neg
        m.d.comb += ClockSignal("clk40_neg").eq(ClockSignal("sync"))

        m.domains += ClockDomain("clk60")
        m.d.comb += ClockSignal("clk60").eq(ft_clkout_i.i)
        m.domains += ClockDomain("clk80")
        m.d.comb += ClockSignal("clk80").eq(clk80)

        # ======================== submodules ========================
        # PLL
        m.submodules += Instance(
            "PLLE2_BASE",
            ("p", "CLKFBOUT_MULT", 24),
            ("p", "DIVCLK_DIVIDE", 1),
            ("p", "CLKOUT0_DIVIDE", 12),
            ("p", "CLKIN1_PERIOD", 25),
            ("o", "CLKOUT0", clk80),
            ("i", "CLKIN1", ClockSignal("sync")),
            ("i", "RST", 0),
            ("o", "CLKFBOUT", pll_fb),
            ("i", "CLKFBIN", pll_fb),
        )

        # ADC
        m.submodules.ltc2292 = ltc2292 = LTC2292(
            posedge_domain="sync", negedge_domain="clk40_neg"
        )
        m.d.comb += [
            ltc2292.di.eq(adc_d_i.i),
            chan_a.eq(ltc2292.dao),
            chan_b.eq(ltc2292.dbo),
        ]

        # FIFO
        m.submodules.fifo = fifo = AsyncFIFO(
            width=self.USB_WIDTH,
            depth=self.DECIMATE * self.FFT_LEN * 2,
            r_domain="clk60",
            w_domain="clk80",
        )
        with m.If(lsb):
            m.d.comb += fifo.w_data.eq(chan_a[: self.USB_WIDTH])
        with m.Else():
            m.d.comb += fifo.w_data.eq(
                Cat(
                    chan_a[self.USB_WIDTH :],
                    Const(0, 2 * self.USB_WIDTH - self.ADC_WIDTH),
                )
            )

        # consumption done sync
        m.submodules.cons_done_sync = cons_done_sync = FFSynchronizer(
            i=cons_done, o=cons_done_clk80_dom, o_domain="clk80"
        )

        # lock synch
        m.submodules.lock_sync = lock_sync = FFSynchronizer(
            i=lock, o=lock_ftclk_dom, o_domain="clk60"
        )

        # =========================== logic ==========================
        m.d.comb += [
            pa_en_n_o.o.eq(1),
            mix_en_n_o.o.eq(1),
            adc_oe_o.o.eq(0b01),
            adc_shdn_o.o.eq(0b00),
            ext1.o[0].eq(0b0),
            ext1.o[3].eq(lock),
            ext1.o[1].eq(0b0),
            ext1.o[4].eq(fifo.r_en),
            ext1.o[2].eq(0b0),
            ext1.o[5].eq(fifo.w_en),
        ]

        # write clock domain
        with m.If(lock == RAW_STATE.PROD):
            with m.If(sample_ctr == sample_ctr_max):
                m.d.clk80 += [
                    lock.eq(RAW_STATE.CONS),
                    sample_ctr.eq(0),
                    lsb.eq(0),
                ]
            with m.Else():
                with m.If(lsb):
                    m.d.clk80 += sample_ctr.eq(sample_ctr + 1)
                m.d.clk80 += lsb.eq(~lsb)
        with m.Else():
            with m.If(cons_done_clk80_dom):
                m.d.clk80 += [
                    lock.eq(RAW_STATE.PROD),
                    sample_ctr.eq(0),
                    lsb.eq(0),
                ]

        with m.Switch(lock):
            with m.Case(RAW_STATE.PROD):
                m.d.comb += fifo.w_en.eq(1)
            with m.Case(RAW_STATE.CONS):
                m.d.comb += fifo.w_en.eq(0)

        # read clock domain
        m.d.clk60 += lock_ftclk_dom_last.eq(lock_ftclk_dom)
        with m.If(lock_ftclk_dom == RAW_STATE.CONS & ~wait_prod):
            with m.If(~fifo.r_rdy):
                m.d.clk60 += wait_prod.eq(1)
        with m.Elif(lock_ftclk_dom == RAW_STATE.CONS):
            m.d.clk60 += wait_prod.eq(1)
        with m.Else():
            m.d.clk60 += wait_prod.eq(0)

        m.d.comb += [
            ft_oe_n_o.o.eq(1),
            ft_rd_n_o.o.eq(1),
            ft_siwua_n_o.o.eq(1),
        ]
        with m.Switch(lock_ftclk_dom):
            with m.Case(RAW_STATE.PROD):
                m.d.comb += [
                    send_start.eq(0),
                    send_stop.eq(0),
                    ft_data_io.o.eq(0),
                    ft_wr_n_o.o.eq(1),
                    fifo.r_en.eq(0),
                ]
            with m.Case(RAW_STATE.CONS):
                with m.If(lock_ftclk_dom_last == RAW_STATE.PROD):
                    m.d.comb += send_start.eq(1)
                with m.Else():
                    m.d.comb += send_start.eq(0)

                with m.If(~fifo.r_rdy):
                    m.d.comb += [send_stop.eq(1), cons_done.eq(1)]
                with m.Else():
                    m.d.comb += [send_stop.eq(0), cons_done.eq(0)]

                with m.If(send_start):
                    m.d.comb += [
                        ft_data_io.o.eq(self.START_FLAG),
                        ft_wr_n_o.o.eq(ft_txe_n_i.i),
                        fifo.r_en.eq(1),
                    ]
                with m.Elif(send_stop):
                    m.d.comb += [
                        ft_data_io.o.eq(self.STOP_FLAG),
                        ft_wr_n_o.o.eq(ft_txe_n_i.i),
                        fifo.r_en.eq(0),
                    ]
                with m.Else():
                    with m.If(wait_prod):
                        m.d.comb += [
                            ft_data_io.o.eq(0),
                            ft_wr_n_o.o.eq(1),
                            fifo.r_en.eq(0),
                        ]
                    with m.Else():
                        m.d.comb += [
                            ft_data_io.o.eq(fifo.r_data),
                            ft_wr_n_o.o.eq(~(~ft_txe_n_i.i & fifo.r_en)),
                            fifo.r_en.eq(~ft_txe_n_i.i & fifo.r_rdy),
                        ]

        return m
Exemplo n.º 12
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        m.d.comb += self._ccs.eq(self.ccs)
        m.d.ph1 += self.ccs.eq(self._ccs)

        # intermediates
        carry4 = Signal()
        carry7 = Signal()
        carry8 = Signal()
        overflow = Signal()

        with m.Switch(self.func):
            with m.Case(ALU8Func.LD):
                m.d.comb += self.output.eq(self.input2)
                m.d.comb += self._ccs[Flags.Z].eq(self.output == 0)
                m.d.comb += self._ccs[Flags.N].eq(self.output[7])
                m.d.comb += self._ccs[Flags.V].eq(0)

            with m.Case(ALU8Func.LDCHAIN):
                m.d.comb += self.output.eq(self.input2)
                m.d.comb += self._ccs[Flags.Z].eq((self.output == 0)
                                                  & self.ccs[Flags.Z])
                m.d.comb += self._ccs[Flags.V].eq(0)

            with m.Case(ALU8Func.ADD, ALU8Func.ADC):
                no_carry = (self.func == ALU8Func.ADD)
                carry_in = Mux(no_carry, 0, self.ccs[Flags.C])

                sum0_3 = Cat(self.output[:4], carry4)
                m.d.comb += sum0_3.eq(self.input1[:4] + self.input2[:4] +
                                      carry_in)
                sum4_6 = Cat(self.output[4:7], carry7)
                m.d.comb += sum4_6.eq(self.input1[4:7] + self.input2[4:7] +
                                      carry4)
                sum7 = Cat(self.output[7], carry8)
                m.d.comb += sum7.eq(self.input1[7] + self.input2[7] + carry7)
                m.d.comb += overflow.eq(carry7 ^ carry8)

                m.d.comb += self._ccs[Flags.H].eq(carry4)
                m.d.comb += self._ccs[Flags.N].eq(self.output[7])
                m.d.comb += self._ccs[Flags.Z].eq(self.output == 0)
                m.d.comb += self._ccs[Flags.V].eq(overflow)
                m.d.comb += self._ccs[Flags.C].eq(carry8)

            with m.Case(ALU8Func.SUB, ALU8Func.SBC, ALU8Func.CPXHI,
                        ALU8Func.CPXLO):
                carry_in = Mux(self.func != ALU8Func.SBC, 0, self.ccs[Flags.C])

                sum0_6 = Cat(self.output[:7], carry7)
                m.d.comb += sum0_6.eq(self.input1[:7] + ~self.input2[:7] +
                                      ~carry_in)
                sum7 = Cat(self.output[7], carry8)
                m.d.comb += sum7.eq(self.input1[7] + ~self.input2[7] + carry7)
                m.d.comb += overflow.eq(carry7 ^ carry8)

                with m.If(self.func != ALU8Func.CPXLO):
                    m.d.comb += self._ccs[Flags.N].eq(self.output[7])
                    m.d.comb += self._ccs[Flags.Z].eq(self.output == 0)
                    m.d.comb += self._ccs[Flags.V].eq(overflow)
                    with m.If(self.func != ALU8Func.CPXHI):
                        m.d.comb += self._ccs[Flags.C].eq(~carry8)
                with m.Else():
                    m.d.comb += self._ccs[Flags.Z].eq((self.output == 0)
                                                      & self.ccs[Flags.Z])

            with m.Case(ALU8Func.AND):
                m.d.comb += self.output.eq(self.input1 & self.input2)
                m.d.comb += self._ccs[Flags.Z].eq(self.output == 0)
                m.d.comb += self._ccs[Flags.N].eq(self.output[7])
                m.d.comb += self._ccs[Flags.V].eq(0)

            with m.Case(ALU8Func.EOR):
                m.d.comb += self.output.eq(self.input1 ^ self.input2)
                m.d.comb += self._ccs[Flags.Z].eq(self.output == 0)
                m.d.comb += self._ccs[Flags.N].eq(self.output[7])
                m.d.comb += self._ccs[Flags.V].eq(0)

            with m.Case(ALU8Func.ORA):
                m.d.comb += self.output.eq(self.input1 | self.input2)
                m.d.comb += self._ccs[Flags.Z].eq(self.output == 0)
                m.d.comb += self._ccs[Flags.N].eq(self.output[7])
                m.d.comb += self._ccs[Flags.V].eq(0)

            with m.Case(ALU8Func.INC):
                m.d.comb += self.output.eq(self.input2 + 1)
                m.d.comb += self._ccs[Flags.Z].eq(self.output == 0)
                m.d.comb += self._ccs[Flags.N].eq(self.output[7])
                m.d.comb += self._ccs[Flags.V].eq(self.output == 0x80)

            with m.Case(ALU8Func.DEC):
                m.d.comb += self.output.eq(self.input2 - 1)
                m.d.comb += self._ccs[Flags.Z].eq(self.output == 0)
                m.d.comb += self._ccs[Flags.N].eq(self.output[7])
                m.d.comb += self._ccs[Flags.V].eq(self.output == 0x7F)

            with m.Case(ALU8Func.COM):
                m.d.comb += self.output.eq(0xFF ^ self.input2)
                m.d.comb += self._ccs[Flags.Z].eq(self.output == 0)
                m.d.comb += self._ccs[Flags.N].eq(self.output[7])
                m.d.comb += self._ccs[Flags.V].eq(0)
                m.d.comb += self._ccs[Flags.C].eq(1)

            with m.Case(ALU8Func.ROL):
                # IIIIIIIIC ->
                # COOOOOOOO
                m.d.comb += [
                    LCat(self._ccs[Flags.C],
                         self.output).eq(LCat(self.input2, self.ccs[Flags.C])),
                    self._ccs[Flags.Z].eq(self.output == 0),
                    self._ccs[Flags.N].eq(self.output[7]),
                    self._ccs[Flags.V].eq(self._ccs[Flags.N]
                                          ^ self._ccs[Flags.C]),
                ]

            with m.Case(ALU8Func.ROR):
                # CIIIIIIII ->
                # OOOOOOOOC
                m.d.comb += [
                    LCat(self.output, self._ccs[Flags.C]).eq(
                        LCat(self.ccs[Flags.C], self.input2)),
                    self._ccs[Flags.Z].eq(self.output == 0),
                    self._ccs[Flags.N].eq(self.output[7]),
                    self._ccs[Flags.V].eq(self._ccs[Flags.N]
                                          ^ self._ccs[Flags.C]),
                ]

            with m.Case(ALU8Func.ASL):
                # IIIIIIII0 ->
                # COOOOOOOO
                m.d.comb += [
                    LCat(self._ccs[Flags.C],
                         self.output).eq(LCat(self.input2, Const(0))),
                    self._ccs[Flags.Z].eq(self.output == 0),
                    self._ccs[Flags.N].eq(self.output[7]),
                    self._ccs[Flags.V].eq(self._ccs[Flags.N]
                                          ^ self._ccs[Flags.C]),
                ]

            with m.Case(ALU8Func.ASR):
                # 7IIIIIIII ->  ("7" is the repeat of input[7])
                # OOOOOOOOC
                m.d.comb += [
                    LCat(self.output, self._ccs[Flags.C]).eq(
                        LCat(self.input2[7], self.input2)),
                    self._ccs[Flags.Z].eq(self.output == 0),
                    self._ccs[Flags.N].eq(self.output[7]),
                    self._ccs[Flags.V].eq(self._ccs[Flags.N]
                                          ^ self._ccs[Flags.C]),
                ]

            with m.Case(ALU8Func.LSR):
                # 0IIIIIIII ->
                # OOOOOOOOC
                m.d.comb += [
                    LCat(self.output,
                         self._ccs[Flags.C]).eq(LCat(Const(0), self.input2)),
                    self._ccs[Flags.Z].eq(self.output == 0),
                    self._ccs[Flags.N].eq(self.output[7]),
                    self._ccs[Flags.V].eq(self._ccs[Flags.N]
                                          ^ self._ccs[Flags.C]),
                ]

            with m.Case(ALU8Func.CLC):
                m.d.comb += self._ccs[Flags.C].eq(0)

            with m.Case(ALU8Func.SEC):
                m.d.comb += self._ccs[Flags.C].eq(1)

            with m.Case(ALU8Func.CLV):
                m.d.comb += self._ccs[Flags.V].eq(0)

            with m.Case(ALU8Func.SEV):
                m.d.comb += self._ccs[Flags.V].eq(1)

            with m.Case(ALU8Func.CLI):
                m.d.comb += self._ccs[Flags.I].eq(0)

            with m.Case(ALU8Func.SEI):
                m.d.comb += self._ccs[Flags.I].eq(1)

            with m.Case(ALU8Func.CLZ):
                m.d.comb += self._ccs[Flags.Z].eq(0)

            with m.Case(ALU8Func.SEZ):
                m.d.comb += self._ccs[Flags.Z].eq(1)

            with m.Case(ALU8Func.TAP):
                m.d.comb += self._ccs.eq(self.input1 | 0b11000000)

            with m.Case(ALU8Func.TPA):
                m.d.comb += self.output.eq(self.ccs | 0b11000000)

            with m.Case(ALU8Func.SEF):
                m.d.comb += self._ccs.eq(self.input1 | 0b11000000)

            with m.Case(ALU8Func.DAA):
                adjust = Signal(8)
                low = self.input1[:4]
                high = self.input1[4:]
                low_ten_or_more = low >= 0xA
                high_ten_or_more = high >= 0xA

                with m.If(low_ten_or_more | self.ccs[Flags.H]):
                    m.d.comb += adjust[:4].eq(6)
                with m.If(high_ten_or_more
                          | self.ccs[Flags.C]
                          | (low_ten_or_more & (high == 9))):
                    m.d.comb += adjust[4:].eq(6)
                sum9 = LCat(carry8, self.output)

                m.d.comb += sum9.eq(self.input1 + adjust)
                m.d.comb += self._ccs[Flags.N].eq(self.output[7])
                m.d.comb += self._ccs[Flags.Z].eq(self.output == 0)
                m.d.comb += self._ccs[Flags.C].eq(carry8 | self.ccs[Flags.C])

            with m.Default():
                m.d.comb += self.output.eq(self.input1)

        return m
Exemplo n.º 13
0
 def multiplex_to_reg_nums(self, m: Module):
     with m.Switch(self._x_reg_select):
         with m.Case(InstrReg.ZERO):
             m.d.comb += self.x_reg.eq(0)
         with m.Case(InstrReg.RS1):
             m.d.comb += self.x_reg.eq(self._rs1)
         with m.Case(InstrReg.RS2):
             m.d.comb += self.x_reg.eq(self._rs2)
         with m.Case(InstrReg.RD):
             m.d.comb += self.x_reg.eq(self._rd)
     with m.Switch(self._y_reg_select):
         with m.Case(InstrReg.ZERO):
             m.d.comb += self.y_reg.eq(0)
         with m.Case(InstrReg.RS1):
             m.d.comb += self.y_reg.eq(self._rs1)
         with m.Case(InstrReg.RS2):
             m.d.comb += self.y_reg.eq(self._rs2)
         with m.Case(InstrReg.RD):
             m.d.comb += self.y_reg.eq(self._rd)
     with m.Switch(self._z_reg_select):
         with m.Case(InstrReg.ZERO):
             m.d.comb += self.z_reg.eq(0)
         with m.Case(InstrReg.RS1):
             m.d.comb += self.z_reg.eq(self._rs1)
         with m.Case(InstrReg.RS2):
             m.d.comb += self.z_reg.eq(self._rs2)
         with m.Case(InstrReg.RD):
             m.d.comb += self.z_reg.eq(self._rd)
Exemplo n.º 14
0
 def multiplex_to(self, m: Module, sig: Signal, sel: Signal, clk: str):
     with m.Switch(sel):
         with m.Case(SeqMuxSelect.MEMDATA_WR):
             m.d[clk] += sig.eq(self.state.memdata_wr)
         with m.Case(SeqMuxSelect.MEMDATA_RD):
             m.d[clk] += sig.eq(self.memdata_rd)
         with m.Case(SeqMuxSelect.MEMADDR):
             m.d[clk] += sig.eq(self.state.memaddr)
         with m.Case(SeqMuxSelect.MEMADDR_LSB_MASKED):
             m.d[clk] += sig.eq(self.state.memaddr & 0xFFFFFFFE)
         with m.Case(SeqMuxSelect.PC):
             m.d[clk] += sig.eq(self.state._pc)
         with m.Case(SeqMuxSelect.PC_PLUS_4):
             m.d[clk] += sig.eq(self._pc_plus_4)
         with m.Case(SeqMuxSelect.MTVEC):
             m.d[clk] += sig.eq(self.state._mtvec)
         with m.Case(SeqMuxSelect.MTVEC_LSR2):
             m.d[clk] += sig.eq(self.state._mtvec >> 2)
         with m.Case(SeqMuxSelect.TMP):
             m.d[clk] += sig.eq(self.state._tmp)
         with m.Case(SeqMuxSelect.IMM):
             m.d[clk] += sig.eq(self._imm)
         with m.Case(SeqMuxSelect.INSTR):
             m.d[clk] += sig.eq(self.state._instr)
         with m.Case(SeqMuxSelect.X):
             m.d[clk] += sig.eq(self.data_x_in)
         with m.Case(SeqMuxSelect.Y):
             m.d[clk] += sig.eq(self.data_y_in)
         with m.Case(SeqMuxSelect.Z):
             m.d[clk] += sig.eq(self.data_z_in)
         with m.Case(SeqMuxSelect.Z_LSL2):
             m.d[clk] += sig.eq(self.data_z_in << 2)
         with m.Case(SeqMuxSelect.CONST):
             m.d[clk] += sig.eq(self.decode_const(m))
Exemplo n.º 15
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        m.d.comb += self._ccs.eq(self.ccs)
        m.d.ph1 += self.ccs.eq(self._ccs)

        # intermediates
        carry4 = Signal()
        carry7 = Signal()
        carry8 = Signal()
        overflow = Signal()

        with m.Switch(self.func):
            with m.Case(ALU8Func.LD):
                m.d.comb += self.output.eq(self.input2)
                m.d.comb += self._ccs[_Z].eq(self.output == 0)
                m.d.comb += self._ccs[_N].eq(self.output[7])
                m.d.comb += self._ccs[_V].eq(0)

            with m.Case(ALU8Func.ADD, ALU8Func.ADC):
                carry_in = Mux(self.func == ALU8Func.ADD, 0, self.ccs[_C])

                sum0_3 = Cat(self.output[:4], carry4)
                m.d.comb += sum0_3.eq(self.input1[:4] + self.input2[:4] +
                                      carry_in)
                sum4_6 = Cat(self.output[4:7], carry7)
                m.d.comb += sum4_6.eq(self.input1[4:7] + self.input2[4:7] +
                                      carry4)
                sum7 = Cat(self.output[7], carry8)
                m.d.comb += sum7.eq(self.input1[7] + self.input2[7] + carry7)
                m.d.comb += overflow.eq(carry7 ^ carry8)
                m.d.comb += self._ccs[_H].eq(carry4)
                m.d.comb += self._ccs[_N].eq(self.output[7])
                m.d.comb += self._ccs[_Z].eq(self.output == 0)
                m.d.comb += self._ccs[_V].eq(overflow)
                m.d.comb += self._ccs[_C].eq(carry8)

            with m.Case(ALU8Func.SUB, ALU8Func.SBC):
                carry_in = Mux(self.func == ALU8Func.SUB, 0, self.ccs[_C])

                sum0_6 = Cat(self.output[:7], carry7)
                m.d.comb += sum0_6.eq(self.input1[:7] + ~self.input2[:7] +
                                      ~carry_in)
                sum7 = Cat(self.output[7], carry8)
                m.d.comb += sum7.eq(self.input1[7] + ~self.input2[7] + carry7)
                m.d.comb += overflow.eq(carry7 ^ carry8)
                m.d.comb += self._ccs[_N].eq(self.output[7])
                m.d.comb += self._ccs[_Z].eq(self.output == 0)
                m.d.comb += self._ccs[_V].eq(overflow)
                m.d.comb += self._ccs[_C].eq(~carry8)

            with m.Case(ALU8Func.AND):
                m.d.comb += self.output.eq(self.input1 & self.input2)
                m.d.comb += self._ccs[_Z].eq(self.output == 0)
                m.d.comb += self._ccs[_N].eq(self.output[7])
                m.d.comb += self._ccs[_V].eq(0)

            with m.Case(ALU8Func.EOR):
                m.d.comb += self.output.eq(self.input1 ^ self.input2)
                m.d.comb += self._ccs[_Z].eq(self.output == 0)
                m.d.comb += self._ccs[_N].eq(self.output[7])
                m.d.comb += self._ccs[_V].eq(0)

            with m.Case(ALU8Func.ORA):
                m.d.comb += self.output.eq(self.input1 | self.input2)
                m.d.comb += self._ccs[_Z].eq(self.output == 0)
                m.d.comb += self._ccs[_N].eq(self.output[7])
                m.d.comb += self._ccs[_V].eq(0)

        return m
Exemplo n.º 16
0
    def elaborate(self, _: Platform) -> Module:
        """Implements the logic of the shifter card."""
        m = Module()

        input_reverse = _ConditionalReverser(width=32)
        shift1 = _ConditionalShiftRight(width=32, N=1)
        shift2 = _ConditionalShiftRight(width=32, N=2)
        shift4 = _ConditionalShiftRight(width=32, N=4)
        shift8 = _ConditionalShiftRight(width=32, N=8)
        shift16 = _ConditionalShiftRight(width=32, N=16)
        output_reverse = _ConditionalReverser(width=32)
        output_buffer = TransparentLatch(size=32)

        m.submodules += [
            input_reverse, shift1, shift2, shift4, shift8, shift16,
            output_reverse, output_buffer
        ]

        # Hook up inputs and outputs

        m.d.comb += [
            input_reverse.data_in.eq(self.data_x),
            shift1.data_in.eq(input_reverse.data_out),
            shift2.data_in.eq(shift1.data_out),
            shift4.data_in.eq(shift2.data_out),
            shift8.data_in.eq(shift4.data_out),
            shift16.data_in.eq(shift8.data_out),
            output_reverse.data_in.eq(shift16.data_out),
            output_buffer.data_in.eq(output_reverse.data_out),
            self.data_z.eq(output_buffer.data_out),
        ]

        # Some flags
        shift_arith = Signal()
        shift_left = Signal()

        m.d.comb += shift_arith.eq(self.alu_op == AluOp.SRA)
        m.d.comb += shift_left.eq(self.alu_op == AluOp.SLL)

        m.d.comb += [
            input_reverse.en.eq(shift_left),
            output_reverse.en.eq(shift_left),
            shift1.arithmetic.eq(shift_arith),
            shift2.arithmetic.eq(shift_arith),
            shift4.arithmetic.eq(shift_arith),
            shift8.arithmetic.eq(shift_arith),
            shift16.arithmetic.eq(shift_arith),
        ]

        # Shift amount
        shamt = self.data_y[:5]

        m.d.comb += [
            shift1.en.eq(shamt[0]),
            shift2.en.eq(shamt[1]),
            shift4.en.eq(shamt[2]),
            shift8.en.eq(shamt[3]),
            shift16.en.eq(shamt[4]),
        ]

        m.d.comb += output_buffer.le.eq(1)
        m.d.comb += output_buffer.n_oe.eq(1)

        with m.Switch(self.alu_op):
            with m.Case(AluOp.SLL, AluOp.SRL, AluOp.SRA):
                m.d.comb += output_buffer.n_oe.eq(0)
            with m.Default():
                m.d.comb += output_buffer.n_oe.eq(1)

        return m
Exemplo n.º 17
0
    def elaborate(self, platform):
        m = Module()

        # constants (at least, the important ones)
        if self.configuration.getOption('isa', 'enable_extra_csr'):
            misa = 0x1 << 30 | (1 << (ord('i') - ord('a'))
                                )  # 32-bits processor. RV32IM
            if self.configuration.getOption('isa', 'enable_rv32m'):
                misa |= 1 << (ord('m') - ord('a'))  # RV32M

            m.d.sync += [
                self.csr.misa.read.eq(misa),
                self.csr.mhartid.read.eq(
                    0),  # ID 0 FOREVER. TODO: make this read only
                self.csr.mimpid.read.eq(0),  # No implemented = 0
                self.csr.marchid.read.eq(0),  # No implemented = 0
                self.csr.mvendorid.read.eq(0)  # No implemented = 0
            ]
        m.d.sync += self.csr.mstatus.read.mpp.eq(0b11)  # Only machine mode

        traps = m.submodules.traps = PriorityEncoder(16)
        m.d.comb += [
            traps.i[ExceptionCause.E_INST_ADDR_MISALIGNED].eq(
                self.m_fetch_misalign),
            traps.i[ExceptionCause.E_INST_ACCESS_FAULT].eq(self.m_fetch_error),
            traps.i[ExceptionCause.E_ILLEGAL_INST].eq(self.m_illegal),
            traps.i[ExceptionCause.E_BREAKPOINT].eq(self.m_ebreak),
            traps.i[ExceptionCause.E_LOAD_ADDR_MISALIGNED].eq(
                self.m_load_misalign),
            traps.i[ExceptionCause.E_LOAD_ACCESS_FAULT].eq(self.m_load_error),
            traps.i[ExceptionCause.E_STORE_AMO_ADDR_MISALIGNED].eq(
                self.m_store_misalign),
            traps.i[ExceptionCause.E_STORE_AMO_ACCESS_FAULT].eq(
                self.m_store_error),
            traps.i[ExceptionCause.E_ECALL_FROM_M].eq(self.m_ecall)
        ]

        interrupts = m.submodules.interrupts = PriorityEncoder(16)
        m.d.comb += [
            interrupts.i[ExceptionCause.I_M_SOFTWARE].eq(
                self.csr.mip.read.msip & self.csr.mie.read.msie),
            interrupts.i[ExceptionCause.I_M_TIMER].eq(
                self.csr.mip.read.mtip & self.csr.mie.read.mtie),
            interrupts.i[ExceptionCause.I_M_EXTERNAL].eq(
                self.csr.mip.read.meip & self.csr.mie.read.meie),
        ]

        m.d.sync += [
            self.csr.mip.read.msip.eq(self.software_interrupt),
            self.csr.mip.read.mtip.eq(self.timer_interrupt),
            self.csr.mip.read.meip.eq(self.external_interrupt)
        ]

        # generate the exception/trap/interrupt signal to kill the pipeline
        m.d.comb += self.m_exception.eq(~traps.n | (
            ~interrupts.n & self.csr.mstatus.read.mie & ~self.m_store))

        # default behavior for all registers.
        for reg in self.csr.csr_list:
            with m.If(reg.we):
                m.d.sync += reg.read.eq(reg.write)

        # behavior for exception handling
        with m.If(self.m_valid):
            with m.If(self.m_exception):
                # Register the exception and move one priviledge mode down.
                # No other priviledge mode, so stay in 'machine' mode
                m.d.sync += [
                    self.csr.mepc.read.base.eq(self.m_pc[2:]),
                    self.csr.mstatus.read.mpie.eq(self.csr.mstatus.read.mie),
                    self.csr.mstatus.read.mie.eq(0)
                ]
                # store cause/mtval
                with m.If(~traps.n):
                    m.d.sync += [
                        self.csr.mcause.read.ecode.eq(traps.o),
                        self.csr.mcause.read.interrupt.eq(0)
                    ]
                    with m.Switch(traps.o):
                        with m.Case(ExceptionCause.E_INST_ADDR_MISALIGNED):
                            m.d.sync += self.csr.mtval.read.eq(
                                self.m_pc_misalign)
                        with m.Case(ExceptionCause.E_INST_ACCESS_FAULT):
                            m.d.sync += self.csr.mtval.read.eq(
                                self.m_fetch_badaddr)
                        with m.Case(ExceptionCause.E_ILLEGAL_INST):
                            m.d.sync += self.csr.mtval.read.eq(
                                self.m_instruction)
                        with m.Case(ExceptionCause.E_BREAKPOINT):
                            m.d.sync += self.csr.mtval.read.eq(self.m_pc)
                        with m.Case(
                                ExceptionCause.E_LOAD_ADDR_MISALIGNED,
                                ExceptionCause.E_STORE_AMO_ADDR_MISALIGNED):
                            m.d.sync += self.csr.mtval.read.eq(
                                self.m_ls_misalign)
                        with m.Case(ExceptionCause.E_LOAD_ACCESS_FAULT,
                                    ExceptionCause.E_STORE_AMO_ACCESS_FAULT):
                            m.d.sync += self.csr.mtval.read.eq(
                                self.m_load_store_badaddr)
                        with m.Default():
                            m.d.sync += self.csr.mtval.read.eq(0)

                with m.Else():
                    m.d.sync += [
                        self.csr.mcause.read.ecode.eq(interrupts.o),
                        self.csr.mcause.read.interrupt.eq(1)
                    ]
            with m.Elif(self.m_mret):
                # restore old mie
                # No other priviledge mode, so nothing more to do
                m.d.sync += self.csr.mstatus.read.mie.eq(
                    self.csr.mstatus.read.mpie)

        # counters
        if self.configuration.getOption('isa', 'enable_extra_csr'):
            mcycle = Signal(64)
            minstret = Signal(64)

            m.d.sync += [
                self.csr.mcycle.read.eq(mcycle[:32]),
                self.csr.mcycleh.read.eq(mcycle[32:64]),
                #
                self.csr.minstret.read.eq(minstret[:32]),
                self.csr.minstreth.read.eq(minstret[32:64])
            ]
            m.d.comb += mcycle.eq(
                Cat(self.csr.mcycle.read, self.csr.mcycleh.read) + 1)
            with m.If(self.w_retire):
                m.d.comb += minstret.eq(
                    Cat(self.csr.minstret.read, self.csr.minstreth.read) + 1)
            with m.Else():
                m.d.comb += minstret.eq(
                    Cat(self.csr.minstret.read, self.csr.minstreth.read))

        return m
Exemplo n.º 18
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        m.domains.ramg = ClockDomain(async_reset=True, local=True)
        m.domains.romb0 = ClockDomain(async_reset=True, local=True)
        m.domains.romb1 = ClockDomain(async_reset=True, local=True)
        m.domains.ramb = ClockDomain(async_reset=True, local=True)

        ramg_clk = ClockSignal("ramg")
        romb0_clk = ClockSignal("romb0")
        romb1_clk = ClockSignal("romb1")
        ramb_clk = ClockSignal("ramb")

        m.d.comb += [
            ResetSignal("ramg").eq(self.cart_rst),
            ResetSignal("romb0").eq(self.cart_rst),
            ResetSignal("romb1").eq(self.cart_rst),
            ResetSignal("ramb").eq(self.cart_rst),
        ]

        ramg = Signal(8)
        romb0 = Signal(8, reset=0x01)
        romb1 = Signal(1)
        ramb = Signal(4)

        m.d.ramg += ramg.eq(self.cart_data)
        m.d.romb0 += romb0.eq(self.cart_data)
        m.d.romb1 += romb1.eq(self.cart_data)
        m.d.ramb += ramb.eq(self.cart_data)

        m.d.comb += [
            ramg_clk.eq(1),
            romb0_clk.eq(1),
            romb1_clk.eq(1),
            ramb_clk.eq(1)
        ]
        with m.If(self.cart_wr):
            with m.Switch(self.cart_addr[12:]):
                with m.Case(0b0000):
                    m.d.comb += ramg_clk.eq(0)
                with m.Case(0b0001):
                    m.d.comb += ramg_clk.eq(0)
                with m.Case(0b0010):
                    m.d.comb += romb0_clk.eq(0)
                with m.Case(0b0011):
                    m.d.comb += romb1_clk.eq(0)
                with m.Case(0b0100):
                    m.d.comb += ramb_clk.eq(0)
                with m.Case(0b0101):
                    m.d.comb += ramb_clk.eq(0)

        m.d.comb += [
            self.ram_en.eq(ramg == 0x0A),
            self.ram_bank.eq(ramb),
        ]
        with m.If(self.cart_addr[14]):
            m.d.comb += self.rom_bank.eq(Cat(romb0, romb1))
        with m.Else():
            m.d.comb += self.rom_bank.eq(0)

        return m
Exemplo n.º 19
0
 def execute(self, m: Module):
     """Execute the instruction in the instr register."""
     with m.Switch(self.instr):
         with m.Case("00000001"):  # NOP
             self.NOP(m)
         with m.Case("00000110"):  # TAP
             self.TAP(m)
         with m.Case("00000111"):  # TPA
             self.TPA(m)
         with m.Case("0000100-"):  # INX/DEX
             self.IN_DE_X(m)
         with m.Case("0000101-"):  # CLV, SEV
             self.CL_SE_V(m)
         with m.Case("0000110-"):  # CLC, SEC
             self.CL_SE_C(m)
         with m.Case("0000111-"):  # CLI, SEI
             self.CL_SE_I(m)
         with m.Case("0010----"):  # Branch instructions
             self.BR(m)
         with m.Case("01--0000"):  # NEG
             self.ALU2(m, ALU8Func.SUB, 0, 1)
         with m.Case("01--0011"):  # COM
             self.ALU2(m, ALU8Func.COM, 0, 1)
         with m.Case("01--0100"):  # LSR
             self.ALU2(m, ALU8Func.LSR, 0, 1)
         with m.Case("01--0110"):  # ROR
             self.ALU2(m, ALU8Func.ROR, 0, 1)
         with m.Case("01--0111"):  # ASR
             self.ALU2(m, ALU8Func.ASR, 0, 1)
         with m.Case("01--1000"):  # ASL
             self.ALU2(m, ALU8Func.ASL, 0, 1)
         with m.Case("01--1001"):  # ROL
             self.ALU2(m, ALU8Func.ROL, 0, 1)
         with m.Case("01--1010"):  # DEC
             self.ALU2(m, ALU8Func.DEC, 0, 1)
         with m.Case("01--1100"):  # INC
             self.ALU2(m, ALU8Func.INC, 0, 1)
         with m.Case("01--1101"):  # TST
             self.ALU2(m, ALU8Func.SUB, 1, 0, store=False)
         with m.Case("011-1110"):  # JMP
             self.JMP(m)
         with m.Case("01--1111"):  # CLR
             self.ALU2(m, ALU8Func.SUB, 1, 1)
         with m.Case("1---0110"):  # LDA
             self.ALU(m, ALU8Func.LD)
         with m.Case("1---0000"):  # SUB
             self.ALU(m, ALU8Func.SUB)
         with m.Case("1---0001"):  # CMP
             self.ALU(m, ALU8Func.SUB, store=False)
         with m.Case("1---0010"):  # SBC
             self.ALU(m, ALU8Func.SBC)
         with m.Case("1---0100"):  # AND
             self.ALU(m, ALU8Func.AND)
         with m.Case("1---0101"):  # BIT
             self.ALU(m, ALU8Func.AND, store=False)
         with m.Case("1--10111", "1-100111"):  # STA
             self.STA(m)
         with m.Case("1---1000"):  # EOR
             self.ALU(m, ALU8Func.EOR)
         with m.Case("1---1001"):  # ADC
             self.ALU(m, ALU8Func.ADC)
         with m.Case("1---1010"):  # ORA
             self.ALU(m, ALU8Func.ORA)
         with m.Case("1---1011"):  # ADD
             self.ALU(m, ALU8Func.ADD)
         with m.Default():  # Illegal
             self.end_instr(m, self.pc)
Exemplo n.º 20
0
    def elaborate(self, platform):
        m = Module()

        # Move the pipeline along
        m.d.sync += [
            self.o_rgbrndr.eq(self.i_rgbrndr),
            self.o_arndr.eq(self.i_arndr),
            self.o_zrndr.eq(self.i_zrndr),
            self.o_x_coord.eq(self.i_x_coord),
            self.o_y_coord.eq(self.i_y_coord),
            self.o_z_coord.eq(self.i_z_coord),
            self.o_alpha.eq(self.i_alpha),
        ]

        a_red = Signal(8)
        a_green = Signal(8)
        a_blue = Signal(8)
        with m.Switch(self.i_blend_a):
            with m.Case(BlendRGB.SRC):
                m.d.comb += a_red.eq(self.i_red)
                m.d.comb += a_green.eq(self.i_green)
                m.d.comb += a_blue.eq(self.i_blue)
            with m.Case(BlendRGB.FB):
                m.d.comb += a_red.eq(self.i_fbred)
                m.d.comb += a_green.eq(self.i_fbgreen)
                m.d.comb += a_blue.eq(self.i_fbblue)
            with m.Case(BlendRGB.ZERO):
                m.d.comb += a_red.eq(0)
                m.d.comb += a_green.eq(0)
                m.d.comb += a_blue.eq(0)

        b_red = Signal(8)
        b_green = Signal(8)
        b_blue = Signal(8)
        with m.Switch(self.i_blend_b):
            with m.Case(BlendRGB.SRC):
                m.d.comb += b_red.eq(self.i_red)
                m.d.comb += b_green.eq(self.i_green)
                m.d.comb += b_blue.eq(self.i_blue)
            with m.Case(BlendRGB.FB):
                m.d.comb += b_red.eq(self.i_fbred)
                m.d.comb += b_green.eq(self.i_fbgreen)
                m.d.comb += b_blue.eq(self.i_fbblue)
            with m.Case(BlendRGB.ZERO):
                m.d.comb += b_red.eq(0)
                m.d.comb += b_green.eq(0)
                m.d.comb += b_blue.eq(0)

        c = Signal(8)
        with m.Switch(self.i_blend_c):
            with m.Case(BlendAlpha.SRC):
                m.d.comb += c.eq(self.i_alpha)
            with m.Case(BlendAlpha.FB):
                m.d.comb += c.eq(self.i_fbalpha)
            with m.Case(BlendAlpha.FIX):
                m.d.comb += c.eq(self.i_fix)

        d_red = Signal(8)
        d_green = Signal(8)
        d_blue = Signal(8)
        with m.Switch(self.i_blend_d):
            with m.Case(BlendRGB.SRC):
                m.d.comb += d_red.eq(self.i_red)
                m.d.comb += d_green.eq(self.i_green)
                m.d.comb += d_blue.eq(self.i_blue)
            with m.Case(BlendRGB.FB):
                m.d.comb += d_red.eq(self.i_fbred)
                m.d.comb += d_green.eq(self.i_fbgreen)
                m.d.comb += d_blue.eq(self.i_fbblue)
            with m.Case(BlendRGB.ZERO):
                m.d.comb += d_red.eq(0)
                m.d.comb += d_green.eq(0)
                m.d.comb += d_blue.eq(0)

        with m.If(self.i_enable & (~self.i_alphaen | self.i_alpha[7])):
            m.d.sync += [
                self.o_red.eq((((a_red - b_red) * c) >> 7) + d_red),
                self.o_green.eq((((a_green - b_green) * c) >> 7) + d_green),
                self.o_blue.eq((((a_blue - b_blue) * c) >> 7) + d_blue)
            ]
        with m.Else():
            m.d.sync += [
                self.o_red.eq(self.i_red),
                self.o_green.eq(self.i_green),
                self.o_blue.eq(self.i_blue)
            ]

        return m
Exemplo n.º 21
0
    def elaborate(self, platform):
        m = Module()

        cpu = Core()
        m.submodules += cpu
        m.domains.ph1 = ph1 = ClockDomain("ph1")
        m.domains.ph2 = ph2 = ClockDomain("ph2", clk_edge="neg")

        # Hook up clocks and reset to pins

        if not SLOWCLK:
            clk1 = platform.request("clk1")
            clk2 = platform.request("clk2")
            rst = platform.request("rst")
            m.d.comb += [
                ph1.rst.eq(rst.i),
                ph2.rst.eq(rst.i),
                ph1.clk.eq(clk1.i),
                ph2.clk.eq(clk2.i),
            ]

        if SLOWCLK:
            clk_freq = platform.default_clk_frequency
            timer = Signal(range(0, int(clk_freq // 2)),
                           reset=int(clk_freq // 2) - 1)
            tick = Signal()
            sync = ClockDomain()

            with m.If(timer == 0):
                m.d.sync += timer.eq(timer.reset)
                m.d.sync += tick.eq(~tick)
            with m.Else():
                m.d.sync += timer.eq(timer - 1)
            m.d.comb += [
                ph1.rst.eq(sync.rst),
                ph2.rst.eq(sync.rst),
                ph1.clk.eq(tick),
                ph2.clk.eq(~tick),
            ]

        # Hook up address lines to pins
        addr = []
        for i in range(16):
            pin = platform.request("addr", i)
            m.d.comb += pin.o.eq(cpu.Addr[i])
            addr.append(pin)

        data = []
        if not FAKEMEM:
            # Hook up data in/out + direction to pins
            for i in range(8):
                pin = platform.request("data", i)
                m.d.comb += pin.o.eq(cpu.Dout[i])
                m.d.ph2 += cpu.Din[i].eq(pin.i)
                data.append(pin)

        if FAKEMEM:
            with m.Switch(cpu.Addr):
                for a, d in mem.items():
                    with m.Case(a):
                        m.d.comb += cpu.Din.eq(d)
                with m.Default():
                    m.d.comb += cpu.Din.eq(0x00)
            for i in range(8):
                pin = platform.request("led", i)
                m.d.comb += pin.o.eq(cpu.Addr[i])

        rw = platform.request("rw")
        m.d.comb += rw.o.eq(cpu.RW)

        nIRQ = platform.request("n_irq")
        nNMI = platform.request("n_nmi")
        m.d.ph2 += cpu.IRQ.eq(~nIRQ)
        m.d.ph2 += cpu.NMI.eq(~nNMI)

        ba = platform.request("ba")
        m.d.comb += ba.o.eq(cpu.BA)
        m.d.comb += rw.oe.eq(~cpu.BA)
        for i in range(len(addr)):
            m.d.comb += addr[i].oe.eq(~cpu.BA)
        for i in range(len(data)):
            m.d.comb += data[i].oe.eq(~cpu.BA & ~cpu.RW)

        return m
Exemplo n.º 22
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        m.d.sync += self.PSW.eq(self._psw)
        m.d.comb += self._psw.eq(self.PSW)

        with m.Switch(self.oper):
            with m.Case(Operation.NOP):
                if self.verification is Operation.NOP:
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self._psw.N == self.PSW.N),
                            Assert(self._psw.V == self.PSW.V),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == self.PSW.Z),
                            Assert(self._psw.C == self.PSW.C),
                        ]

            with m.Case(Operation.ADC):
                low = Cat(self.result[:4], self._psw.H)
                high = Cat(self.result[4:], self._psw.C)

                m.d.comb += [
                    low.eq(self.inputa[:4] + self.inputb[:4] + self.PSW.C),
                    high.eq(self.inputa[4:] + self.inputb[4:] + self._psw.H),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                    self._psw.V.eq(self.result[7] != self._psw.C),
                ]
                if self.verification is Operation.ADC:
                    r = Signal(8)
                    f = Signal(9)
                    h = Signal(5)
                    m.d.comb += [
                        r.eq(self.inputa.as_signed() +
                             self.inputb.as_signed() + self.PSW.C),
                        f.eq(self.inputa + self.inputb + self.PSW.C),
                        h.eq(self.inputa[:4] + self.inputb[:4] + self.PSW.C),
                    ]
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r),
                            Assert(self.result == f[:8]),
                            Assert(self._psw.N == f[7]),
                            Assert(self._psw.V == (f[7] ^ f[8])),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == h[4]),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(f[:8].bool())),
                            Assert(self._psw.C == f[8]),
                        ]

            with m.Case(Operation.SBC):
                low = Cat(self.result[:4], self._psw.H)
                high = Cat(self.result[4:], self._psw.C)

                m.d.comb += [
                    low.eq(self.inputa[:4] - self.inputb[:4] - self.PSW.C),
                    high.eq(self.inputa[4:] - self.inputb[4:] - self._psw.H),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                    self._psw.V.eq(self.result[7] != self._psw.C),
                ]
                if self.verification is Operation.SBC:
                    r = Signal(8)
                    f = Signal(9)
                    h = Signal(5)
                    m.d.comb += [
                        r.eq(self.inputa.as_signed() -
                             self.inputb.as_signed() - self.PSW.C),
                        f.eq(self.inputa - self.inputb - self.PSW.C),
                        h.eq(self.inputa[:4] - self.inputb[:4] - self.PSW.C),
                    ]
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r),
                            Assert(self.result == f[:8]),
                            Assert(self._psw.N == f[7]),
                            Assert(self._psw.V == (f[7] ^ f[8])),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == h[4]),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(f[:8].bool())),
                            Assert(self._psw.C == f[8]),
                        ]

            with m.Case(Operation.CMP):
                full = Cat(self.result, self._psw.C)

                m.d.comb += [
                    full.eq(self.inputa.as_signed() - self.inputb.as_signed()),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                    self._psw.V.eq(self.result[7] != self._psw.C),
                ]
                if self.verification is Operation.CMP:
                    r = Signal(9)
                    m.d.comb += r.eq(self.inputa.as_signed() -
                                     self.inputb.as_signed())
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r[:8]),
                            Assert(self._psw.N == r[7]),
                            Assert(self._psw.V == (r[7] ^ r[8])),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(r[:8].bool())),
                            Assert(self._psw.C == r[8]),
                        ]

            with m.Case(Operation.AND):
                m.d.comb += [
                    self.result.eq(self.inputa & self.inputb),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                ]
                if self.verification is Operation.AND:
                    r = Signal(8)
                    m.d.comb += r.eq(self.inputa & self.inputb)
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r),
                            Assert(self._psw.N == r[7]),
                            Assert(self._psw.V == self.PSW.V),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(r.bool())),
                            Assert(self._psw.C == self.PSW.C),
                        ]

            with m.Case(Operation.OOR):
                m.d.comb += [
                    self.result.eq(self.inputa | self.inputb),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                ]
                if self.verification is Operation.OOR:
                    r = Signal(8)
                    m.d.comb += [
                        r.eq(self.inputa | self.inputb),
                    ]
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r),
                            Assert(self._psw.N == r[7]),
                            Assert(self._psw.V == self.PSW.V),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(r.bool())),
                            Assert(self._psw.C == self.PSW.C),
                        ]

            with m.Case(Operation.EOR):
                m.d.comb += [
                    self.result.eq(self.inputa ^ self.inputb),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                ]
                if self.verification is Operation.EOR:
                    r = Signal(8)
                    m.d.comb += [
                        r.eq(self.inputa ^ self.inputb),
                    ]
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r),
                            Assert(self._psw.N == r[7]),
                            Assert(self._psw.V == self.PSW.V),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(r.bool())),
                            Assert(self._psw.C == self.PSW.C),
                        ]

            with m.Case(Operation.INC):
                m.d.comb += [
                    self.result.eq(self.inputa + 1),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                ]
                if self.verification is Operation.INC:
                    r = Signal(8)
                    m.d.comb += [
                        r.eq(self.inputa + 1),
                    ]
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r),
                            Assert(self._psw.N == r[7]),
                            Assert(self._psw.V == self.PSW.V),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(r.bool())),
                            Assert(self._psw.C == self.PSW.C),
                        ]

            with m.Case(Operation.DEC):
                m.d.comb += [
                    self.result.eq(self.inputa - 1),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                ]
                if self.verification is Operation.DEC:
                    r = Signal(8)
                    m.d.comb += [
                        r.eq(self.inputa - 1),
                    ]
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r),
                            Assert(self._psw.N == r[7]),
                            Assert(self._psw.V == self.PSW.V),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(r.bool())),
                            Assert(self._psw.C == self.PSW.C),
                        ]

            with m.Case(Operation.ASL):
                m.d.comb += [
                    Cat(self.result,
                        self._psw.C).eq(Cat(Const(0), self.inputa)),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                ]
                if self.verification is Operation.ASL:
                    r = Signal(8)
                    m.d.comb += [
                        r.eq(self.inputa * 2),
                    ]
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r),
                            Assert(self._psw.N == self.inputa[6]),
                            Assert(self._psw.V == self.PSW.V),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(r.bool())),
                            Assert(self._psw.C == self.inputa[7]),
                        ]

            with m.Case(Operation.LSR):
                m.d.comb += [
                    Cat(self._psw.C,
                        self.result).eq(Cat(self.inputa, Const(0))),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                ]
                if self.verification is Operation.LSR:
                    r = Signal(8)
                    m.d.comb += [
                        r.eq(self.inputa // 2),
                    ]
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r),
                            Assert(self._psw.N == 0),
                            Assert(self._psw.V == self.PSW.V),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(r.bool())),
                            Assert(self._psw.C == self.inputa[0]),
                        ]

            with m.Case(Operation.ROL):
                m.d.comb += [
                    Cat(self.result,
                        self._psw.C).eq(Cat(self.PSW.C, self.inputa)),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                ]
                if self.verification is Operation.ROL:
                    r = Signal(8)
                    m.d.comb += [
                        r.eq(self.inputa * 2 + self.PSW.C),
                    ]
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r),
                            Assert(self._psw.N == self.inputa[6]),
                            Assert(self._psw.V == self.PSW.V),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(r.bool())),
                            Assert(self._psw.C == self.inputa[7]),
                        ]

            with m.Case(Operation.ROR):
                m.d.comb += [
                    Cat(self._psw.C,
                        self.result).eq(Cat(self.inputa, self.PSW.C)),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                ]
                if self.verification is Operation.ROR:
                    r = Signal(8)
                    m.d.comb += [
                        r.eq(self.inputa // 2 + Cat(Signal(7), self.PSW.C)),
                    ]
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r),
                            Assert(self._psw.N == self.PSW.C),
                            Assert(self._psw.V == self.PSW.V),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(r.bool())),
                            Assert(self._psw.C == self.inputa[0]),
                        ]

            with m.Case(Operation.XCN):
                m.d.comb += [
                    self.result.eq(Cat(self.inputa[4:], self.inputa[:4])),
                    self._psw.N.eq(self.result.as_signed() < 0),
                    self._psw.Z.eq(self.result == 0),
                ]
                if self.verification is Operation.XCN:
                    r = Signal(8)
                    m.d.comb += [
                        r.eq(self.inputa * 16 + self.inputa // 16),
                    ]
                    with m.If(~Initial()):
                        m.d.comb += [
                            Assert(self.result == r),
                            Assert(self._psw.N == self.inputa[3]),
                            Assert(self._psw.V == self.PSW.V),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(self.inputa.bool())),
                            Assert(self._psw.C == self.PSW.C),
                        ]

            with m.Case(Operation.DAA):
                temp = Signal().like(self.inputa)
                with m.If(self.PSW.C | (self.inputa > 0x99)):
                    m.d.comb += self._psw.C.eq(1)
                    m.d.comb += temp.eq(self.inputa + 0x60)
                with m.Else():
                    m.d.comb += temp.eq(self.inputa)

                with m.If(self.PSW.H | (temp[:4] > 0x09)):
                    m.d.comb += self.result.eq(temp + 0x06)

                m.d.comb += [
                    self._psw.N.eq(self.result & 0x80),
                    self._psw.Z.eq(self.result == 0),
                ]
                if self.verification is Operation.DAA:
                    with m.If(~Initial()):
                        m.d.comb += [Assert(False)]

            with m.Case(Operation.DAS):
                temp = Signal().like(self.inputa)
                with m.If(~self.PSW.C | (self.inputa > 0x99)):
                    m.d.comb += self._psw.C.eq(0)
                    m.d.comb += temp.eq(self.inputa - 0x60)
                with m.Else():
                    m.d.comb += temp.eq(self.inputa)

                with m.If(~self.PSW.H | (temp[:4] > 0x09)):
                    m.d.comb += self.result.eq(temp - 0x06)

                m.d.comb += [
                    self._psw.N.eq(self.result & 0x80),
                    self._psw.Z.eq(self.result == 0),
                ]
                if self.verification is Operation.DAS:
                    with m.If(~Initial()):
                        m.d.comb += [Assert(False)]

            # could be optimized with shift to right
            with m.Case(Operation.MUL):
                with m.Switch(self.count):
                    for i in range(0, 8):
                        with m.Case(i):
                            prod = self.inputa * self.inputb[i]
                            if i == 0:
                                prod = Cat(prod[0:7], ~prod[7], Const(1))
                            elif i == 7:
                                prod = Cat(~prod[0:7], prod[7], Const(1))
                            else:
                                prod = Cat(prod[0:7], ~prod[7])
                            m.d.sync += self.partial.eq(self.partial +
                                                        (prod << i))
                            m.d.sync += self.count.eq(i + 1)
                    with m.Case(8):
                        m.d.sync += self.partial_hi.eq(self.partial_lo)
                        m.d.sync += self.count.eq(9)
                        m.d.comb += [
                            self.result.eq(self.partial_hi),
                            self._psw.N.eq(self.partial_hi.as_signed() < 0),
                            self._psw.Z.eq(self.partial_hi == 0),
                        ]
                    with m.Case(9):
                        m.d.sync += self.partial.eq(0)
                        m.d.sync += self.count.eq(0)
                        m.d.comb += [
                            self.result.eq(self.partial_hi),
                        ]
                if self.verification is Operation.MUL:
                    r = Signal(16)
                    m.d.comb += [
                        r.eq(self.inputa.as_signed() *
                             self.inputb.as_signed()),
                        Cover(self.count == 9),
                    ]
                    with m.If(self.count == 9):
                        m.d.comb += [
                            Assert(Past(self.result) == r[8:16]),
                            Assert(self.result == r[0:8]),
                            Assert(self._psw.N == r[15]),
                            Assert(self._psw.V == self.PSW.V),
                            Assert(self._psw.P == self.PSW.P),
                            Assert(self._psw.B == self.PSW.B),
                            Assert(self._psw.H == self.PSW.H),
                            Assert(self._psw.I == self.PSW.I),
                            Assert(self._psw.Z == ~(r[8:16].bool())),
                            Assert(self._psw.C == self.PSW.C),
                        ]
                    with m.If(~Initial() & (self.count == 0)):
                        m.d.comb += [
                            Assert(self.partial == 0),
                            Assert((Past(self.count) == 0)
                                   | (Past(self.count) == 9)),
                        ]
                    with m.If(~Initial() & (self.count != 0)):
                        m.d.comb += [
                            Assert(self.count == Past(self.count) + 1),
                            Assume(self.inputa == Past(self.inputa)),
                            Assume(self.inputb == Past(self.inputb)),
                        ]

            with m.Case(Operation.DIV):
                over = Signal(reset=0)
                with m.Switch(self.count):
                    with m.Case(0):
                        m.d.sync += self.partial_hi.eq(self.inputa)  # Y
                        m.d.sync += self.count.eq(1)

                    with m.Case(1):
                        m.d.sync += self.partial_lo.eq(self.inputa)  # A
                        m.d.sync += self.count.eq(2)
                        m.d.comb += self._psw.H.eq(
                            Mux(self.partial_hi[0:4] >= self.inputb[0:4], 1,
                                0))

                    for i in range(2, 11):
                        with m.Case(i):
                            tmp1_w = Cat(self.partial << 1, over)
                            tmp1_x = Signal(17)
                            tmp1_y = Signal(17)
                            tmp1_z = Signal(17)
                            tmp2 = self.inputb << 9

                            m.d.comb += tmp1_x.eq(tmp1_w)
                            with m.If(tmp1_w & 0x20000):
                                m.d.comb += tmp1_x.eq((tmp1_w & 0x1FFFF) | 1)

                            m.d.comb += tmp1_y.eq(tmp1_x)
                            with m.If(tmp1_x >= tmp2):
                                m.d.comb += tmp1_y.eq(tmp1_x ^ 1)

                            m.d.comb += tmp1_z.eq(tmp1_y)
                            with m.If(tmp1_y & 1):
                                m.d.comb += tmp1_z.eq((tmp1_y - tmp2)
                                                      & 0x1FFFF)

                            m.d.sync += Cat(self.partial, over).eq(tmp1_z)

                            m.d.sync += self.count.eq(i + 1)

                    with m.Case(11):
                        m.d.sync += self.count.eq(12)
                        m.d.comb += [
                            self.result.eq(
                                (Cat(self.partial, over) >> 9)),  # Y %
                        ]

                    with m.Case(12):
                        m.d.sync += self.partial.eq(0)
                        m.d.sync += over.eq(0)
                        m.d.sync += self.count.eq(0)
                        m.d.comb += [
                            self.result.eq(self.partial_lo),  # A /
                            self._psw.N.eq(self.partial_lo.as_signed() < 0),
                            self._psw.V.eq(over),
                            self._psw.Z.eq(self.partial_lo == 0),
                        ]

                if self.verification is Operation.DIV:
                    m.d.comb += [
                        Cover(self.count == 12),
                    ]
                    with m.If(self.count == 12):
                        m.d.comb += [Assert(False)]

        return m
Exemplo n.º 23
0
    def elaborate(self, platform):
        m = Module()

        # Collection that will store each of our descriptor-generation submodules.
        descriptor_generators = {}

        #
        # Figure out the maximum length we're willing to send.
        #
        length = Signal(16)

        # We'll never send more than our MaxPacketSize. This means that we'll want to send a maximum of
        # either our maximum packet length, or the amount of data we have remaining; whichever is less.
        #
        # Note that this doesn't take into account the length of the actual data to be sent; this is handled
        # in the stream generator.
        words_remaining = self.length - self.start_position
        with m.If(words_remaining <= self._max_packet_length):
            m.d.comb += length.eq(words_remaining)
        with m.Else():
            m.d.comb += length.eq(self._max_packet_length)


        #
        # Create our constant-stream generators for each of our descriptors.
        #
        for type_number, index, raw_descriptor in self._descriptors:

            # Create the generator...
            generator = USBDescriptorStreamGenerator(raw_descriptor)
            descriptor_generators[(type_number, index)] = generator

            m.d.comb += [
                generator.max_length     .eq(length),
                generator.start_position .eq(self.start_position)
            ]

            # ... and attach it to this module.
            m.submodules += generator


        #
        # Connect up each of our generators.
        #

        with m.Switch(self.value):

            # Generate a conditional interconnect for each of our items.
            for (type_number, index), generator in descriptor_generators.items():

                # If the value matches the given type number...
                with m.Case(type_number << 8 | index):

                    # ... connect the relevant generator to our output.
                    m.d.comb += generator.stream  .attach(self.tx)
                    m.d.usb += generator.start    .eq(self.start),

            # If none of our descriptors match, stall any request that comes in.
            with m.Case():
                m.d.comb += self.stall.eq(self.start)


        return m
Exemplo n.º 24
0
    def elaborate(self, platform):
        m = Module()

        # create the byte selector
        with m.Switch(self.x_funct3):
            with m.Case(Funct3.B):
                m.d.comb += self.x_byte_sel.eq(0b0001 << self.x_offset)
            with m.Case(Funct3.H):
                m.d.comb += self.x_byte_sel.eq(0b0011 << self.x_offset)
            with m.Case(Funct3.W):
                m.d.comb += self.x_byte_sel.eq(0b1111)

        # format output data
        with m.Switch(self.x_funct3):
            with m.Case(Funct3.B):
                m.d.comb += self.x_data_w.eq(Repl(self.x_store_data[:8], 4))
            with m.Case(Funct3.H):
                m.d.comb += self.x_data_w.eq(Repl(self.x_store_data[:16], 2))
            with m.Case(Funct3.W):
                m.d.comb += self.x_data_w.eq(self.x_store_data)

        # format input data
        _byte = Signal((8, True))
        _half = Signal((16, True))

        m.d.comb += [
            _byte.eq(self.m_data_r.word_select(self.m_offset, 8)),
            _half.eq(self.m_data_r.word_select(self.m_offset[1], 16)),
        ]

        with m.Switch(self.m_funct3):
            with m.Case(Funct3.B):
                m.d.comb += self.m_load_data.eq(_byte)
            with m.Case(Funct3.BU):
                m.d.comb += self.m_load_data.eq(Cat(_byte,
                                                    0))  # make sign bit = 0
            with m.Case(Funct3.H):
                m.d.comb += self.m_load_data.eq(_half)
            with m.Case(Funct3.HU):
                m.d.comb += self.m_load_data.eq(Cat(_half,
                                                    0))  # make sign bit = 0
            with m.Case(Funct3.W):
                m.d.comb += self.m_load_data.eq(self.m_data_r)

        # misalignment
        with m.Switch(self.x_funct3):
            with m.Case(Funct3.H, Funct3.HU):
                m.d.comb += self.x_misaligned.eq(self.x_offset[0])
            with m.Case(Funct3.W):
                m.d.comb += self.x_misaligned.eq(self.x_offset != 0)

        return m
Exemplo n.º 25
0
    def handle_load(self, m: Module):
        """Adds the LOAD logic to the given module.

        Note that byte loads are byte-aligned, half-word loads
        are 16-bit aligned, and word loads are 32-bit aligned.
        Attempting to load unaligned will lead to undefined
        behavior.

        Operation is to load 32 bits from a 32-bit aligned
        address, and then perform at most two shifts to get
        the desired behavior: a shift left to get the most
        significant byte into the leftmost position, then a
        shift right to zero or sign extend the value.

        For example, for loading a half-word starting at
        address A where A%4=0, we first load the full 32
        bits at that address, resulting in XYHL, where X and
        Y are unwanted and H and L are the half-word we want
        to load. Then we shift left by 16: HL00. And finally
        we shift right by 16, either signed or unsigned
        depending on whether we are doing an LH or an LHU:
        ssHL / 00HL.

        addr <- rs1 + imm
        rd <- data at addr, possibly sign-extended
        PC <- PC + 4

        If we let N be addr%4, then:

        instr   N   shift1  shift2
        --------------------------
        LB      0   SLL 24  SRA 24
        LB      1   SLL 16  SRA 24
        LB      2   SLL  8  SRA 24
        LB      3   SLL  0  SRA 24
        LBU     0   SLL 24  SRL 24
        LBU     1   SLL 16  SRL 24
        LBU     2   SLL  8  SRL 24
        LBU     3   SLL  0  SRL 24
        LH      0   SLL 16  SRA 16
        LH      2   SLL  0  SRA 16
        LHU     0   SLL 16  SRL 16
        LHU     2   SLL  0  SRL 16
        LW      0   SLL  0  SRA  0
        (all other N are misaligned accesses)

        Where there is an SLL 0, the machine cycle
        could be skipped, but in the interests of
        simpler logic, we will not do that.

        rs1     -> X
        imm     -> Y
        ALU ADD -> Z
        Z       -> memaddr
        ---------------------
        memdata -> X
        shamt1  -> Y
        ALU SLL -> Z
        Z       -> rd
        ---------------------
        rd          -> X
        shamt2      -> Y
        ALU SRA/SRL -> Z
        Z           -> rd
        PC + 4      -> PC
        PC + 4      -> memaddr
        """
        with m.If(self._instr_phase == 0):
            m.d.comb += [
                self.reg_to_x.eq(1),
                self._x_reg_select.eq(InstrReg.RS1),
                self.y_mux_select.eq(SeqMuxSelect.IMM),
                self.alu_op_to_z.eq(AluOp.ADD),
                self.memaddr_mux_select.eq(SeqMuxSelect.Z),
                self._next_instr_phase.eq(1),
            ]

        with m.Elif(self._instr_phase == 1):
            # Check for exception conditions first
            with m.If(
                    self._funct3.matches(MemAccessWidth.H, MemAccessWidth.HU)
                    & self.memaddr_2_lsb[0]):
                self.set_exception(m,
                                   ConstSelect.EXC_LOAD_ADDR_MISALIGN,
                                   mtval=SeqMuxSelect.MEMADDR)

            with m.Elif((self._funct3 == MemAccessWidth.W)
                        & (self.memaddr_2_lsb != 0)):
                self.set_exception(m,
                                   ConstSelect.EXC_LOAD_ADDR_MISALIGN,
                                   mtval=SeqMuxSelect.MEMADDR)

            with m.Elif(~self._funct3.matches(
                    MemAccessWidth.B, MemAccessWidth.BU, MemAccessWidth.H,
                    MemAccessWidth.HU, MemAccessWidth.W)):
                self.handle_illegal_instr(m)

            with m.Else():
                m.d.comb += [
                    self.mem_rd.eq(1),
                    self.x_mux_select.eq(SeqMuxSelect.MEMDATA_RD),
                    self.y_mux_select.eq(SeqMuxSelect.CONST),
                    self.alu_op_to_z.eq(AluOp.SLL),
                    self._z_reg_select.eq(InstrReg.RD),
                    self._next_instr_phase.eq(2),
                ]

                with m.Switch(self._funct3):

                    with m.Case(MemAccessWidth.B, MemAccessWidth.BU):
                        with m.Switch(self.memaddr_2_lsb):
                            with m.Case(0):
                                m.d.comb += self._const.eq(
                                    ConstSelect.SHAMT_24)
                            with m.Case(1):
                                m.d.comb += self._const.eq(
                                    ConstSelect.SHAMT_16)
                            with m.Case(2):
                                m.d.comb += self._const.eq(ConstSelect.SHAMT_8)
                            with m.Case(3):
                                m.d.comb += self._const.eq(ConstSelect.SHAMT_0)

                    with m.Case(MemAccessWidth.H, MemAccessWidth.HU):
                        with m.Switch(self.memaddr_2_lsb):
                            with m.Case(0):
                                m.d.comb += self._const.eq(
                                    ConstSelect.SHAMT_16)
                            with m.Case(2):
                                m.d.comb += self._const.eq(ConstSelect.SHAMT_0)

                    with m.Case(MemAccessWidth.W):
                        m.d.comb += self._const.eq(ConstSelect.SHAMT_0)

        with m.Else():
            m.d.comb += [
                self.reg_to_x.eq(1),
                self._x_reg_select.eq(InstrReg.RD),
                self.y_mux_select.eq(SeqMuxSelect.CONST),
                self._z_reg_select.eq(InstrReg.RD),
            ]

            with m.Switch(self._funct3):
                with m.Case(MemAccessWidth.B):
                    m.d.comb += [
                        self._const.eq(ConstSelect.SHAMT_24),
                        self.alu_op_to_z.eq(AluOp.SRA),
                    ]
                with m.Case(MemAccessWidth.BU):
                    m.d.comb += [
                        self._const.eq(ConstSelect.SHAMT_24),
                        self.alu_op_to_z.eq(AluOp.SRL),
                    ]
                with m.Case(MemAccessWidth.H):
                    m.d.comb += [
                        self._const.eq(ConstSelect.SHAMT_16),
                        self.alu_op_to_z.eq(AluOp.SRA),
                    ]
                with m.Case(MemAccessWidth.HU):
                    m.d.comb += [
                        self._const.eq(ConstSelect.SHAMT_16),
                        self.alu_op_to_z.eq(AluOp.SRL),
                    ]
                with m.Case(MemAccessWidth.W):
                    m.d.comb += [
                        self._const.eq(ConstSelect.SHAMT_0),
                        self.alu_op_to_z.eq(AluOp.SRL),
                    ]

            self.next_instr(m)
Exemplo n.º 26
0
    def elaborate(self, platform):
        m = Module()
        size = self.configuration.getOption('predictor', 'size')
        if size == 0 or (size & (size - 1)):
            raise ValueError(f'size must be a power of 2: {size}')

        _bits_index = log2_int(size)
        _bits_tag = 32 - _bits_index
        _btb_width = 1 + 32 + _bits_tag  # valid + data + tag
        _btb_depth = 1 << _bits_index

        _btb_layout = [('target', 32), ('tag', _bits_tag), ('valid', 1)]

        _pc_layout = [('index', _bits_index), ('tag', _bits_tag)]

        btb = Memory(width=_btb_width, depth=_btb_depth)
        btb_rp = btb.read_port()
        btb_wp = btb.write_port()

        bht = Memory(width=2, depth=_btb_depth)
        bht_rp = bht.read_port()
        bht_wp = bht.write_port()

        m.submodules += btb_rp, btb_wp
        m.submodules += bht_rp, bht_wp

        btb_r = Record(_btb_layout)
        a_pc = Record(_pc_layout)
        f_pc = Record(_pc_layout)
        m_pc = Record(_pc_layout)
        hit = Signal()
        pstate_next = Signal(2)

        m.d.comb += [
            btb_rp.addr.eq(Mux(self.a_stall, f_pc.index, a_pc.index)),
            bht_rp.addr.eq(Mux(self.a_stall, f_pc.index, a_pc.index)),
            btb_r.eq(btb_rp.data),
            #
            a_pc.eq(self.a_pc),
            f_pc.eq(self.f_pc),
            hit.eq(btb_r.valid & (btb_r.tag == f_pc.tag)),
            #
            self.f_prediction.eq(hit & bht_rp.data[1]),
            self.f_prediction_state.eq(bht_rp.data),
            self.f_prediction_pc.eq(btb_r.target)
        ]

        # update
        m.d.comb += [
            btb_wp.addr.eq(m_pc.index),
            btb_wp.data.eq(Cat(self.m_target_pc, m_pc.tag, 1)),
            btb_wp.en.eq(self.m_update),
            bht_wp.addr.eq(m_pc.index),
            bht_wp.data.eq(pstate_next),
            bht_wp.en.eq(self.m_update),
            m_pc.eq(self.m_pc),
            pstate_next.eq(0)
        ]

        with m.Switch(Cat(self.m_prediction_state, self.m_take_jmp_branch)):
            with m.Case(0b000, 0b001):
                m.d.comb += pstate_next.eq(0b00)
            with m.Case(0b010, 0b100):
                m.d.comb += pstate_next.eq(0b01)
            with m.Case(0b011, 0b101):
                m.d.comb += pstate_next.eq(0b10)
            with m.Case(0b110, 0b111):
                m.d.comb += pstate_next.eq(0b11)

        return m
Exemplo n.º 27
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        triggers      = [Record.like(self.tdata1.read) for _ in range(self.ntriggers)]
        triggers_data = [Record.like(self.tdata2.read) for _ in range(self.ntriggers)]

        for t in triggers:
            m.d.comb += t.type.eq(TriggerType.MATCH)  # support only address/data match

        # handle writes to tselect
        with m.If(self.tselect.we):
            with m.If(self.tselect.write < self.ntriggers):  # no more than ntriggers
                m.d.sync += self.tselect.read.eq(self.tselect.write)

        # select the trigger
        with m.Switch(self.tselect.read):
            for idx, (trigger, trigger_data) in enumerate(zip(triggers, triggers_data)):
                with m.Case(idx):
                    m.d.comb += [
                        self.tdata1.read.eq(trigger),      # trigger visible @tdata1
                        self.tdata2.read.eq(trigger_data)  # data visible @tdata2
                    ]
                    # handle writes to tdata1
                    with m.If(self.tdata1.we):
                        mcontrol = Record([('i', mcontrol_layout), ('o', mcontrol_layout)])
                        m.d.comb += [
                            mcontrol.i.eq(self.tdata1.write.data),  # casting
                            mcontrol.o.execute.eq(mcontrol.i.execute),
                            mcontrol.o.store.eq(mcontrol.i.store),
                            mcontrol.o.load.eq(mcontrol.i.load),
                            mcontrol.o.m.eq(mcontrol.i.m),
                            mcontrol.o.u.eq(mcontrol.i.u),
                            mcontrol.o.action.eq(mcontrol.i.action)
                        ]
                        m.d.sync += [
                            trigger.dmode.eq(self.tdata1.write.dmode),
                            trigger.data.eq(mcontrol.o)
                        ]
                    # handle writes to tdata2
                    with m.If(self.tdata2.we):
                        m.d.sync += trigger_data.data.eq(self.tdata2.write)

        # trigger logic
        hit    = Signal()
        halt   = Signal()
        hit_v  = Signal(self.ntriggers)
        halt_v = Signal(self.ntriggers)

        for idx, (trigger, trigger_data) in enumerate(zip(triggers, triggers_data)):
            with m.Switch(trigger.type):
                with m.Case(TriggerType.MATCH):
                    match    = Signal()
                    mcontrol = Record(mcontrol_layout)
                    m.d.comb += mcontrol.eq(trigger)  # casting, lol

                    with m.If(mcontrol.execute):
                        m.d.comb += match.eq(self.x_valid & (trigger_data == self.x_pc))
                    with m.Elif(mcontrol.store):
                        m.d.comb += match.eq(self.x_valid & self.x_store & (trigger_data == self.x_bus_addr))
                    with m.Elif(mcontrol.load):
                        m.d.comb += match.eq(self.x_valid & self.x_load & (trigger_data == self.x_bus_addr))

                    if self.enable_user_mode:
                        # check the current priv mode, and check the priv enable mode
                        priv_m = self.privmode == PrivMode.Machine
                        priv_u = self.privmode == PrivMode.User
                        hit_tmp = match & ((mcontrol.m & priv_m) | (mcontrol.u & priv_u))
                    else:
                        hit_tmp = match & mcontrol.m

                    m.d.comb += [
                        hit_v[idx].eq(hit_tmp),
                        halt_v[idx].eq(mcontrol.action)
                    ]

        # request signals: halt/exception
        m.d.comb += [
            hit.eq(reduce(or_, hit_v, 0)),
            halt.eq(reduce(or_, halt_v, 0))
        ]
        with m.If(hit):
            with m.If(halt):  # halt = mcontrol.action
                m.d.comb += self.haltreq.eq(self.tdata1.read.dmode)  # enter debug mode only if dmode = 1
            with m.Else():
                m.d.comb += self.trap.eq(1)  # generate exception

        return m
Exemplo n.º 28
0
    m.submodules.alu = alu = ALU8()
    m.domains.ph1 = ph1 = ClockDomain("ph1")

    rst = Signal()
    ph1clk = ClockSignal("ph1")
    ph1.rst = rst

    carry_in = Signal()
    sum9 = Signal(9)
    sum8 = Signal(8)
    sum5 = Signal(5)

    m.d.comb += Assert(alu._ccs[6:] == 0b11)

    with m.Switch(alu.func):
        with m.Case(ALU8Func.ADD, ALU8Func.ADC):
            # sumN = input1[:N] + input2[:N] (so sumN[N-1] is the carry bit)
            with m.If(alu.func == ALU8Func.ADD):
                m.d.comb += carry_in.eq(0)
            with m.Else():
                m.d.comb += carry_in.eq(alu.ccs[_C])
            h = sum5[4]
            n = sum9[7]
            c = sum9[8]
            z = (sum9[:8] == 0)
            v = (sum8[7] ^ c)
            m.d.comb += [
                sum9.eq(alu.input1 + alu.input2 + carry_in),
                sum8.eq(alu.input1[:7] + alu.input2[:7] + carry_in),
                sum5.eq(alu.input1[:4] + alu.input2[:4] + carry_in),
                Assert(alu.output == sum9[:8]),
Exemplo n.º 29
0
        main_runner(parser, args, m, ports=core.ports() + [ph1clk, rst])

    else:
        # Fake memory
        mem = {
            0xFFFE: 0x12,
            0xFFFF: 0x34,
            0x1234: 0x7E,  # JMP 0xA010
            0x1235: 0xA0,
            0x1236: 0x10,
            0xA010: 0x01,  # NOP
        }
        with m.Switch(core.Addr):
            for addr, data in mem.items():
                with m.Case(addr):
                    m.d.comb += core.Din.eq(data)
            with m.Default():
                m.d.comb += core.Din.eq(0xFF)

        sim = Simulator(m)
        sim.add_clock(1e-6, domain="ph1")

        def process():
            yield
            yield
            yield
            yield
            yield
            yield
            yield
Exemplo n.º 30
0
    def encode_opcode_select(self, m: Module):
        m.d.comb += self.opcode_select.eq(OpcodeSelect.NONE)
        m.d.comb += self._imm_format.eq(OpcodeFormat.R)

        with m.Switch(self._opcode):
            with m.Case(Opcode.LUI):
                m.d.comb += self.opcode_select.eq(OpcodeSelect.LUI)
                m.d.comb += self._imm_format.eq(OpcodeFormat.U)

            with m.Case(Opcode.AUIPC):
                m.d.comb += self.opcode_select.eq(OpcodeSelect.AUIPC)
                m.d.comb += self._imm_format.eq(OpcodeFormat.U)

            with m.Case(Opcode.OP_IMM):
                m.d.comb += self.opcode_select.eq(OpcodeSelect.OP_IMM)
                m.d.comb += self._imm_format.eq(OpcodeFormat.I)

            with m.Case(Opcode.OP):
                m.d.comb += self.opcode_select.eq(OpcodeSelect.OP)
                m.d.comb += self._imm_format.eq(OpcodeFormat.R)

            with m.Case(Opcode.JAL):
                m.d.comb += self.opcode_select.eq(OpcodeSelect.JAL)
                m.d.comb += self._imm_format.eq(OpcodeFormat.J)

            with m.Case(Opcode.JALR):
                m.d.comb += self.opcode_select.eq(OpcodeSelect.JALR)
                m.d.comb += self._imm_format.eq(OpcodeFormat.J)

            with m.Case(Opcode.BRANCH):
                m.d.comb += self.opcode_select.eq(OpcodeSelect.BRANCH)
                m.d.comb += self._imm_format.eq(OpcodeFormat.B)

            with m.Case(Opcode.LOAD):
                m.d.comb += self.opcode_select.eq(OpcodeSelect.LOAD)
                m.d.comb += self._imm_format.eq(OpcodeFormat.I)

            with m.Case(Opcode.STORE):
                m.d.comb += self.opcode_select.eq(OpcodeSelect.STORE)
                m.d.comb += self._imm_format.eq(OpcodeFormat.S)

            with m.Case(Opcode.SYSTEM):
                m.d.comb += self._imm_format.eq(OpcodeFormat.SYS)

                with m.If(self._funct3 == SystemFunc.PRIV):
                    with m.Switch(self.state._instr):
                        with m.Case(Instr.MRET):
                            m.d.comb += self.opcode_select.eq(
                                OpcodeSelect.MRET)
                        with m.Case(Instr.ECALL):
                            m.d.comb += self.opcode_select.eq(
                                OpcodeSelect.ECALL)
                        with m.Case(Instr.EBREAK):
                            m.d.comb += self.opcode_select.eq(
                                OpcodeSelect.EBREAK)
                with m.Else():
                    m.d.comb += self.opcode_select.eq(OpcodeSelect.CSRS)