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

        invalid_r = Signal()
        invalid_w = Signal()

        # do the read
        m.d.comb += invalid_r.eq(0)
        for rport in self._read_ports:
            with m.Switch(rport.addr):
                for addr, csr in self._csr_map.items():
                    with m.Case(addr):
                        m.d.comb += rport.data.eq(csr.read & csr.mask)
                with m.Default():
                    m.d.comb += invalid_r.eq(1)

        # do the write
        m.d.comb += invalid_r.eq(0)
        for wport in self._write_ports:
            with m.Switch(wport.addr):
                for addr, csr in self._csr_map.items():
                    with m.Case(addr):
                        m.d.comb += [
                            csr.we.eq(wport.en),
                            csr.write.eq(wport.data & csr.mask)
                        ]
                with m.Default():
                    m.d.comb += invalid_r.eq(1)

        m.d.comb += self.invalid.eq(invalid_r | invalid_w)
        return m
Exemplo n.º 2
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.º 3
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)
Exemplo n.º 4
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.º 5
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.º 6
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("01111110"):  # JMP ext
             self.JMPext(m)
         with m.Case("1-110110"):  # LDA ext
             self.ALUext(m, ALU8Func.LD)
         with m.Case("1-110000"):  # SUB ext
             self.ALUext(m, ALU8Func.SUB)
         with m.Case("1-110001"):  # CMP ext
             self.ALUext(m, ALU8Func.SUB, store=False)
         with m.Case("1-110010"):  # SBC ext
             self.ALUext(m, ALU8Func.SBC)
         with m.Case("1-110100"):  # AND ext
             self.ALUext(m, ALU8Func.AND)
         with m.Case("1-110101"):  # BIT ext
             self.ALUext(m, ALU8Func.AND, store=False)
         with m.Case("1-110111"):  # STA ext
             self.STAext(m)
         with m.Case("1-111000"):  # EOR ext
             self.ALUext(m, ALU8Func.EOR)
         with m.Case("1-111001"):  # ADC ext
             self.ALUext(m, ALU8Func.ADC)
         with m.Case("1-111010"):  # ORA ext
             self.ALUext(m, ALU8Func.ORA)
         with m.Case("1-111011"):  # ADD ext
             self.ALUext(m, ALU8Func.ADD)
         with m.Default():  # Illegal
             self.end_instr(m, self.pc)
Exemplo n.º 7
0
 def elaborate(self, p: Platform) -> Module:
     m = Module()
     comb = m.d.comb
     signed_lhs = as_signed(m, self.lhs)
     signed_rhs = as_signed(m, self.rhs)
     with m.If(self.en):
         if self.invalid_op is not None:
             comb += self.invalid_op.eq(0)
         with m.Switch(self.op):
             with m.Case(OpAlu.ADD):
                 comb += self.output.eq(self.lhs + self.rhs)
             with m.Case(OpAlu.SLT):
                 comb += self.output.eq(Mux(signed_lhs < signed_rhs, 1, 0))
             with m.Case(OpAlu.SLTU):
                 comb += self.output.eq(Mux(self.lhs < self.rhs, 1, 0))
             with m.Case(OpAlu.AND):
                 comb += self.output.eq(self.lhs & self.rhs)
             with m.Case(OpAlu.OR):
                 comb += self.output.eq(self.lhs | self.rhs)
             with m.Case(OpAlu.XOR):
                 comb += self.output.eq(self.lhs ^ self.rhs)
             with m.Default():
                 comb += self.output.eq(0)
                 if self.invalid_op is not None:
                     comb += self.invalid_op.eq(1)
     with m.Else():
         self.output.eq(0)
     return m
Exemplo n.º 8
0
	def execute(self, m: Module):
		with m.Switch(self.registers.instr):
			for key, instr in self.instruction_set.instructions.items():
				with m.Case(key):
					instr.implement(m, self)
			with m.Default():
				self.halt(m)
