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 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.º 3
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.º 4
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.º 5
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.º 6
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.º 7
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.º 8
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.º 9
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.º 10
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.º 11
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.º 12
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.º 13
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.º 14
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.º 15
0
    def elaborate(self, platform):
        m = Module()

        with m.Switch(self.op):
            with m.Case(Funct3.BEQ):
                m.d.comb += self.cmp_ok.eq(self.zero)
            with m.Case(Funct3.BNE):
                m.d.comb += self.cmp_ok.eq(~self.zero)
            with m.Case(Funct3.BLT, Funct3.SLT):
                m.d.comb += self.cmp_ok.eq(~self.zero
                                           & (self.negative != self.overflow))
            with m.Case(Funct3.BLTU, Funct3.SLTU):
                m.d.comb += self.cmp_ok.eq(~self.zero & self.carry)
            with m.Case(Funct3.BGE):
                m.d.comb += self.cmp_ok.eq(self.negative == self.overflow)
            with m.Case(Funct3.BGEU):
                m.d.comb += self.cmp_ok.eq(~self.carry)
            with m.Default():
                m.d.comb += self.cmp_ok.eq(0)

        return m
Exemplo n.º 16
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.º 17
0
    def handle_csrs(self, m: Module):
        """Adds the SYSTEM (CSR opcodes) logic to the given module.

        Some points of interest:

        * Attempts to write a read-only register
          result in an illegal instruction exception.
        * Attempts to access a CSR that doesn't exist
          result in an illegal instruction exception.
        * Attempts to write read-only bits to a read/write CSR
          are ignored.

        Because we're building this in hardware, which is
        expensive, we're not implementing any CSRs that aren't
        strictly necessary. The documentation for the misa, mvendorid,
        marchid, and mimpid registers state that they can return zero if
        unimplemented. This implies that unimplemented CSRs still
        exist.

        The mhartid, because we only have one HART, can just return zero.
        """
        with m.Switch(self._funct3):
            with m.Case(SystemFunc.CSRRW):
                self.handle_CSRRW(m)
            with m.Case(SystemFunc.CSRRWI):
                self.handle_CSRRWI(m)
            with m.Case(SystemFunc.CSRRS):
                self.handle_CSRRS(m)
            with m.Case(SystemFunc.CSRRSI):
                self.handle_CSRRSI(m)
            with m.Case(SystemFunc.CSRRC):
                self.handle_CSRRC(m)
            with m.Case(SystemFunc.CSRRCI):
                self.handle_CSRRCI(m)
            with m.Default():
                self.handle_illegal_instr(m)
Exemplo n.º 18
0
    def formal(cls) -> Tuple[Module, List[Signal]]:
        m = Module()
        ph = ClockDomain("ph")
        clk = ClockSignal("ph")

        m.domains += ph
        m.d.sync += clk.eq(~clk)

        s = IC_reg32_with_mux(clk="ph", N=2, faster=True)

        m.submodules += s

        sync_clk = ClockSignal("sync")
        sync_rst = ResetSignal("sync")

        with m.If(Rose(clk)):
            with m.Switch(~Past(s.n_sel)):
                with m.Case(0b11):
                    m.d.comb += Assert(0)
                with m.Case(0b01):
                    m.d.comb += Assert(s.q == Past(s.d[0]))
                with m.Case(0b10):
                    m.d.comb += Assert(s.q == Past(s.d[1]))
                with m.Default():
                    m.d.comb += Assert(s.q == Past(s.q))

        # Make sure the clock is clocking
        m.d.comb += Assume(sync_clk == ~Past(sync_clk))

        # Don't want to test what happens when we reset.
        m.d.comb += Assume(~sync_rst)
        m.d.comb += Assume(~ResetSignal("ph"))

        m.d.comb += Assume(s.n_sel != 0)

        return m, [sync_clk, sync_rst, s.d[0], s.d[1], s.n_sel, s.q]
