Exemple #1
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
Exemple #2
0
    def check(self, m: Module, instr: Value, data: FormalData):
        b = instr[6]
        pre_input = Mux(b, data.pre_b, data.pre_a)
        output = Mux(b, data.post_b, data.post_a)

        with m.If(b):
            m.d.comb += Assert(data.post_a == data.pre_a)
        with m.Else():
            m.d.comb += Assert(data.post_b == data.pre_b)

        m.d.comb += [
            Assert(data.post_x == data.pre_x),
            Assert(data.post_sp == data.pre_sp),
            Assert(data.addresses_written == 0),
        ]
        m.d.comb += [
            Assert(data.post_pc == data.plus16(data.pre_pc, 3)),
            Assert(data.addresses_read == 3),
            Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)),
            Assert(data.read_addr[1] == data.plus16(data.pre_pc, 2)),
            Assert(data.read_addr[2] == Cat(data.read_data[1],
                                            data.read_data[0])),
        ]

        input1 = pre_input
        input2 = data.read_data[2]
        z = output == 0
        n = output[7]
        v = 0

        m.d.comb += Assert(output == (input1 | input2))
        self.assertFlags(m, data.post_ccs, data.pre_ccs, Z=z, N=n, V=v)
Exemple #3
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        sign_fill   = Signal()
        operand     = Signal(32)
        r_direction = Signal()
        r_result    = Signal(32)

        shdata      = Signal(64)  # temp data

        # pre-invert the value, if needed
        # Direction:  1 = right. 0 = left.
        m.d.comb += [
            operand.eq(Mux(self.direction, self.dat, self.dat[::-1])),
            sign_fill.eq(Mux(self.direction & self.sign_ext, self.dat[-1], 0)),

            shdata.eq(Cat(operand, Repl(sign_fill, 32)))
        ]

        with m.If(~self.stall):
            m.d.sync += [
                r_direction.eq(self.direction),
                r_result.eq(shdata >> self.shamt)
            ]

        m.d.comb += self.result.eq(Mux(r_direction, r_result, r_result[::-1]))
        return m
Exemple #4
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        a = Signal(signed(33))
        b = Signal(signed(33))
        result_ll = Signal(32)
        result_lh = Signal(33)
        result_hl = Signal(33)
        result_hh = Signal(33)
        result_3 = Signal(64)
        result_4 = Signal(64)
        active = Signal(5)
        is_signed = Signal()
        a_is_signed = Signal()
        b_is_signed = Signal()
        low = Signal()

        m.d.sync += [
            is_signed.eq(a_is_signed ^ b_is_signed),
            active.eq(Cat(self.valid & (active == 0), active)),
            low.eq(self.op == Funct3.MUL)
        ]
        # ----------------------------------------------------------------------
        # fist state
        m.d.comb += [
            a_is_signed.eq((
                (self.op == Funct3.MULH) | (self.op == Funct3.MULHSU))
                           & self.dat1[-1]),
            b_is_signed.eq((self.op == Funct3.MULH) & self.dat2[-1])
        ]
        m.d.sync += [
            a.eq(Mux(a_is_signed, -Cat(self.dat1, 1), self.dat1)),
            b.eq(Mux(b_is_signed, -Cat(self.dat2, 1), self.dat2)),
        ]
        # ----------------------------------------------------------------------
        # second state
        m.d.sync += [
            result_ll.eq(a[0:16] * b[0:16]),
            result_lh.eq(a[0:16] * b[16:33]),
            result_hl.eq(a[16:33] * b[0:16]),
            result_hh.eq(a[16:33] * b[16:33])
        ]
        # ----------------------------------------------------------------------
        # third state
        m.d.sync += [
            result_3.eq(
                Cat(result_ll, result_hh) +
                Cat(Repl(0, 16), (result_lh + result_hl)))
        ]
        # ----------------------------------------------------------------------
        # fourth state
        m.d.sync += [
            result_4.eq(Mux(is_signed, -result_3, result_3)),
            self.result.eq(Mux(low, result_4[:32], result_4[32:64]))
        ]
        m.d.comb += self.ready.eq(active[-1])

        return m