Exemplo n.º 9
0
    def check(self, m: Module, instr: Value, data: FormalData):
        m.d.comb += [
            Assert(data.post_a == data.pre_a),
            Assert(data.post_b == data.pre_b),
            Assert(data.post_x == data.pre_x),
            Assert(data.post_sp == data.pre_sp),
            Assert(data.addresses_written == 0),
            Assert(data.addresses_read == 0),
        ]
        m.d.comb += Assert(data.post_pc == data.plus16(data.pre_pc, 1))

        c = Signal()
        v = Signal()
        i = Signal()

        m.d.comb += c.eq(data.pre_ccs[Flags.C])
        m.d.comb += v.eq(data.pre_ccs[Flags.V])
        m.d.comb += i.eq(data.pre_ccs[Flags.I])

        with m.Switch(instr):
            with m.Case(CLV):
                m.d.comb += v.eq(0)
            with m.Case(SEV):
                m.d.comb += v.eq(1)
            with m.Case(CLC):
                m.d.comb += c.eq(0)
            with m.Case(SEC):
                m.d.comb += c.eq(1)
            with m.Case(CLI):
                m.d.comb += i.eq(0)
            with m.Case(SEI):
                m.d.comb += i.eq(1)

        self.assertFlags(m, data.post_ccs, data.pre_ccs, V=v, C=c, I=i)
Exemplo n.º 10
0
	def setup_src_bus(self, m: Module, reg_map: Dict[IntEnum, Register], bus: Signal, selector: Signal):
		with m.Switch(selector):
			for (e, reg) in reg_map.items():
				with m.Case(e):
					m.d.comb += bus.eq(reg.register)
			with m.Default():
				m.d.comb += bus.eq(0)
Exemplo n.º 11
0
Arquivo: acm.py Projeto: yhetti/luna
    def elaborate(self, platform):
        m = Module()

        interface = self.interface
        setup = self.interface.setup

        #
        # Class request handlers.
        #

        with m.If(setup.type == USBRequestType.CLASS):
            with m.Switch(setup.request):

                # SET_LINE_CODING: The host attempts to tell us how it wants serial data
                # encoding. Since we output a stream, we'll ignore the actual line coding.
                with m.Case(self.SET_LINE_CODING):

                    # Always ACK the data out...
                    with m.If(interface.rx_ready_for_response):
                        m.d.comb += interface.handshakes_out.ack.eq(1)

                    # ... and accept whatever the request was.
                    with m.If(interface.status_requested):
                        m.d.comb += self.send_zlp()

                with m.Case():

                    #
                    # Stall unhandled requests.
                    #
                    with m.If(interface.status_requested
                              | interface.data_requested):
                        m.d.comb += interface.handshakes_out.stall.eq(1)

                return m
Exemplo n.º 12
0
    def branch_check(self, m: Module) -> Signal:
        """Generates logic for a 1-bit value for branching.

        Returns a 1-bit Signal which is set if the branch should be
        taken. The branch logic is determined by the instruction.
        """
        invert = self.instr[0]
        cond = Signal()
        take_branch = Signal()

        with m.Switch(self.instr[1:4]):
            with m.Case("000"):  # BRA, BRN
                m.d.comb += cond.eq(1)
            with m.Case("001"):  # BHI, BLS
                m.d.comb += cond.eq(~(self.ccs[Flags.C] | self.ccs[Flags.Z]))
            with m.Case("010"):  # BCC, BCS
                m.d.comb += cond.eq(~self.ccs[Flags.C])
            with m.Case("011"):  # BNE, BEQ
                m.d.comb += cond.eq(~self.ccs[Flags.Z])
            with m.Case("100"):  # BVC, BVS
                m.d.comb += cond.eq(~self.ccs[Flags.V])
            with m.Case("101"):  # BPL, BMI
                m.d.comb += cond.eq(~self.ccs[Flags.N])
            with m.Case("110"):  # BGE, BLT
                m.d.comb += cond.eq(~(self.ccs[Flags.N] ^ self.ccs[Flags.V]))
            with m.Case("111"):  # BGT, BLE
                m.d.comb += cond.eq(~(self.ccs[Flags.Z] |
                                      (self.ccs[Flags.N] ^ self.ccs[Flags.V])))

        m.d.comb += take_branch.eq(cond ^ invert)
        return take_branch
