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 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 full_subtractor(a, b, c): """ chain two half subtractors to subtract bit B and previous borrow from A, again returning a difference and a borrow """ s1, c1 = half_subtractor(a, b) s2, c2 = half_subtractor(s1, c) return s2, Or(c1, c2)
def shuffle_right(word, amount): """ shuffle a word right (x2) adding 0's to the left """ network = word[0].network res = [Tie(network, False) for i in range(amount)] + word if amount: carry = Or(*res[len(word):]) else: carry = Tie(network, False) return res[:len(word)], carry
def ripple_sum(*words): """ sum multiple words """ carries = [] # iterate building layers of a binary tree structure while len(words) > 1: new_words = [] # add every adjacent pair, so 1+2, 3+4 etc for a, b in zip(words[::2], words[1::2]): res, carry = ripple_adder(a, b) carries.append(carry) new_words.append(res) # if there is one left at the end just keep it in the next level up if len(words) % 2: new_words.append(words[-1]) words = new_words return words[0], Or(*carries)
def bit_switch(control_lines_, *data_): """ select the bit(s) from the data that match the enabled control line(s) (generally only 1) """ assert len(control_lines_) >= len(data_) return Or(*[Nor(c_, d_) for c_, d_ in zip(control_lines_, data_)])
def half_subtractor(a, b): """ subtract bit B from bit A, return a difference and a borrow """ borrow = And(Not(a), b) result = Or(And(a, Not(b)), And(Not(a), b)) return result, borrow
def full_adder(a, b, c): """ chain two half adders to add two bits and a previous carry, again returning a sum and a carry """ s1, c1 = half_adder(a, b) s2, c2 = half_adder(s1, c) return s2, Or(c1, c2)