Exemple #5
0
    def ALU(self, m: Module, func: ALU8Func, store: bool = True):
        b = self.instr[6]

        with m.If(self.mode == ModeBits.DIRECT.value):
            operand = self.mode_direct(m)
            self.read_byte(m, cycle=1, addr=operand, comb_dest=self.src8_2)

            with m.If(self.cycle == 2):
                m.d.comb += self.src8_1.eq(Mux(b, self.b, self.a))
                m.d.comb += self.alu8_func.eq(func)
                if store:
                    with m.If(b):
                        m.d.ph1 += self.b.eq(self.alu8)
                    with m.Else():
                        m.d.ph1 += self.a.eq(self.alu8)
                self.end_instr(m, self.pc)

        with m.Elif(self.mode == ModeBits.EXTENDED.value):
            operand = self.mode_ext(m)
            self.read_byte(m, cycle=2, addr=operand, comb_dest=self.src8_2)

            with m.If(self.cycle == 3):
                m.d.comb += self.src8_1.eq(Mux(b, self.b, self.a))
                m.d.comb += self.alu8_func.eq(func)
                if store:
                    with m.If(b):
                        m.d.ph1 += self.b.eq(self.alu8)
                    with m.Else():
                        m.d.ph1 += self.a.eq(self.alu8)
                self.end_instr(m, self.pc)

        with m.Elif(self.mode == ModeBits.IMMEDIATE.value):
            operand = self.mode_immediate8(m)

            with m.If(self.cycle == 2):
                m.d.comb += self.src8_1.eq(Mux(b, self.b, self.a))
                m.d.comb += self.src8_2.eq(operand)
                m.d.comb += self.alu8_func.eq(func)
                if store:
                    with m.If(b):
                        m.d.ph1 += self.b.eq(self.alu8)
                    with m.Else():
                        m.d.ph1 += self.a.eq(self.alu8)
                self.end_instr(m, self.pc)

        with m.Elif(self.mode == ModeBits.INDEXED.value):
            operand = self.mode_indexed(m)
            self.read_byte(m, cycle=3, addr=operand, comb_dest=self.src8_2)

            with m.If(self.cycle == 4):
                m.d.comb += self.src8_1.eq(Mux(b, self.b, self.a))
                m.d.comb += self.alu8_func.eq(func)
                if store:
                    with m.If(b):
                        m.d.ph1 += self.b.eq(self.alu8)
                    with m.Else():
                        m.d.ph1 += self.a.eq(self.alu8)
                self.end_instr(m, self.pc)
Exemple #6
0
    def check(self, m: Module, instr: Value, data: FormalData):
        b = instr[6]
        pre_input = Mux(b, data.pre_b, data.pre_a)
        output = Mux(b, data.post_b, data.post_a)

        carry_in = Signal()
        sum9 = Signal(9)
        sum8 = Signal(8)
        sum5 = Signal(5)
        with_carry = (instr[1] == 0)

        with m.If(b):
            m.d.comb += Assert(data.post_a == data.pre_a)
        with m.Else():
            m.d.comb += Assert(data.post_b == data.pre_b)

        m.d.comb += [
            Assert(data.post_x == data.pre_x),
            Assert(data.post_sp == data.pre_sp),
            Assert(data.addresses_written == 0),
        ]
        m.d.comb += [
            Assert(data.post_pc == data.plus16(data.pre_pc, 3)),
            Assert(data.addresses_read == 3),
            Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)),
            Assert(data.read_addr[1] == data.plus16(data.pre_pc, 2)),
            Assert(
                data.read_addr[2] == Cat(data.read_data[1], data.read_data[0])),
        ]

        h = sum5[4]
        n = sum9[7]
        c = sum9[8]
        z = (sum9[:8] == 0)
        v = (sum8[7] ^ c)

        with m.If(with_carry):
            m.d.comb += carry_in.eq(data.pre_ccs[_C])
        with m.Else():
            m.d.comb += carry_in.eq(0)

        input1 = pre_input
        input2 = data.read_data[2]

        m.d.comb += [
            sum9.eq(input1 + input2 + carry_in),
            sum8.eq(input1[:7] + input2[:7] + carry_in),
            sum5.eq(input1[:4] + input2[:4] + carry_in),
            Assert(output == sum9[:8]),
        ]
        self.assertFlags(m, data.post_ccs, data.pre_ccs,
                         Z=z, N=n, V=v, C=c, H=h)