Exemplo n.º 13
0
    def formal(cls) -> Tuple[Module, List[Signal]]:
        """Formal verification for the shifter."""
        m = Module()
        m.submodules.shifter = shifter = ShiftCard()

        shamt = Signal(5)
        m.d.comb += shamt.eq(shifter.data_y[:5])

        with m.If(shamt > 0):
            m.d.comb += Cover(shifter.data_z == 0xFFFFAAA0)

        with m.Switch(shifter.alu_op):
            with m.Case(AluOp.SLL):
                m.d.comb += Assert(
                    shifter.data_z == (shifter.data_x << shamt)[:32])

            with m.Case(AluOp.SRL):
                m.d.comb += Assert(shifter.data_z == (shifter.data_x >> shamt))

            with m.Case(AluOp.SRA):
                m.d.comb += Assert(
                    shifter.data_z == (shifter.data_x.as_signed() >> shamt))

            with m.Default():
                m.d.comb += Assert(shifter.data_z == 0)

        return m, [
            shifter.alu_op, shifter.data_x, shifter.data_y, shifter.data_z
        ]
Exemplo n.º 14
0
    def elaborate(self, _: Platform) -> Module:
        """Implements the logic of the buffer."""
        m = Module()

        # OE_I = 0000011 | 0001111 | 0010011
        # OE_S = 0100011
        # OE_U = 0010111 | 0110111
        # OE_B = 1100011
        # OE_J = 1100111 | 1101111
        # OE_SYS = 1110011

        m.d.comb += [
            self.i_n_oe.eq(1),
            self.s_n_oe.eq(1),
            self.u_n_oe.eq(1),
            self.b_n_oe.eq(1),
            self.j_n_oe.eq(1),
            self.sys_n_oe.eq(1),
        ]
        with m.Switch(self.opcode):
            with m.Case(0b0000011, 0b0001111, 0b0010011):  # I
                m.d.comb += self.i_n_oe.eq(0)
            with m.Case(0b0100011):  # S
                m.d.comb += self.s_n_oe.eq(0)
            with m.Case(0b0010111, 0b0110111):  # U
                m.d.comb += self.u_n_oe.eq(0)
            with m.Case(0b1100011):
                m.d.comb += self.b_n_oe.eq(0)
            with m.Case(0b1100111, 0b1101111):
                m.d.comb += self.j_n_oe.eq(0)
            with m.Default():
                m.d.comb += self.sys_n_oe.eq(0)
        return m
Exemplo n.º 15
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),
        ]        

        with m.Switch(self.i_y_coord & 3):
            with m.Case(0):
                self._dither(m, self.i_dm00, self.i_dm01, self.i_dm02, self.i_dm03)
            with m.Case(1):
                self._dither(m, self.i_dm10, self.i_dm11, self.i_dm12, self.i_dm13)
            with m.Case(2):
                self._dither(m, self.i_dm20, self.i_dm21, self.i_dm22, self.i_dm23)
            with m.Case(3):
                self._dither(m, self.i_dm30, self.i_dm31, self.i_dm32, self.i_dm33)

        return m
