def cpu_core(clock, data_in, pc_in, write_pc, debug=False): """ the core CPU state machine executes a 4 state loop continuously s0: fetch address from pc s1: fetch value from address and increment pc s2: fetch address from pc s3: store value to address and increment pc """ network = clock.network word_size = len(data_in) # step through the 4 states in order state = PlaceholderWord(network, 2) incr, c = ripple_incr(state) state.replace(register(incr, clock)) s0, s1, s2, s3 = address_decode(state) # pc increments in s1 and s3, incoming pc writes from the jump module are taken in s3 pc = PlaceholderWord(network, word_size) incr, c = ripple_incr(pc) jumping = And(write_pc, s3) new_pc = word_mux([jumping], incr, pc_in) clock_pc = And(clock, Or(s1, s3)) pc.replace(register(new_pc, clock_pc)) # clock in address in s0 and s2 addr = register(data_in, And(clock, Or(s0, s2))) # set address lines to pc in s0 and s2 and to the previously fetched address in s1 and s3 addr_out = word_switch([Or(s0, s2), Or(s1, s3)], pc, addr) # read in data in s1 data = register(data_in, And(clock, s1)) # write out data in s3 write_out = s3 data_out = data if debug: clock.watch('clock') s0.watch('s0') s1.watch('s1') s2.watch('s2') s3.watch('s3') jumping.watch('jumping') clock_pc.watch('clock pc') write_out.watch('write out') return addr_out, data_out, write_out
def test_register(): network = core.Network() clock = gates.Switch(network) data = test_utils.BinaryIn(network, 8) register = latches.register(data, clock) res = test_utils.BinaryOut(register) network.drain() assert res.read() == 0 # clock a value through v1 = random.randrange(256) data.write(v1) network.drain() assert res.read() == 0 clock.write(True) network.drain() assert res.read() == 0 clock.write(False) network.drain() assert res.read() == v1 # and a different value v2 = random.randrange(256) data.write(v2) network.drain() assert res.read() == v1 clock.write(True) network.drain() assert res.read() == v1 clock.write(False) network.drain() assert res.read() == v2
def sub(clock, write, address, data_in): assert len(address) >= 2 address = address[:2] control_lines = address_decode(address) write_a = And(clock, write, control_lines[0]) a = register(data_in, write_a) write_b = And(clock, write, control_lines[1]) b = register(data_in, write_b) res, carry = ripple_subtractor(a, b) carry = pad([carry], len(data_in)) return word_switch(control_lines, a, b, res, carry)
def jump(clock, write, address, data_in): """ allows manipulation of the PC address read write 0 PC PC 1 PC dest 2 PC if 0: dest -> PC 3 PC if !0: dest -> PC """ assert len(address) >= 2 address = address[:2] control_lines = address_decode(address) # a destination register for conditional jumps write_dest = And(clock, write, control_lines[1]) dest = register(data_in, write_dest) # are we jumping and if so where jump_if_zero = And(control_lines[2], Not(Or(*data_in))) jump_if_not_zero = And(control_lines[3], Or(*data_in)) conditional_jump = Or(jump_if_zero, jump_if_not_zero) unconditional_jump = control_lines[0] write_pc = And(write, Or(conditional_jump, unconditional_jump)) pc_out = word_switch([conditional_jump, unconditional_jump], dest, data_in) return dest, pc_out, write_pc
def memory(clock, write, address, data_in, size): address = address[:size] write_clock = And(clock, write) if size: control_lines = address_decode(address) else: control_lines = [Tie(clock.network, True)] registers = [] for line in control_lines: registers.append(register(data_in, And(line, write_clock))) return word_switch(control_lines, *registers)
def memory(clock, write, address, data_in, size): """ a block of RAM address read write N [N] [N] """ # address_decode can't deal with empty addresses (aka 1 word memories) if not size: control_lines = [Tie(clock.network, True)] else: control_lines = address_decode(address[:size]) # otherwise it's a simple pile of registers switched by the control lines registers = [] data_in_ = invert(data_in) for line in control_lines: registers.append( register(data_in_, And(line, clock, write), negate_in=True, negate_out=True)) return word_switch_(control_lines, *registers)