Exemple #7
0
    def elaborate(self, platform: Platform) -> Module:
        m             = Module()

        is_div        = Signal()
        is_divu       = Signal()
        is_rem        = Signal()
        dividend      = Signal(32)
        divisor       = Signal(63)
        quotient      = Signal(32)
        quotient_mask = Signal(32)
        start         = Signal()
        outsign       = Signal()

        m.d.comb += [
            is_div.eq(self.op == Funct3.DIV),
            is_divu.eq(self.op == Funct3.DIVU),
            is_rem.eq(self.op == Funct3.REM)
        ]

        m.d.comb += start.eq(self.start & ~self.busy)

        with m.If(start):
            m.d.sync += [
                dividend.eq(Mux((is_div | is_rem) & self.dat1[-1], -self.dat1, self.dat1)),
                divisor.eq(Mux((is_div | is_rem) & self.dat2[-1], -self.dat2, self.dat2) << 31),
                outsign.eq((is_div & (self.dat1[-1] ^ self.dat2[-1]) & (self.dat2 != 0)) | (is_rem & self.dat1[-1])),
                quotient.eq(0),
                quotient_mask.eq(1 << 31),
                self.busy.eq(1)
            ]
        with m.Elif(quotient_mask == 0 & self.busy):
            m.d.sync += self.busy.eq(0)

            with m.If(is_div | is_divu):
                m.d.sync += self.result.eq(Mux(outsign, -quotient, quotient))
            with m.Else():
                m.d.sync += self.result.eq(Mux(outsign, -dividend, dividend))
        with m.Else():
            with m.If(divisor <= dividend):
                m.d.sync += [
                    dividend.eq(dividend - divisor),
                    quotient.eq(quotient | quotient_mask)
                ]
            m.d.sync += [
                divisor.eq(divisor >> 1),
                quotient_mask.eq(quotient_mask >> 1)
            ]

        return m
Exemple #8
0
    def elab(self, m):
        # Track previous restart, next
        was_restart = Signal()
        m.d.sync += was_restart.eq(self.restart)
        was_next = Signal()
        m.d.sync += was_next.eq(self.next)

        # Decide address to be output (determines data available next cycle)
        last_mem_addr = Signal.like(self.limit)
        m.d.sync += last_mem_addr.eq(self.mem_addr)
        incremented_addr = Signal.like(self.limit)
        m.d.comb += incremented_addr.eq(
            Mux(last_mem_addr == self.limit - 1, 0, last_mem_addr + 1))
        with m.If(self.restart):
            m.d.comb += self.mem_addr.eq(0)
        with m.Elif(was_next | was_restart):
            m.d.comb += self.mem_addr.eq(incremented_addr)
        with m.Else():
            m.d.comb += self.mem_addr.eq(last_mem_addr)

        # Decide data to be output
        last_data = Signal.like(self.data)
        m.d.sync += last_data.eq(self.data)
        with m.If(was_restart | was_next):
            m.d.comb += self.data.eq(self.mem_data)
        with m.Else():
            m.d.comb += self.data.eq(last_data)
Exemple #9
0
 def elab(self, m):
     # TODO: reimplement as a function that returns an expression
     mask = (1 << self.exponent) - 1
     remainder = self.x & mask
     threshold = (mask >> 1) + self.x[31]
     rounding = Mux(remainder > threshold, 1, 0)
     m.d.comb += self.result.eq((self.x >> self.exponent) + rounding)
Exemple #10
0
    def check(self, m: Module, instr: Value, data: FormalData):
        b = instr[6]
        input = Mux(b, data.pre_b, data.pre_a)

        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),
        ]
        m.d.comb += [
            Assert(data.post_pc == data.plus16(data.pre_pc, 3)),
            Assert(data.addresses_read == 2),
            Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)),
            Assert(data.read_addr[1] == data.plus16(data.pre_pc, 2)),
            Assert(data.addresses_written == 1),
            Assert(data.write_addr[0] == Cat(data.read_data[1],
                                             data.read_data[0])),
            Assert(data.write_data[0] == input),
        ]
        self.assertFlags(m,
                         data.post_ccs,
                         data.pre_ccs,
                         Z=(input == 0),
                         N=input[7],
                         V=0)
