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