Exemplo n.º 19
0
    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
            yield
            yield
Exemplo n.º 20
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.º 21
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.º 22
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.º 23
0
    def elaborate(self, _: Platform) -> Module:
        """Implements the logic of the ALU card."""
        m = Module()

        output_buffer = TransparentLatch(size=32)

        m.submodules += output_buffer
        m.d.comb += output_buffer.le.eq(1)
        m.d.comb += output_buffer.data_in.eq(0)
        m.d.comb += self.data_z.eq(output_buffer.data_out)

        m.d.comb += self.alu_eq.eq(0)
        m.d.comb += self.alu_lt.eq(0)
        m.d.comb += self.alu_ltu.eq(0)

        x = self.data_x
        y = self.data_y

        m.d.comb += self.alu_eq.eq(output_buffer.data_in == 0)
        m.d.comb += self.alu_ltu.eq(x < y)
        m.d.comb += self.alu_lt.eq(x.as_signed() < y.as_signed())

        with m.Switch(self.alu_op):
            with m.Case(AluOp.ADD):
                m.d.comb += output_buffer.data_in.eq(x + y)
                m.d.comb += output_buffer.n_oe.eq(0)

            with m.Case(AluOp.SUB):
                m.d.comb += output_buffer.data_in.eq(x - y)
                m.d.comb += output_buffer.n_oe.eq(0)

            with m.Case(AluOp.SLTU):
                m.d.comb += output_buffer.data_in.eq(self.alu_ltu)
                m.d.comb += output_buffer.n_oe.eq(0)

            with m.Case(AluOp.SLT):
                m.d.comb += output_buffer.data_in.eq(self.alu_lt)
                m.d.comb += output_buffer.n_oe.eq(0)

            with m.Case(AluOp.AND):
                m.d.comb += output_buffer.data_in.eq(x & y)
                m.d.comb += output_buffer.n_oe.eq(0)

            with m.Case(AluOp.AND_NOT):
                m.d.comb += output_buffer.data_in.eq(x & ~y)
                m.d.comb += output_buffer.n_oe.eq(0)

            with m.Case(AluOp.OR):
                m.d.comb += output_buffer.data_in.eq(x | y)
                m.d.comb += output_buffer.n_oe.eq(0)

            with m.Case(AluOp.XOR):
                m.d.comb += output_buffer.data_in.eq(x ^ y)
                m.d.comb += output_buffer.n_oe.eq(0)

            with m.Case(AluOp.X):
                m.d.comb += output_buffer.data_in.eq(x)
                m.d.comb += output_buffer.n_oe.eq(0)

            with m.Case(AluOp.Y):
                m.d.comb += output_buffer.data_in.eq(y)
                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.º 24
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.º 25
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.º 26
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        # Set MTVEC to the RESET address, to avoid getting lost in limbo if there's an exception
        # before the boot code sets this to a valid value
        self.mtvec.read.base.reset = self.core_reset_address >> 2

        privmode = Signal(PrivMode)
        privmode.reset = PrivMode.Machine  # default mode is Machine

        m.d.comb += self.m_privmode.eq(privmode)

        # Read/write behavior for all registers
        for reg in self.get_csrs():
            with m.If(reg.we):
                m.d.sync += reg.read.eq(reg.write)

        # constants (at least, the important ones)
        if self.enable_extra_csr:
            misa = 0x1 << 30 | (1 << (ord('i') - ord('a'))
                                )  # 32-bits processor. RV32I
            if self.enable_rv32m:
                misa |= 1 << (ord('m') - ord('a'))  # RV32M
            if self.enable_user_mode:
                misa |= 1 << (ord('u') - ord('a'))  # User mode enabled

            m.d.sync += [
                self.misa.read.eq(misa),
                self.mhartid.read.eq(0),  # ID 0 FOREVER.
                self.mimpid.read.eq(0),  # No implemented = 0
                self.marchid.read.eq(0),  # No implemented = 0
                self.mvendorid.read.eq(0)  # No implemented = 0
            ]

        traps = m.submodules.traps = PriorityEncoder(ExceptionCause.MAX_NUM)
        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(
            ExceptionCause.MAX_NUM)
        m.d.comb += [
            interrupts.i[ExceptionCause.I_M_SOFTWARE].eq(self.mip.read.msip
                                                         & self.mie.read.msie),
            interrupts.i[ExceptionCause.I_M_TIMER].eq(self.mip.read.mtip
                                                      & self.mie.read.mtie),
            interrupts.i[ExceptionCause.I_M_EXTERNAL].eq(self.mip.read.meip
                                                         & self.mie.read.meie),
        ]

        # generate the exception/trap/interrupt signal to kill the pipeline
        # interrupts are globally enable for less priviledge mode than Machine
        m.d.comb += self.m_exception.eq(~traps.n | (
            ~interrupts.n & (self.mstatus.read.mie |
                             (privmode != PrivMode.Machine)) & ~self.m_store))

        # --------------------------------------------------------------------------------
        # overwrite values from the RW circuit
        # --------------------------------------------------------------------------------
        m.d.sync += [
            self.mip.read.msip.eq(self.software_interrupt),
            self.mip.read.mtip.eq(self.timer_interrupt),
            self.mip.read.meip.eq(self.external_interrupt)
        ]

        if self.enable_user_mode:
            self.mstatus.read.mpp.reset = PrivMode.User
            with m.If(self.mstatus.write.mpp != PrivMode.User):
                # In case of writting an invalid priviledge mode, force a valid one
                # For this case, anything different to the User mode is forced to Machine mode.
                m.d.sync += self.mstatus.read.mpp.eq(PrivMode.Machine)
        else:
            self.mstatus.read.mpp.reset = PrivMode.Machine
            m.d.sync += self.mstatus.read.mpp.eq(
                PrivMode.Machine)  # Only machine mode

        # Constant fields in MSTATUS
        # Disable because S-mode and User-level interrupts
        # are not supported.
        m.d.sync += [
            self.mstatus.read.uie.eq(0),
            self.mstatus.read.upie.eq(0),
            self.mstatus.read.sie.eq(0),
            self.mstatus.read.spie.eq(0),
            self.mstatus.read.spp.eq(0),
            self.mstatus.read.mxr.eq(0),
            self.mstatus.read.sum.eq(0),
            self.mstatus.read.tvm.eq(0),
            self.mstatus.read.tsr.eq(0),
            self.mstatus.read.fs.eq(0),
            self.mstatus.read.xs.eq(0),
            self.mstatus.read.sd.eq(0)
        ]
        # MIP and MIE
        m.d.sync += [
            self.mip.read.usip.eq(0),
            self.mip.read.ssip.eq(0),
            self.mip.read.utip.eq(0),
            self.mip.read.stip.eq(0),
            self.mip.read.ueip.eq(0),
            self.mip.read.seip.eq(0),
            self.mie.read.usie.eq(0),
            self.mie.read.ssie.eq(0),
            self.mie.read.utie.eq(0),
            self.mie.read.stie.eq(0),
            self.mie.read.ueie.eq(0),
            self.mie.read.seie.eq(0)
        ]

        # 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.
                m.d.sync += [
                    self.mepc.read.base.eq(self.m_pc[2:]),
                    self.mstatus.read.mpie.eq(self.mstatus.read.mie),
                    self.mstatus.read.mie.eq(0),

                    # Change priviledge mode
                    privmode.eq(PrivMode.Machine),
                    self.mstatus.read.mpp.eq(privmode)
                ]
                # store cause/mtval
                with m.If(~traps.n):
                    m.d.sync += [
                        self.mcause.read.ecode.eq(traps.o),
                        self.mcause.read.interrupt.eq(0)
                    ]
                    with m.Switch(traps.o):
                        with m.Case(ExceptionCause.E_INST_ADDR_MISALIGNED):
                            m.d.sync += self.mtval.read.eq(self.m_pc_misalign)
                        with m.Case(ExceptionCause.E_INST_ACCESS_FAULT):
                            m.d.sync += self.mtval.read.eq(
                                self.m_fetch_badaddr)
                        with m.Case(ExceptionCause.E_ILLEGAL_INST):
                            m.d.sync += self.mtval.read.eq(self.m_instruction)
                        with m.Case(ExceptionCause.E_BREAKPOINT):
                            m.d.sync += self.mtval.read.eq(self.m_pc)
                        with m.Case(
                                ExceptionCause.E_LOAD_ADDR_MISALIGNED,
                                ExceptionCause.E_STORE_AMO_ADDR_MISALIGNED):
                            m.d.sync += self.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.mtval.read.eq(
                                self.m_load_store_badaddr)
                        with m.Default():
                            m.d.sync += self.mtval.read.eq(0)

                with m.Else():
                    m.d.sync += [
                        self.mcause.read.ecode.eq(interrupts.o),
                        self.mcause.read.interrupt.eq(1)
                    ]
            with m.Elif(self.m_mret):
                # restore old mie
                # Restore priviledge mode
                m.d.sync += [
                    self.mstatus.read.mie.eq(self.mstatus.read.mpie),
                    privmode.eq(self.mstatus.read.mpp),
                ]
                if self.enable_user_mode:
                    m.d.sync += self.mstatus.read.mpp.eq(PrivMode.User)

        # counters
        if self.enable_extra_csr:
            mcycle = Signal(64)
            minstret = Signal(64)

            m.d.sync += [
                self.mcycle.read.eq(mcycle[:32]),
                self.mcycleh.read.eq(mcycle[32:64]),
                #
                self.minstret.read.eq(minstret[:32]),
                self.minstreth.read.eq(minstret[32:64])
            ]

            m.d.comb += mcycle.eq(Cat(self.mcycle.read, self.mcycleh.read) + 1)
            with m.If(self.w_retire):
                m.d.comb += minstret.eq(
                    Cat(self.minstret.read, self.minstreth.read) + 1)
            with m.Else():
                m.d.comb += minstret.eq(
                    Cat(self.minstret.read, self.minstreth.read))

            # shadow versions of MCYCLE and MINSTRET
            if self.enable_user_mode:
                m.d.sync += [
                    self.cycle.read.eq(mcycle[:32]),
                    self.cycleh.read.eq(mcycle[32:64]),
                    #
                    self.instret.read.eq(minstret[:32]),
                    self.instreth.read.eq(minstret[32:64])
                ]

        return m