Exemple #11
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()
        m.submodules.mbc = self.mbc

        any_cs = Signal()
        rom_cs = Signal()

        m.d.comb += [
            self.mbc.cart_rst.eq(self.cart_rst),
            self.mbc.cart_addr.eq(self.cart_addr),
            self.mbc.cart_data.eq(self.cart_data),
            self.mbc.cart_wr.eq(self.cart_wr),
        ]
        m.d.comb += [
            self.ram_bank.eq(self.mbc.ram_bank),
            self.rom_bank.eq(self.mbc.rom_bank),
        ]

        m.d.comb += [rom_cs.eq(~self.cart_addr[15]), any_cs.eq(self.ram_cs ^ rom_cs)]

        m.d.comb += self.data_dir.eq(
            Mux(self.cart_rd & any_cs, DataDirection.OUTPUT, DataDirection.INPUT)
        )
        m.d.comb += self.cart_oe.eq(
            (self.cart_rd | self.cart_wr | self.rom_wr) & any_cs
        )
        m.d.comb += self.ram_cs.eq(
            m.submodules.mbc.ram_en & self.cart_cs & (self.cart_addr[13:] == 0b101)
        )

        return m
Exemple #12
0
 def process_load(self, input_value):
     lh_value = Signal(32)
     comb = self.core.current_module.d.comb
     
     bit_to_replicate=Mux(self.core.itype.funct3[2], Const(0,1), input_value[15])
     comb += lh_value.eq(Cat(input_value[0:16], Repl(bit_to_replicate, 16)))
     return lh_value
Exemple #13
0
    def mode_ext(self, m: Module) -> Statement:
        """Generates logic to get the 16-bit operand for extended mode instructions.

        Returns a Statement containing the 16-bit operand. After cycle 2, tmp16 
        contains the operand.
        """
        operand = Mux(self.cycle == 2, Cat(self.Din, self.tmp16[8:]),
                      self.tmp16)

        with m.If(self.cycle == 1):
            m.d.ph1 += self.tmp16[8:].eq(self.Din)
            m.d.ph1 += self.pc.eq(self.pc + 1)
            m.d.ph1 += self.Addr.eq(self.pc + 1)
            m.d.ph1 += self.RW.eq(1)
            m.d.ph1 += self.cycle.eq(2)
            if self.verification is not None:
                self.formalData.read(m, self.Addr, self.Din)

        with m.If(self.cycle == 2):
            m.d.ph1 += self.tmp16[:8].eq(self.Din)
            m.d.ph1 += self.pc.eq(self.pc + 1)
            m.d.ph1 += self.cycle.eq(3)
            if self.verification is not None:
                self.formalData.read(m, self.Addr, self.Din)

        return operand
Exemple #14
0
    def IN_DE_X(self, m: Module):
        """Increments or decrements X."""
        dec = self.instr[0]

        with m.If(self.cycle == 1):
            m.d.ph1 += self.VMA.eq(0)
            m.d.ph1 += self.Addr.eq(self.x)
            m.d.ph1 += self.x.eq(Mux(dec, self.x - 1, self.x + 1))

        with m.If(self.cycle == 2):
            m.d.ph1 += self.VMA.eq(0)
            m.d.ph1 += self.Addr.eq(self.x)

        with m.If(self.cycle == 3):
            m.d.comb += self.alu8_func.eq(
                Mux(self.x == 0, ALU8Func.SEZ, ALU8Func.CLZ))
            self.end_instr(m, self.pc)
Exemple #15
0
    def elaborate(self, _: Platform) -> Module:
        """Implements the logic for the reverser."""
        m = Module()

        m.d.comb += self.data_out.eq(
            Mux(self.en, self.data_in[::-1], self.data_in))

        return m
