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)
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)
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]
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]
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]
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]
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
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))
def _declare_wires(): """ Declares the wires to be used in the HDL. :rtype: List[string] """ return ['wire [{}:0] wires;'.format(Wire.get_count() - 1)]
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
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
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
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
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))
def test_create(): multiplier = [Wire()] * 4 multiplicand = [Wire()] * 4 wires, entities = create(multiplier, multiplicand, 4)
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
def reset_counts(): Wire.reset_count() HalfAdder.reset_count() FullAdder.reset_count()
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)