Exemplo n.º 16
0
    def check(self, m: Module):
        self.assert_cycles(m, 2)

        c = Signal()
        v = Signal()
        i = Signal()

        m.d.comb += c.eq(self.data.pre_ccs[Flags.C])
        m.d.comb += v.eq(self.data.pre_ccs[Flags.V])
        m.d.comb += i.eq(self.data.pre_ccs[Flags.I])

        with m.Switch(self.instr):
            with m.Case(CLV):
                m.d.comb += v.eq(0)
            with m.Case(SEV):
                m.d.comb += v.eq(1)
            with m.Case(CLC):
                m.d.comb += c.eq(0)
            with m.Case(SEC):
                m.d.comb += c.eq(1)
            with m.Case(CLI):
                m.d.comb += i.eq(0)
            with m.Case(SEI):
                m.d.comb += i.eq(1)

        self.assert_registers(m, PC=self.data.pre_pc + 1)
        self.assert_flags(m, V=v, C=c, I=i)
Exemplo n.º 17
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        invalid_undef = Signal()  # The register is not defined
        invalid_ro = Signal()  # The register is read-only.
        invalid_priv = Signal()  # The priviledge mode is incorrect.

        # ----------------------------------------------------------------------
        # access
        for idx, port in enumerate(self._ports):
            if idx == 0:
                # The first write port is for pipeline use, and is the only one that
                # can generate exceptions
                # Other write ports do not generate exceptions: for debug use, for example.

                # Priv mode must be greater or equal to the priv mode of the register.
                m.d.comb += [
                    invalid_ro.eq(port.addr[10:12] == 0b11),
                    invalid_priv.eq(port.addr[8:10] > self.privmode)
                ]

                with m.Switch(port.addr):
                    for addr, csr in self._csr_map.items():
                        with m.Case(addr):
                            m.d.comb += [
                                csr.we.eq(port.en
                                          & ~(invalid_ro | invalid_priv)),
                                port.data_r.eq(csr.read & csr.mask),
                                csr.write.eq(port.data_w & csr.mask)
                            ]
                    with m.Default():
                        m.d.comb += invalid_undef.eq(1)

                m.d.comb += self.invalid.eq(invalid_undef
                                            | (invalid_ro & port.en)
                                            | invalid_priv)
            else:
                with m.Switch(port.addr):
                    for addr, csr in self._csr_map.items():
                        with m.Case(addr):
                            m.d.comb += [
                                csr.we.eq(port.en),
                                port.data_r.eq(csr.read & csr.mask),
                                csr.write.eq(port.data_w & csr.mask)
                            ]

        return m
Exemplo n.º 18
0
    def decode_imm(self, m: Module):
        """Decodes the immediate value out of the instruction."""
        with m.Switch(self._imm_format):
            # Format I instructions. Surprisingly, SLTIU (Set if Less Than
            # Immediate Unsigned) actually does sign-extend the immediate
            # value, and then compare as if the sign-extended immediate value
            # were unsigned!
            with m.Case(OpcodeFormat.I):
                tmp = Signal(signed(12))
                m.d.comb += tmp.eq(self.state._instr[20:])
                m.d.comb += self._imm.eq(tmp)

            # Format S instructions:
            with m.Case(OpcodeFormat.S):
                tmp = Signal(signed(12))
                m.d.comb += tmp[0:5].eq(self.state._instr[7:12])
                m.d.comb += tmp[5:].eq(self.state._instr[25:])
                m.d.comb += self._imm.eq(tmp)

            # Format R instructions:
            with m.Case(OpcodeFormat.R):
                m.d.comb += self._imm.eq(0)

            # Format U instructions:
            with m.Case(OpcodeFormat.U):
                m.d.comb += self._imm.eq(0)
                m.d.comb += self._imm[12:].eq(self.state._instr[12:])

            # Format B instructions:
            with m.Case(OpcodeFormat.B):
                tmp = Signal(signed(13))
                m.d.comb += [
                    tmp[12].eq(self.state._instr[31]),
                    tmp[11].eq(self.state._instr[7]),
                    tmp[5:11].eq(self.state._instr[25:31]),
                    tmp[1:5].eq(self.state._instr[8:12]),
                    tmp[0].eq(0),
                    self._imm.eq(tmp),
                ]

            # Format J instructions:
            with m.Case(OpcodeFormat.J):
                tmp = Signal(signed(21))
                m.d.comb += [
                    tmp[20].eq(self.state._instr[31]),
                    tmp[12:20].eq(self.state._instr[12:20]),
                    tmp[11].eq(self.state._instr[20]),
                    tmp[1:11].eq(self.state._instr[21:31]),
                    tmp[0].eq(0),
                    self._imm.eq(tmp),
                ]

            with m.Case(OpcodeFormat.SYS):
                m.d.comb += [
                    self._imm[0:5].eq(self.state._instr[15:]),
                    self._imm[5:].eq(0),
                ]