Exemple #16
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
def rounding_divide_by_pot(x, exponent):
    """Implements gemmlowp::RoundingDivideByPOT

    This divides by a power of two, rounding to the nearest whole number.
    """
    mask = (1 << exponent) - 1
    remainder = x & mask
    threshold = (mask >> 1) + x[31]
    rounding = Mux(remainder > threshold, 1, 0)
    return (x >> exponent) + rounding
Exemple #18
0
    def check(self, m: Module, instr: Value, data: FormalData):
        b = instr[6]
        pre_input = Mux(b, data.pre_b, data.pre_a)

        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),
        ]
        m.d.comb += [
            Assert(data.post_pc == data.plus16(data.pre_pc, 3)),
            Assert(data.addresses_read == 3),
            Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)),
            Assert(data.read_addr[1] == data.plus16(data.pre_pc, 2)),
            Assert(
                data.read_addr[2] == Cat(data.read_data[1], data.read_data[0])),
        ]

        input1 = pre_input
        input2 = data.read_data[2]
        sinput1 = Signal(signed(8))
        sinput2 = Signal(signed(8))
        m.d.comb += sinput1.eq(input1)
        m.d.comb += sinput2.eq(input2)

        z = (input1 == input2)
        n = (input1 - input2)[7]

        # The following is wrong. This would calculate LT (less than), not N.
        # In other words, N is not a comparison, it's just the high bit
        # of the (unsigned) result.
        # n = ((sinput1 - sinput2) < 0)

        # GE is true if and only if N^V==0 (i.e. N == V).
        ge = sinput1 >= sinput2
        v = Mux(ge, n, ~n)
        c = (input1 < input2)

        self.assertFlags(m, data.post_ccs, data.pre_ccs,
                         Z=z, N=n, V=v, C=c)
Exemple #19
0
    def elab(self, m):
        count = Signal.like(self.max)
        last_count = self.max - 1
        next_count = Mux(count == last_count, 0, count + 1)

        with m.If(self.en):
            m.d.sync += count.eq(next_count)
            m.d.comb += self.done.eq(count == last_count)

        with m.If(self.restart):
            m.d.sync += count.eq(0)
Exemple #20
0
def increment_to_limit(value, limit):
    """Builds a statement that performs circular increments.

    Parameters
    ----------
    value: Signal(n)
        The value to be incremented
    limit: Signal(n)
        The maximum allowed value
    """
    return value.eq(Mux(value == limit - 1, 0, value + 1))
Exemple #21
0
    def STAext(self, m: Module):
        operand = self.mode_ext(m)

        b = self.instr[6]

        with m.If(self.cycle == 2):
            m.d.ph1 += self.VMA.eq(0)
            m.d.ph1 += self.Addr.eq(operand)
            m.d.ph1 += self.RW.eq(1)

        with m.If(self.cycle == 3):
            m.d.ph1 += self.Addr.eq(operand)
            m.d.ph1 += self.Dout.eq(Mux(b, self.b, self.a))
            m.d.ph1 += self.RW.eq(0)
            m.d.ph1 += self.cycle.eq(4)

        with m.If(self.cycle == 4):
            if self.verification is not None:
                self.formalData.write(m, self.Addr, self.Dout)
            m.d.comb += self.src8_2.eq(Mux(b, self.b, self.a))
            m.d.comb += self.alu8_func.eq(ALU8Func.LD)
            self.end_instr(m, self.pc)
Exemple #22
0
    def BR(self, m: Module):
        operand = self.mode_immediate8(m)

        relative = Signal(signed(8))
        m.d.comb += relative.eq(operand)

        # At this point, pc is the instruction start + 2, so we just
        # add the signed relative offset to get the target.
        with m.If(self.cycle == 2):
            m.d.ph1 += self.tmp16.eq(self.pc + relative)

        with m.If(self.cycle == 3):
            take_branch = self.branch_check(m)
            self.end_instr(m, Mux(take_branch, self.tmp16, self.pc))