Exemplo n.º 27
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.º 28
0
    def formal(cls) -> Tuple[Module, List[Signal]]:
        """Formal verification for the register card."""
        m = Module()

        ph1 = ClockDomain("ph1")
        ph2 = ClockDomain("ph2")
        regs = RegCard()

        m.domains += [ph1, ph2]
        m.submodules += regs

        # Generate the ph1 and ph2 clocks.
        cycle_count = Signal(8, reset=0, reset_less=True)
        phase_count = Signal(3, reset=0, reset_less=True)

        m.d.sync += phase_count.eq(phase_count + 1)
        with m.Switch(phase_count):
            with m.Case(0, 1, 2):
                m.d.comb += ph1.clk.eq(1)
            with m.Default():
                m.d.comb += ph1.clk.eq(0)
        with m.Switch(phase_count):
            with m.Case(1, 4):
                m.d.comb += ph2.clk.eq(0)
            with m.Default():
                m.d.comb += ph2.clk.eq(1)
        with m.If(phase_count == 5):
            m.d.sync += phase_count.eq(0)
            m.d.sync += cycle_count.eq(cycle_count + 1)

        # This is how we expect to use the card.
        with m.If(phase_count > 0):
            m.d.comb += [
                Assume(Stable(regs.reg_x)),
                Assume(Stable(regs.reg_y)),
                Assume(Stable(regs.reg_z)),
                Assume(Stable(regs.reg_page)),
                Assume(Stable(regs.reg_to_x)),
                Assume(Stable(regs.reg_to_y)),
                Assume(Stable(regs.data_z)),
            ]

        # Figure out how to get to the point where X and Y are nonzero and different.
        m.d.comb += Cover((regs.data_x != 0) & (regs.data_y != 0)
                          & (regs.data_x != regs.data_y))

        # X and Y buses should not change during a cycle, except for the first phase
        with m.Switch(phase_count):
            with m.Case(2, 3, 4, 5):
                with m.If(regs.data_x != 0):
                    m.d.comb += Assert(Stable(regs.data_x))
                with m.If(regs.data_y != 0):
                    m.d.comb += Assert(Stable(regs.data_y))

        # X and Y buses should be zero if there is no data transfer.
        with m.If(regs.reg_to_x == 0):
            m.d.comb += Assert(regs.data_x == 0)
        with m.If(regs.reg_to_y == 0):
            m.d.comb += Assert(regs.data_y == 0)

        with m.If(phase_count > 0):
            # X and Y buses should be zero if we read from register 0.
            with m.If(regs.reg_to_x & (regs.reg_x == 0)):
                m.d.comb += Assert(regs.data_x == 0)
            with m.If(regs.reg_to_y & (regs.reg_y == 0)):
                m.d.comb += Assert(regs.data_y == 0)

        write_pulse = Signal()
        m.d.comb += write_pulse.eq(phase_count != 4)

        # On write, the data should have been written to both banks.
        past_mem_addr = Signal(6)
        m.d.comb += past_mem_addr[:5].eq(Past(regs.reg_z))
        m.d.comb += past_mem_addr[5].eq(Past(regs.reg_page))
        past_z = Past(regs.data_z)
        with m.If(Rose(write_pulse)):
            m.d.comb += Assert(regs._x_bank._mem[past_mem_addr] == past_z)
            m.d.comb += Assert(regs._y_bank._mem[past_mem_addr] == past_z)

        # Pick an register, any register, except 0. We assert that unless
        # it is written, its data will not change.

        check_addr = AnyConst(5)
        check_page = AnyConst(1)
        saved_data = Signal(32)
        stored_x_data = Signal(32)
        stored_y_data = Signal(32)

        write_pulse_domain = ClockDomain("write_pulse_domain", local=True)
        m.domains.write_pulse_domain = write_pulse_domain
        write_pulse_domain.clk = write_pulse

        mem_addr = Signal(6)

        m.d.comb += Assume(check_addr != 0)
        m.d.comb += [
            mem_addr[:5].eq(check_addr),
            mem_addr[5].eq(check_page),
            stored_x_data.eq(regs._x_bank._mem[mem_addr]),
            stored_y_data.eq(regs._y_bank._mem[mem_addr]),
        ]

        with m.If((regs.reg_z == check_addr) & (regs.reg_page == check_page)):
            m.d.write_pulse_domain += saved_data.eq(regs.data_z)

        with m.If(Initial()):
            m.d.comb += Assume(saved_data == stored_x_data)
            m.d.comb += Assume(stored_x_data == stored_y_data)
        with m.Else():
            m.d.comb += Assert(saved_data == stored_x_data)
            m.d.comb += Assert(saved_data == stored_y_data)

        return m, [regs.data_z, regs.reg_to_x, regs.reg_to_y,
                   regs.reg_x, regs.reg_y, regs.reg_z, regs.reg_page, ph1.clk, ph2.clk, saved_data,
                   stored_x_data, stored_y_data]
Exemplo n.º 29
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