Exemplo n.º 19
0
 def src_bus_setup(self, m: Module, reg_map: Dict[IntEnum, Tuple[Signal,
                                                                 bool]],
                   bus: Signal, selector: Signal):
     with m.Switch(selector):
         for e, reg in reg_map.items():
             with m.Case(e):
                 m.d.comb += bus.eq(reg[0])
         with m.Default():
             m.d.comb += bus.eq(0)
Exemplo n.º 20
0
    def formal(cls) -> Tuple[Module, List[Signal]]:
        """Formal verification for the ALU."""
        m = Module()
        m.submodules.alu = alu = AluCard()

        with m.Switch(alu.alu_op):
            with m.Case(AluOp.ADD):
                m.d.comb += Assert(alu.data_z == (alu.data_x +
                                                  alu.data_y)[:32])

            with m.Case(AluOp.SUB):
                m.d.comb += [
                    Assert(alu.data_z == (alu.data_x - alu.data_y)[:32]),
                    Assert(alu.alu_eq == (alu.data_x == alu.data_y)),
                    Assert(alu.alu_ltu == (alu.data_x < alu.data_y)),
                    Assert(alu.alu_lt == (
                        alu.data_x.as_signed() < alu.data_y.as_signed())),
                ]

            with m.Case(AluOp.AND):
                m.d.comb += Assert(alu.data_z == (alu.data_x & alu.data_y))

            with m.Case(AluOp.AND_NOT):
                m.d.comb += Assert(alu.data_z == (alu.data_x & ~alu.data_y))

            with m.Case(AluOp.OR):
                m.d.comb += Assert(alu.data_z == (alu.data_x | alu.data_y))

            with m.Case(AluOp.XOR):
                m.d.comb += Assert(alu.data_z == (alu.data_x ^ alu.data_y))

            with m.Case(AluOp.SLTU):
                with m.If(alu.data_x < alu.data_y):
                    m.d.comb += Assert(alu.data_z == 1)
                with m.Else():
                    m.d.comb += Assert(alu.data_z == 0)

            with m.Case(AluOp.SLT):
                with m.If(alu.data_x.as_signed() < alu.data_y.as_signed()):
                    m.d.comb += Assert(alu.data_z == 1)
                with m.Else():
                    m.d.comb += Assert(alu.data_z == 0)

            with m.Case(AluOp.X):
                m.d.comb += Assert(alu.data_z == alu.data_x)

            with m.Case(AluOp.Y):
                m.d.comb += Assert(alu.data_z == alu.data_y)

            with m.Default():
                m.d.comb += Assert(alu.data_z == 0)

        return m, [alu.alu_op, alu.data_x, alu.data_y, alu.data_z]
