コード例 #1
0
ファイル: bus.py プロジェクト: tolomea/Minecraft
def bus(address, write, modules):
    """
    the bus switches the write line between the modules and muxes the data lines coming back
    in both cases based on the address lines
    """
    address_ = invert(address)

    # module prefixes are aligned to their sizes
    for prefix, size, data_in in modules:
        assert prefix % 2**size == 0, (prefix, size)

    # module ranges don't overlap
    _modules = sorted(modules)
    for a, b in zip(_modules, _modules[1:]):
        a_start, a_size, _ = a
        b_start, b_size, _ = b
        a_end = a_start + 2**a_size - 1
        assert a_end < b_start

    # the control line for each module is based on the relevant address prefix match
    control_lines = []
    for prefix, size, data_in in modules:
        prefix //= 2**size
        control_lines.append(address_matches(prefix, address[size:], address_[size:]))

    # switch the data and write lines based on the control lines
    data_out = word_switch(control_lines, *[d for p, s, d in modules])
    write_lines = [And(write, ctrl) for ctrl in control_lines]

    return data_out, write_lines
コード例 #2
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
コード例 #3
0
def rom(clock, write, address, data_in, size, data):
    address = address[:size]
    control_lines = address_decode(address, len(data))
    assert len(data) <= len(control_lines)
    network = clock.network
    data_size = len(data_in)
    ties = [tie_word(network, data_size, d) for d in data]
    return word_switch(control_lines, *ties)
コード例 #4
0
def bus(address, write, modules):
    control_lines = []
    for prefix, size, data_in in modules:
        prefix //= 2**size
        control_lines.append(equals(prefix, address[size:]))
    data_out = word_switch(control_lines, *[d for p, s, d in modules])
    write_lines = [And(write, ctrl) for ctrl in control_lines]
    return data_out, write_lines
コード例 #5
0
ファイル: cpu_core.py プロジェクト: tolomea/Minecraft
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
コード例 #6
0
def rom(clock, write, address, data_in, size, data):
    """
    a block of ROM containing the specified data

    address  read     write
    N        data[N]  -
    """
    network = clock.network
    data_size = len(data_in)
    assert len(data) <= 2**len(address)

    # just ties muxed by address
    control_lines = address_decode(address[:size], len(data))
    ties = [tie_word(network, data_size, d) for d in data]
    return word_switch(control_lines, *ties)
コード例 #7
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)
コード例 #8
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)