Esempio n. 1
0
def test_generate():
    multiplier = [Wire() for _ in range(4)]
    multiplicand = [Wire() for _ in range(4)]

    output, entities = create(multiplier, multiplicand, 4)

    generated = generate([multiplier, multiplicand], [output], entities)
Esempio n. 2
0
def assert_NxN_partial_products(width):
    multiplier = [Wire()] * width
    multiplicand = [Wire()] * width

    wires, entities, compensation = _create_partial_products(multiplier, multiplicand)

    _assert_multiplier(width, wires, entities)
Esempio n. 3
0
def test_full_adder():
    in_1, in_2, in_3 = Wire(), Wire(), Wire()
    out_sum, out_carry = Wire(), Wire()

    fa = FullAdder(in_1, in_2, in_3, out_sum, out_carry)

    assert fa.inputs == [in_1, in_2, in_3]
    assert fa.outputs == [out_sum, out_carry]
Esempio n. 4
0
def test_and_gate():
    in_1, in_2 = Wire(), Wire()
    out = Wire()

    and_gate = And(in_1, in_2, out)

    assert and_gate.inputs == [in_1, in_2]
    assert and_gate.outputs == [out]
Esempio n. 5
0
def test_or_gate():
    in_1, in_2 = Wire(), Wire()
    out = Wire()

    or_gate = Or(in_1, in_2, out)

    assert or_gate.inputs == [in_1, in_2]
    assert or_gate.outputs == [out]
Esempio n. 6
0
def test_half_adder():
    in_1, in_2 = Wire(), Wire()
    out_sum, out_carry = Wire(), Wire()

    ha = HalfAdder(in_1, in_2, out_sum, out_carry)

    assert ha.inputs == [in_1, in_2]
    assert ha.outputs == [out_sum, out_carry]
Esempio n. 7
0
def test_wire():
    w1 = Wire()
    assert w1.value == None

    w2 = Wire(1)
    assert w2.value == 1

    w3 = Wire(w2)
    assert w3.value == w2

    w3.value = w1
    assert w3.value == w1
Esempio n. 8
0
def multiplier(width, output_dir, with_cpa, with_pipeline):
    print('Generating multiplier of two operands, {}-bits wide each.'.format(
        width))

    multiplier_in = [Wire() for _ in range(width)]
    multiplicand_in = [Wire() for _ in range(width)]

    output, entities = multiplier_creator.create(multiplier_in,
                                                 multiplicand_in, width)
    generated = generate([multiplier_in, multiplicand_in], [output], entities)

    with open(output_dir, 'w') as f:
        f.write(generated)

    print('Success! Generated Verilog file saved at {}'.format(output_dir))
Esempio n. 9
0
def _declare_wires():
    """
    Declares the wires to be used in the HDL.

    :rtype: List[string]
    """
    return ['wire [{}:0] wires;'.format(Wire.get_count() - 1)]
Esempio n. 10
0
def _reduce_partial_products(partials):
    """
    Reduce our partial products into a list of entities. We group every
    column's bit in chunks of 3 / 2 bits at a time.

    :type partials: List[List[Wire]]
    :rtype: List[List[Wire]], List[Entity]
    """

    result_width = len(partials)
    entities = []

    # Transform the partial products
    while max(map(len, partials)) > 2:
        next_layer = [[] for _ in range(result_width)]

        for idx, column in enumerate(partials):
            bits = [item for item in column if item != None]
            # Group chunks of bits into a full adder
            for chunk in chunks(bits, 3):
                if len(chunk) == 1:
                    next_layer[idx] += chunk
                    continue

                s = Wire()
                c = Wire()

                if len(chunk) == 3:
                    in_1, in_2, in_3 = chunk

                    fa = FullAdder(in_1, in_2, in_3, s, c)
                    entities += [fa]
                elif len(chunk) == 2:
                    in_1, in_2 = chunk
                    ha = HalfAdder(in_1, in_2, s, c)
                    entities += [ha]

                next_layer[idx] += [s]
                if idx < result_width - 1:
                    next_layer[idx + 1] += [c]

        partials = next_layer

    return partials, entities
Esempio n. 11
0
File: fma.py Progetto: xbili/pyrilog
def create(width, size, cpa=True, signed=True):
    # Generate all the partial products
    inputs, entities = [], []

    res_width = result_bit_width(size, width * 2)
    partials = [[] for _ in range(res_width)]
    compensation = [[] for _ in range(res_width)]

    for i in range(size):
        multiplier_in = [
            Wire(label='a{}{}'.format(i, j)) for j in range(width)
        ]
        multiplicand_in = [
            Wire(label='b{}{}'.format(i, j)) for j in range(width)
        ]

        inputs += [multiplier_in, multiplicand_in]

        product_partial, product_entities, product_compensation =\
            multiplier._create_partial_products(
                multiplier_in,
                multiplicand_in,
            )

        for idx, col in enumerate(product_partial):
            partials[idx] += col
        for idx, col in enumerate(product_compensation):
            compensation[idx] += col
        entities += product_entities

    # Compensate negatively weighted bits
    partials = multiplier.compensate(partials, compensation)

    # Reduce partials
    penultimate, reduction_entities = multiplier._reduce_partial_products(
        partials)

    output, cpa_entities = multiplier._carry_propagate(penultimate)

    return inputs, output, entities + reduction_entities + cpa_entities