Exemplo n.º 21
0
Arquivo: bus.py Projeto: zyp/luna
    def elaborate(self, platform):
        m = Module()

        #
        # Our module has three core parts:
        #   - an encoder, which converts from our one-hot signal to a mux select line
        #   - a multiplexer, which handles multiplexing e.g. payload signals
        #   - a set of OR'ing logic, which joints together our simple or'd signals

        # Create our encoder...
        m.submodules.encoder = encoder = Encoder(len(self._inputs))
        for index, interface in enumerate(self._inputs):

            # ... and tie its inputs to each of our 'valid' signals.
            valid_signal = getattr(interface, self._valid_field)
            m.d.comb += encoder.i[index].eq(valid_signal)

        # Create our multiplexer, and drive each of our output signals from it.
        with m.Switch(encoder.o):
            for index, interface in enumerate(self._inputs):

                # If an interface is selected...
                with m.Case(index):
                    for identifier in self._mux_signals:

                        # ... connect all of its muxed signals through to the output.
                        output_signal = self._get_signal(
                            self.output, identifier)
                        input_signal = self._get_signal(interface, identifier)
                        m.d.comb += output_signal.eq(input_signal)

        # Create the OR'ing logic for each of or or_signals.
        for identifier in self._or_signals:

            # Figure out the signals we want to work with...
            output_signal = self._get_signal(self.output, identifier)
            input_signals = (self._get_signal(i, identifier)
                             for i in self._inputs)

            # ... and OR them together.
            or_reduced = functools.reduce(operator.__or__, input_signals, 0)
            m.d.comb += output_signal.eq(or_reduced)

        # Finally, pass each of our pass-back signals from the output interface
        # back to each of our input interfaces.
        for identifier in self._pass_signals:
            output_signal = self._get_signal(self.output, identifier)

            for interface in self._inputs:
                input_signal = self._get_signal(interface, identifier)
                m.d.comb += input_signal.eq(output_signal)

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

        with m.Switch(self.op):
            with m.Case(Funct3.XOR):
                m.d.comb += self.result.eq(self.dat1 ^ self.dat2)
            with m.Case(Funct3.OR):
                m.d.comb += self.result.eq(self.dat1 | self.dat2)
            with m.Case(Funct3.AND):
                m.d.comb += self.result.eq(self.dat1 & self.dat2)
            with m.Default():
                m.d.comb += self.result.eq(0)

        return m
Exemplo n.º 23
0
    def handle_op(self, m: Module):
        """Adds the OP logic to the given module.

        rd <- rs1 op rs2
        PC <- PC + 4

        rs1     -> X
        rs2     -> Y
        ALU op  -> Z
        Z       -> rd
        PC + 4  -> PC
        PC + 4  -> memaddr
        """
        with m.If(~self._alu_func.matches(
                AluFunc.ADD, AluFunc.SUB, AluFunc.SLL, AluFunc.SLT,
                AluFunc.SLTU, AluFunc.XOR, AluFunc.SRL, AluFunc.SRA,
                AluFunc.OR, AluFunc.AND)):
            self.handle_illegal_instr(m)
        with m.Else():
            m.d.comb += [
                self.reg_to_x.eq(1),
                self._x_reg_select.eq(InstrReg.RS1),
                self.reg_to_y.eq(1),
                self._y_reg_select.eq(InstrReg.RS2),
                self._z_reg_select.eq(InstrReg.RD),
            ]
            with m.Switch(self._alu_func):
                with m.Case(AluFunc.ADD):
                    m.d.comb += self.alu_op_to_z.eq(AluOp.ADD)
                with m.Case(AluFunc.SUB):
                    m.d.comb += self.alu_op_to_z.eq(AluOp.SUB)
                with m.Case(AluFunc.SLL):
                    m.d.comb += self.alu_op_to_z.eq(AluOp.SLL)
                with m.Case(AluFunc.SLT):
                    m.d.comb += self.alu_op_to_z.eq(AluOp.SLT)
                with m.Case(AluFunc.SLTU):
                    m.d.comb += self.alu_op_to_z.eq(AluOp.SLTU)
                with m.Case(AluFunc.XOR):
                    m.d.comb += self.alu_op_to_z.eq(AluOp.XOR)
                with m.Case(AluFunc.SRL):
                    m.d.comb += self.alu_op_to_z.eq(AluOp.SRL)
                with m.Case(AluFunc.SRA):
                    m.d.comb += self.alu_op_to_z.eq(AluOp.SRA)
                with m.Case(AluFunc.OR):
                    m.d.comb += self.alu_op_to_z.eq(AluOp.OR)
                with m.Case(AluFunc.AND):
                    m.d.comb += self.alu_op_to_z.eq(AluOp.AND)
            self.next_instr(m)