Exemple #23
0
    def check(self, m: Module, instr: Value, data: FormalData):
        mode = instr[4:6]
        b = instr[6]
        input = Mux(b, data.pre_b, data.pre_a)

        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),
        ]

        with m.If(mode == ModeBits.DIRECT.value):
            m.d.comb += [
                Assert(data.post_pc == data.plus16(data.pre_pc, 2)),
                Assert(data.addresses_read == 1),
                Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)),
                Assert(data.addresses_written == 1),
                Assert(data.write_addr[0] == data.read_data[0]),
                Assert(data.write_data[0] == input),
            ]
        with m.Elif(mode == ModeBits.EXTENDED.value):
            m.d.comb += [
                Assert(data.post_pc == data.plus16(data.pre_pc, 3)),
                Assert(data.addresses_read == 2),
                Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)),
                Assert(data.read_addr[1] == data.plus16(data.pre_pc, 2)),
                Assert(data.addresses_written == 1),
                Assert(data.write_addr[0] == Cat(data.read_data[1],
                                                 data.read_data[0])),
                Assert(data.write_data[0] == input),
            ]

        with m.Elif(mode == ModeBits.INDEXED.value):
            m.d.comb += [
                Assert(data.post_pc == data.plus16(data.pre_pc, 2)),
                Assert(data.addresses_read == 1),
                Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)),
                Assert(data.addresses_written == 1),
                Assert(data.write_addr[0] == (data.pre_x +
                                              data.read_data[0])[:16]),
                Assert(data.write_data[0] == input),
            ]

        self.assertFlags(m,
                         data.post_ccs,
                         data.pre_ccs,
                         Z=(input == 0),
                         N=input[7],
                         V=0)
Exemple #24
0
    def elab(self, m):
        # Current r_addr is the address being presented to memory this cycle
        # By default current address is last address, but this can be
        # modied by the reatart or next signals
        last_addr = Signal.like(self.r_addr)
        m.d.sync += last_addr.eq(self.r_addr)
        m.d.comb += self.r_addr.eq(last_addr)

        # Respond to inputs
        with m.If(self.restart):
            m.d.comb += self.r_addr.eq(0)
        with m.Elif(self.next):
            m.d.comb += self.r_addr.eq(Mux(last_addr >=
                                           self.limit - 1, 0, last_addr + 1))
Exemple #25
0
    def ALUext(self, m: Module, func: ALU8Func, store: bool = True):
        operand = self.mode_ext(m)
        self.read_byte(m, cycle=2, addr=operand, comb_dest=self.src8_2)

        b = self.instr[6]

        with m.If(self.cycle == 3):
            m.d.comb += self.src8_1.eq(Mux(b, self.b, self.a))
            m.d.comb += self.alu8_func.eq(func)
            if store:
                with m.If(b):
                    m.d.ph1 += self.b.eq(self.alu8)
                with m.Else():
                    m.d.ph1 += self.a.eq(self.alu8)
            self.end_instr(m, self.pc)
Exemple #26
0
    def elaborate(self, _: Platform) -> Module:
        """Implements the logic of the sequencer card."""
        m = Module()

        m.submodules.instr_latch = self._instr_latch
        m.submodules.rom = self.rom
        m.submodules.trap_rom = self.trap_rom
        m.submodules.irq_load_rom = self.irq_load_rom

        m.d.comb += self._pc_plus_4.eq(self.state._pc + 4)
        m.d.comb += self.vec_mode.eq(self.state._mtvec[:2])
        m.d.comb += self.memaddr_2_lsb.eq(self.state.memaddr[0:2])
        m.d.comb += self.imm0.eq(self._imm == 0)
        m.d.comb += self.rd0.eq(self._rd == 0)
        m.d.comb += self.rs1_0.eq(self._rs1 == 0)
        m.d.comb += self.csr_num_is_mtvec.eq(self.csr_num == CSRAddr.MTVEC)
        m.d.comb += self.mtvec_mux_select.eq(Mux(self.z_to_csr & self.csr_num_is_mtvec,
                                                 SeqMuxSelect.Z, SeqMuxSelect.MTVEC))
        # Only used on instruction phase 1 in BRANCH, which is why we can
        # register this on phase 1. Also, because it's an input to a ROM,
        # we have to ensure the signal is registered.
        m.d.ph1 += self.data_z_in_2_lsb0.eq(self.data_z_in[0:2] == 0)

        with m.If(self.set_instr_complete):
            m.d.comb += self.instr_complete.eq(self.mcycle_end)
        with m.Else():
            m.d.comb += self.instr_complete.eq(0)

        # We only check interrupts once we're about to load an instruction but we're not already
        # trapping an interrupt.
        m.d.comb += self.is_interrupted.eq(all_true(self.instr_complete,
                                                    ~self.state.trap,
                                                    (self.mei_pend | self.mti_pend)))

        # Because we don't support the C (compressed instructions)
        # extension, the PC must be 32-bit aligned.
        m.d.comb += self.instr_misalign.eq(
            all_true(self.state._pc[0:2] != 0, ~self.state.trap))

        m.d.comb += self.enable_sequencer_rom.eq(
            ~self.state.trap & ~self.instr_misalign & ~self.bad_instr)

        self.encode_opcode_select(m)
        self.connect_roms(m)
        self.process(m)
        self.updates(m)

        return m