Esempio n. 12
0
def _carry_propagate(columns):
    """
    Creates the Carry Propagate Adder at the end of the partial product
    reduction tree given 2 layers.

    :type columns: List[List[Wire]]
    :rtype: List[Wire], List[Entity]
    """

    # We assume that the max number of bits in each column is 2.
    assert max(map(len, columns)) == 2

    res, entities = [], []

    carry = None
    for column in columns:
        if len(column) == 0:
            continue

        if carry:
            s, c = Wire(), Wire()
            if len(column) == 2: # Combine 2 bits and carry with FA
                adder = FullAdder(column[0], column[1], carry, s, c)
            else: # Combine 1 bit and carry with HA
                adder = HalfAdder(column[0], carry, s, c)
            res += [s]
            entities += [adder]
            carry = c
        else:
            if len(column) == 2: # Combine two bits into with a single HA
                s, c = Wire(), Wire()
                adder = HalfAdder(column[0], column[1], s, c)
                entities += [adder]
                carry = c
                res += [s]
            else: # Add the wire into result
                res += [column[0]]

    # Last carry bit to be dropped since it is in 2s complement
    return res, entities
Esempio n. 13
0
def compensate(wires, compensation):
    """
    Compensate negatively weighted bits in 2s complement representation
    of the partial products.
    """

    # Group compensation bits together by moving them one column up
    # until all the way to the left
    for idx, col in enumerate(compensation):
        for chunk in chunks(col, 2):
            # The last column does not need to be negated again
            if idx < len(compensation) - 1:
                compensation[idx + 1] += [-1]

            if len(chunk) == 1:
                wires[idx] += [Wire(value=1, label='1')]

    return wires
Esempio n. 14
0
def pprt(size, width, output_dir, with_cpa, with_pipeline):
    print(
        'Generating reduction tree of {} operands, {}-bits wide each.'.format(
            size, width))

    inputs = []
    for _ in range(size):
        inputs += [[Wire() for _ in range(width)]]
    penultimate, pprt_entities = multiplier_creator._reduce_partial_products(
        inputs)
    output, cpa_entities = multiplier_creator._carry_propagate(penultimate)

    generated = generate(inputs, [output], pprt_entities + cpa_entities)

    with open(output_dir, 'w') as f:
        f.write(generated)

    print('Success! Generated Verilog file saved at {}'.format(output_dir))
Esempio n. 15
0
def test_create():
    multiplier = [Wire()] * 4
    multiplicand = [Wire()] * 4

    wires, entities = create(multiplier, multiplicand, 4)
Esempio n. 16
0
def _create_partial_products(multiplier, multiplicand):
    """
    Combine the multiplier and multiplicand into partial products in separate
    layers in order to group them together with our Wallace strategy later.

    The handling of signed multiplication is in this step, where we utilize
    Modified Baugh-Wooley method to compensate for the negatively weighted
    bits in the PPRT.

    :type multiplier: List[Wire]
    :type multiplicand: List[Wire]
    :rtype: List[List[Wire]], List[Entity]
    """

    # We assume that one is longer than the other
    assert len(multiplier) == len(multiplicand)

    entities = []
    wires = [[] for _ in range(len(multiplier) * 2)]
    compensation = [[] for _ in range(len(multiplier) * 2)]

    # 'AND' related bits together
    for col_x, x in enumerate(multiplier[:-1]):
        for col_a, a in enumerate(multiplicand):
            label = 'a{}x{}'.format(col_a, col_x)
            out = Wire(label=label)

            # Negate the last product
            if col_a == len(multiplicand) - 1:
                out2 = Wire(label=label)
                product = And(a, x, out)
                negate = Not(out, None, out2)

                # Compensate for negating one bit
                compensation[col_x + col_a] += [-1]

                entities += [product, negate]
                wires[col_x + col_a] += [out2]
            else:
                entities += [And(a, x, out)]
                wires[col_x + col_a] += [out]

    # The final layer has every partial product negated except for the
    # last
    for col_a, a in enumerate(multiplicand):
        label = 'a{}x{}'.format(col_a, len(multiplier) - 1)

        out = Wire(label=label)

        if col_a == len(multiplicand) - 1:
            entities += [And(a, multiplier[-1], out)]
            wires[col_a + len(multiplier) - 1] += [out]
        else:
            out2 = Wire(label=label)
            product = And(a, multiplier[-1], out)
            negate = Not(out, None, out2)

            # Compensate for negating the bit
            compensation[col_a + len(multiplier) - 1] += [-1]

            entities += [product, negate]
            wires[col_a + len(multiplier) - 1] += [out2]

    return wires, entities, compensation
Esempio n. 17
0
def reset_counts():
    Wire.reset_count()
    HalfAdder.reset_count()
    FullAdder.reset_count()
Esempio n. 18
0
def assert_NxN_pprt(width):
    multiplier = [Wire()] * width
    multiplicand = [Wire()] * width

    wires, entities, compensation = _create_partial_products(multiplier, multiplicand)
    pprt_wires, pprt_entities = _reduce_partial_products(wires)