Exemplo n.º 24
0
 def make_fakemem(self, m: Module, mem: Dict[int, int]):
     comb: List[Statement] = m.d.comb
     with m.If(self.mem2core.en):
         with m.Switch(self.mem2core.addr):
             for address, value in mem.items():
                 with m.Case(address):
                     word_value = value | (
                         mem.get(address + 1, 0xff) << 8) | (
                             mem.get(address + 2, 0xff) << 16) | (
                                 mem.get(address + 3, 0xff) << 24)
                     comb += self.mem2core.value.eq(word_value)
             with m.Default():
                 comb += self.mem2core.value.eq(0xFFFFFFFF)
         comb += self.mem2core.ready.eq(1)
     with m.Else():
         comb += self.mem2core.ready.eq(1)
Exemplo n.º 25
0
	def setup(self, m: Module):
		with m.Switch(self.reset_state):
			with m.Case(0):
				m.d.ph1 += self.core.Addr.eq(0xFFFE)
				m.d.ph1 += self.core.RW.eq(1)
				m.d.ph1 += self.reset_state.eq(1)
			with m.Case(1):
				m.d.ph1 += self.core.Addr.eq(0xFFFF)
				m.d.ph1 += self.core.RW.eq(1)
				m.d.ph1 += self.core.registers.tmp8.eq(self.core.Din)
				m.d.ph1 += self.reset_state.eq(2)
			with m.Case(2):
				m.d.ph1 += self.reset_state.eq(3)
				reset_vec = Cat(self.core.Din, self.core.registers.tmp8)
				m.d.ph1 += self.core.registers.ccr.eq((1 << Ccr.RUN) | (1 << Ccr.RUN_2))
				self.core.next(m, reset_vec)
Exemplo n.º 26
0
 def reset_handler(self, m: Module):
     """Generates logic for reading the reset vector at 0xFFFE
     and jumping there."""
     with m.Switch(self.reset_state):
         with m.Case(0):
             m.d.ph1 += self.Addr.eq(0xFFFE)
             m.d.ph1 += self.RW.eq(1)
             m.d.ph1 += self.reset_state.eq(1)
         with m.Case(1):
             m.d.ph1 += self.Addr.eq(0xFFFF)
             m.d.ph1 += self.RW.eq(1)
             m.d.ph1 += self.tmp8.eq(self.Din)
             m.d.ph1 += self.reset_state.eq(2)
         with m.Case(2):
             m.d.ph1 += self.reset_state.eq(3)
             reset_vec = Cat(self.Din, self.tmp8)
             self.end_instr(m, reset_vec)