Exemple #27
0
    def check(self, m: Module):
        input, actual_output = self.common_check(m)
        expected_output = Signal(8)

        with m.If(self.instr.matches(INC)):
            m.d.comb += expected_output.eq((input + 1)[:8])
        with m.If(self.instr.matches(DEC)):
            m.d.comb += expected_output.eq((input - 1)[:8])

        m.d.comb += Assert(expected_output == actual_output)
        z = expected_output == 0
        n = expected_output[7]
        v = Mux(self.instr.matches(INC), expected_output == 0x80,
                expected_output == 0x7F)

        self.assert_flags(m, Z=z, N=n, V=v)
Exemple #28
0
    def check(self, m: Module, instr: Value, data: FormalData):
        input, actual_output = self.common_check(m, instr, data)
        expected_output = Signal(8)

        with m.If(instr.matches(INC)):
            m.d.comb += expected_output.eq((input + 1)[:8])
        with m.If(instr.matches(DEC)):
            m.d.comb += expected_output.eq((input - 1)[:8])

        m.d.comb += Assert(expected_output == actual_output)
        z = (expected_output == 0)
        n = expected_output[7]
        v = Mux(instr.matches(INC), expected_output == 0x80,
                expected_output == 0x7F)

        self.assertFlags(m, data.post_ccs, data.pre_ccs, Z=z, N=n, V=v)
Exemple #29
0
    def mode_immediate8(self, m: Module) -> Statement:
        """Generates logic to get the 8-bit operand for immediate mode instructions.

        Returns a Statement containing an 8-bit operand.
        After cycle 1, tmp8 contains the operand.
        """
        operand = Mux(self.cycle == 1, self.Din, self.tmp8)

        with m.If(self.cycle == 1):
            m.d.ph1 += self.tmp8.eq(self.Din)
            m.d.ph1 += self.pc.eq(self.pc + 1)
            m.d.ph1 += self.Addr.eq(self.pc + 1)
            m.d.ph1 += self.RW.eq(1)
            if self.verification is not None:
                self.formalData.read(m, self.Addr, self.Din)

        return operand
Exemple #30
0
    def check(self, m: Module, instr: Value, data: FormalData):
        m.d.comb += [
            Assert(data.post_ccs == data.pre_ccs),
            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),
        ]

        m.d.comb += [
            Assert(data.addresses_read == 1),
            Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)),
        ]

        n = data.pre_ccs[Flags.N]
        z = data.pre_ccs[Flags.Z]
        v = data.pre_ccs[Flags.V]
        c = data.pre_ccs[Flags.C]
        offset = Signal(signed(8))
        br = instr[:4]

        take_branch = Array([
            Const(1),
            Const(0),
            (c | z) == 0,
            (c | z) == 1,
            c == 0,
            c == 1,
            z == 0,
            z == 1,
            v == 0,
            v == 1,
            n == 0,
            n == 1,
            (n ^ v) == 0,
            (n ^ v) == 1,
            (z | (n ^ v)) == 0,
            (z | (n ^ v)) == 1,
        ])
        m.d.comb += offset.eq(data.read_data[0])
        m.d.comb += Assert(
            data.post_pc == Mux(take_branch[br], (data.pre_pc + 2 +
                                                  offset)[:16], (data.pre_pc +
                                                                 2)[:16]))