Example #1
0
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
Example #2
0
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
Example #3
0
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)
Example #4
0
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
Example #5
0
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
Example #6
0
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)
Example #7
0
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)