Exemplo n.º 27
0
    def elaborate(self, platform):
        m = Module()

        interface         = self.interface
        setup             = self.interface.setup

        # Grab a reference to the board's LEDs.
        leds  = Cat(platform.request("led", i) for i in range(6))

        #
        # Vendor request handlers.
        #
        with m.If(setup.type == USBRequestType.VENDOR):
            with m.Switch(setup.request):

                # SET_LEDS request handler: handler that sets the board's LEDS
                # to a user provided value
                with m.Case(self.REQUEST_SET_LEDS):

                    # If we have an active data byte, splat it onto the LEDs.
                    #
                    # For simplicity of this example, we'll accept any byte in
                    # the packet; and not just the first one; each byte will
                    # cause an update. This is fun; we can PWM the LEDs with
                    # USB packets. :)
                    with m.If(interface.rx.valid & interface.rx.next):
                        m.d.usb += leds.eq(interface.rx.payload)

                    # Once the receive is complete, respond with an ACK.
                    with m.If(interface.rx_ready_for_response):
                        m.d.comb += interface.handshakes_out.ack.eq(1)

                    # If we reach the status stage, send a ZLP.
                    with m.If(interface.status_requested):
                        m.d.comb += self.send_zlp()


                with m.Case():

                    #
                    # Stall unhandled requests.
                    #
                    with m.If(interface.status_requested | interface.data_requested):
                        m.d.comb += interface.handshakes_out.stall.eq(1)

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

        m.submodules.alu = self.alu = ALU()

        """Fetch the opcode, common for all instr"""
        m.d.sync += self.opcode.eq(Mux(self.cycle == 1, self.dout, self.opcode))

        with m.Switch(Mux(self.cycle == 1, self.dout, self.opcode)):
            for i in implemented.implemented:
                with m.Case(i.opcode):
                    i.synth(self, m)
            with m.Default():
                m.d.comb += core.alu.oper.eq(Operation.NOP)
                m.d.sync += [
                    core.reg.PC.eq(add16(core.reg.PC, 1)),
                    core.enable.eq(1),
                    core.addr.eq(add16(core.reg.PC, 1)),
                    core.RWB.eq(1),
                    core.cycle.eq(1),
                ]

        if self.verification is not None:
            self.verify(m)

            with m.If(Initial()):
                m.d.sync += [
                    self.reg.A.eq(AnyConst(8)),
                    self.reg.X.eq(AnyConst(8)),
                    self.reg.Y.eq(AnyConst(8)),
                    self.reg.SP.eq(AnyConst(16)),
                    self.reg.PC.eq(AnyConst(16)),
                ]
                m.d.sync += [
                    self.reg.PSW.N.eq(AnyConst(1)),
                    self.reg.PSW.V.eq(AnyConst(1)),
                    self.reg.PSW.P.eq(AnyConst(1)),
                    self.reg.PSW.B.eq(AnyConst(1)),
                    self.reg.PSW.H.eq(AnyConst(1)),
                    self.reg.PSW.I.eq(AnyConst(1)),
                    self.reg.PSW.Z.eq(AnyConst(1)),
                    self.reg.PSW.C.eq(AnyConst(1)),
                ]

        return m
Exemplo n.º 29
0
    def elaborate(self, _: Platform) -> Module:
        """Implements the logic for the NextDay module."""
        m = Module()

        is_leap_year = Signal()
        max_day = Signal.like(self.day)

        m.d.comb += is_leap_year.eq(0)  # We can override this below!
        with m.If((self.year % 4) == 0):
            m.d.comb += is_leap_year.eq(1)
            with m.If((self.year % 100) == 0):
                m.d.comb += is_leap_year.eq(0)
                with m.If((self.year % 400) == 0):
                    m.d.comb += is_leap_year.eq(1)

        with m.Switch(self.month):
            with m.Case(1, 3, 5, 7, 8, 10, 12):
                m.d.comb += max_day.eq(31)
            with m.Case(2):
                m.d.comb += max_day.eq(28 + is_leap_year)
            with m.Default():
                m.d.comb += max_day.eq(30)

        m.d.comb += self.next_year.eq(self.year)
        m.d.comb += self.next_month.eq(self.month)
        m.d.comb += self.next_day.eq(self.day + 1)

        with m.If(self.day == max_day):
            m.d.comb += self.next_day.eq(1)
            m.d.comb += self.next_month.eq(self.month + 1)
            with m.If(self.month == 12):
                m.d.comb += self.next_month.eq(1)
                m.d.comb += self.next_year.eq(self.year + 1)

        m.d.comb += self.invalid.eq(0)
        with m.If((self.day < 1) | (self.day > max_day) | (self.month < 1)
                  | (self.month > 12) | (self.year < 1) | (self.year > 9999)):
            m.d.comb += self.invalid.eq(1)

        with m.If(self.invalid):
            m.d.comb += self.next_year.eq(0)
            m.d.comb += self.next_month.eq(0)
            m.d.comb += self.next_day.eq(0)

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

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

        #
        # 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

            # ... 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),
                        generator.start.eq(self.start),
                        generator.max_length.eq(self.length)
                    ]

            # 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