From 5b04327dfa7a3005819045c9cc19e558e86d59d5 Mon Sep 17 00:00:00 2001 From: functionpointersuss Date: Sat, 23 Dec 2023 10:23:39 +0800 Subject: renamed to sv --- multiplier/gen_wallace.py | 354 ---------------------------------------------- 1 file changed, 354 deletions(-) delete mode 100755 multiplier/gen_wallace.py (limited to 'multiplier/gen_wallace.py') diff --git a/multiplier/gen_wallace.py b/multiplier/gen_wallace.py deleted file mode 100755 index ed5c4f5..0000000 --- a/multiplier/gen_wallace.py +++ /dev/null @@ -1,354 +0,0 @@ -#!/usr/bin/python3 -import argparse - -def gen_half_adder(): - print(f"---------- Half adder generation ----------") - f = open(f"half_adder.v", "w") - f.write(f"""module half_adder ( - input logic a, - input logic b, - output logic sum, - output logic carry -); - -assign sum = a ^ b; -assign carry = a & b; - -endmodule -""") - f.close() - -def gen_full_adder(): - print(f"---------- Full adder generation ----------") - f = open(f"full_adder.v", "w") - f.write(f"""module full_adder ( - input logic a, - input logic b, - input logic c, - output logic sum, - output logic carry -); - -assign sum = a ^ b ^ c; -assign carry = (a & b) | (c & (a ^ b)); - -endmodule -""") - f.close() - -def gen_multiplier(bits): - print(f"\n---------- {bits} Bit Top Level Multiplier Generation ----------") - f = open(f"multiplier.v", "w") - f.write(f"""module multiplier( - input logic [{bits-1}:0] a, - input logic [{bits-1}:0] b, - output logic [{2*bits-1}:0] c -); - - logic [{bits-1}:0] partial_prod [0:{bits-1}]; - logic [{2*bits-1}:0] partial_sum; - - assign c = partial_sum; - - wallace_adder wadder0(partial_prod, partial_sum); - partial_products partprod0(a, b, partial_prod); - -endmodule -""") - f.close() - -def gen_partial_products(bits): - print(f"------------ {bits} Bit Partial Products Generation ------------") - f = open(f"partial_products.v", "w") - f.write(f"""module partial_products -( - input logic [{bits-1}:0] a, - input logic [{bits-1}:0] b, - output logic [{bits-1}:0] c [0:{bits-1}] -); - -always @ (*) begin - integer i; - for (i = 0; i < {bits}; i=i+1) begin - c[i][{bits-1}:0] = {{{bits}{{b[i]}}}} & a; - end -end - -endmodule -""") - - f.close() - -def add_half_adder(reduction_layers, instantiations, net_names, col, col_idx, curr_layer, prev_layer, debug): - # Generates nets and updates the layer net array - curr_col_net_idx = len(reduction_layers[curr_layer][col_idx]) - next_col_net_idx = len(reduction_layers[curr_layer][col_idx+1]) - cout = f"layer{curr_layer}_col{col_idx}_net{curr_col_net_idx}" - sout = f"layer{curr_layer}_col{col_idx+1}_net{next_col_net_idx}" - - reduction_layers[curr_layer][col_idx].append(cout) - reduction_layers[curr_layer][col_idx+1].append(sout) - - # Adds half adder to instantiations - net_names[prev_layer].append(cout) - net_names[prev_layer].append(sout) - a, b = [col.pop() for i in range(2)] - instantiations[prev_layer].append(f"half_adder ha_add{curr_layer}_{len(instantiations[prev_layer])} ({a}, {b}, {cout}, {sout});") - - # Debug Print half adder - if debug: - print(f"half_adder ha_add{curr_layer}_{len(instantiations[prev_layer])} ({a}, {b}, {cout}, {sout});") - - pass - -def add_full_adder(reduction_layers, instantiations, net_names, col, col_idx, curr_layer, prev_layer, debug): - # Generates nets and updates the layer net array - curr_col_net_idx = len(reduction_layers[curr_layer][col_idx]) - next_col_net_idx = len(reduction_layers[curr_layer][col_idx+1]) - cout = f"layer{curr_layer}_col{col_idx}_net{curr_col_net_idx}" - sout = f"layer{curr_layer}_col{col_idx+1}_net{next_col_net_idx}" - reduction_layers[curr_layer][col_idx].append(cout) - reduction_layers[curr_layer][col_idx+1].append(sout) - - # Adds nets and adders to be instantiated - net_names[prev_layer].append(cout) - net_names[prev_layer].append(sout) - a, b, cin = [col.pop() for i in range(3)] - instantiations[prev_layer].append(f"full_adder fa_add{curr_layer}_{len(instantiations[prev_layer])} ({a}, {b}, {cin}, {cout}, {sout});") - - # Debug Print half adder - if debug: - print(f"full_adder fa_add{curr_layer}_{len(instantiations[prev_layer])} ({a}, {b}, {cin}, {cout}, {sout});") - -def add_passthrough(reduction_layers, instantiations, net_names, col, col_idx, curr_layer, prev_layer, debug): -# Assigns passthrough for remaining logic and updates the counter - curr_col_net_idx = len(reduction_layers[curr_layer][col_idx]) - passthrough = f"layer{curr_layer}_col{col_idx}_net{curr_col_net_idx}" - - # Adds passthrough to netlist array - reduction_layers[curr_layer][col_idx].append(passthrough) - - # Adds the assign statement to passthrough - net_names[prev_layer].append(passthrough) - input_net1 = col.pop() - instantiations[prev_layer].append(f"assign {passthrough} = {input_net1};") - - if debug: - print(f"assign {passthrough} = {input_net1};") - -def gen_adder_tree(bits, debug): - print(f"--------------- {bits} Bit Adder Tree Generation ---------------") - - # Parameters of the adder tree generate script - num_cols = (2 * bits) - layer_limit = 50 - - # Initialize reduction layer array - reduction_layers = [] - - # Initialize instantiations and net names - ha_instantiations = [] - fa_instantiations = [] - pass_instantiations = [] - net_names = [] - - # Partial layer is the "zeroeth" reduction layer, initialize it - curr_layer = 0 - reduction_layers.append([[] for i in range(num_cols)]) - - # Fill up partial layer - for i in range(bits): - for j in range(bits): - reduction_layers[curr_layer][i+j].append(f"partial_prod[{i}][{j}]") - - # Debug partial layer print - if debug: - print(f"\n--------- LAYER {curr_layer} -------------") - for col_idx, reduce in enumerate(reduction_layers[curr_layer]): - print(f"Col: {col_idx}, Length: {len(reduce)}, {reduce}") - - # Build out subsequent reduction layers - curr_layer = 1 - prev_layer = 0 - - instantiation_idx = 0 - - # Run until we can add the remaining bit vectors together or non-convergent solution - while (len(max(reduction_layers[prev_layer], key=len)) > 2 and curr_layer < layer_limit): - # Allocate next layer - if debug: - print(f"--------- LAYER {prev_layer} -------------") - reduction_layers.append([[] for i in range(num_cols)]) - pass_instantiations.append([]) - ha_instantiations.append([]) - fa_instantiations.append([]) - net_names.append([]) - - carry_propogation = 0 - extra_ha = (len(max(reduction_layers[prev_layer], key=len)) == 3) - fa_used = False - ha_used = False - - # Counts how many bits need to be eventually removed by this bit - for col_idx, col in enumerate(reduction_layers[prev_layer]): - - # Check that this is actually solvable using only 2*bits output - if (col_idx+1 == len(reduction_layers[prev_layer]) and (len(col) + carry_propogation) > 2): - print("Cannot SOLVE") - return -1 - - # Debug print for this column - if debug: - print(f"Index: {col_idx}, Length: {len(col)}") - - next_layer_size = carry_propogation - carry_propogation = 0 - - # Add full adders if needed - while (len(col) > 3): - add_full_adder(reduction_layers, fa_instantiations, net_names, col, col_idx, curr_layer, prev_layer, debug) - fa_used = True - # 1 carry will go to the next column next layer, and the sum will go to this col next layer - carry_propogation += 1 - next_layer_size += 1 - - if (len(col) == 3): - # Only add half adder if no propogations or other adders created - if (fa_used == False and (ha_used == False or extra_ha == True) and next_layer_size == 0): - add_half_adder(reduction_layers, ha_instantiations, net_names, col, col_idx, curr_layer, prev_layer, debug) - ha_used = True - else: - fa_used = True - add_full_adder(reduction_layers, fa_instantiations, net_names, col, col_idx, curr_layer, prev_layer, debug) - - # Increment the propogation and current size - carry_propogation += 1 - next_layer_size += 1 - - if (len(col) == 2): - # Only add half adder if there is propogation from previous columns and if there is less than three in the next col, else pass through both - if (fa_used == False and (ha_used == False or extra_ha == True) and next_layer_size == 1 ): - add_half_adder(reduction_layers, ha_instantiations, net_names, col, col_idx, curr_layer, prev_layer, debug) - ha_used = True - carry_propogation += 1 - next_layer_size += 1 - else: - add_passthrough(reduction_layers, pass_instantiations, net_names, col, col_idx, curr_layer, prev_layer, debug) - add_passthrough(reduction_layers, pass_instantiations, net_names, col, col_idx, curr_layer, prev_layer, debug) - - if (len(col) == 1): - add_passthrough(reduction_layers, pass_instantiations, net_names, col, col_idx, curr_layer, prev_layer, debug) - - # Update the layer indices - prev_layer = curr_layer - curr_layer += 1 - - # Debug reduction layer print - if debug: - for col_idx, reduce in enumerate(reduction_layers[prev_layer]): - print(f"Col: {col_idx}, Length: {len(reduce)}, {reduce}") - - - # Debug final reduction layer to be added - if debug: - print("\n--------- BIT PAIRS ----------") - add_layer = list(zip(reduction_layers[prev_layer])) - add_layer.reverse() - for bit_pair in add_layer: - print(bit_pair[0]) - - # Add the two remaining rows of bits at the end - bit_vector_0 = "{ " - bit_vector_1 = "{ " - for bit_pair_idx, bit_pair in enumerate(reversed(list(zip(reduction_layers[prev_layer])))): - - # Exclude MSB if no overflows to it - if (len(bit_pair[0]) == 0 and bit_pair_idx == 0): - continue - - # Generate bit string for both vectors, order doesn't matter here - bit_vector_0 += f"{bit_pair[0][0]}, " - if (len(bit_pair[0]) == 2): - bit_vector_1 += f"{bit_pair[0][1]}, " - else: - bit_vector_1 += "1'b0, " - - bit_vector_0 = bit_vector_0[:-2] + "}" - bit_vector_1 = bit_vector_1[:-2] + "};" - - f = open(f"wallace_adder.v", "w") - - # Start by printing module declaration - f.write(f"module wallace_adder (\n") - f.write(f"\tinput logic [{bits-1}:0] partial_prod[0:{bits-1}],\n") - f.write(f"\toutput logic [{2*bits-1}:0] partial_sum\n") - f.write(");\n\n") - - # Print out net names - for net_layer in net_names: - netstring = "logic " - net_idx_len = len(net_layer) - for net_idx, net in enumerate(net_layer): - if (net_idx != net_idx_len - 1): - netstring += f"{net}, " - else: - netstring += f"{net};" - f.write(netstring + '\n') - - # Print out entire reduction tree and calculate stats - ha_count = 0 - fa_count = 0 - for layer in range(len(pass_instantiations)): - f.write(f"\n//----------- Reduction Layer {layer+1} Start --------------\n\n") - for passthrough in pass_instantiations[layer]: - f.write(passthrough + '\n') - - for half_adder in ha_instantiations[layer]: - ha_count += 1 - f.write(half_adder + '\n') - - for full_adder in fa_instantiations[layer]: - fa_count += 1 - f.write(full_adder + '\n') - - # Print final two number adder - - f.write(f"\n//----------- Adding Layer Start --------------\n\n") - f.write(f"assign partial_sum = {bit_vector_0} + {bit_vector_1}\n") - - # Endmodule - f.write("\nendmodule\n") - - f.close() - - # Print stats of the wallace adder - print(f"{ha_count} Half Adders Used") - print(f"{fa_count} Full Adders Used") - print(f"{len(pass_instantiations)-1} Reduction Layers") - -def main(): - parser = argparse.ArgumentParser(prog="Multiplier Generator", description="Generates a n bit multiplier based on the bits argument provided", - epilog="bits sets the bit width of the multiplier, the output of the multiplier is 2 times the number of bits") - parser.add_argument("bits", type=int, help="The bit width of the multiplier") - parser.add_argument("-a", "--adder", help="Generates the full and half adders for you to use", action='store_true') - parser.add_argument("-d", "--debug", help="Enables debug prints during generation scripting", action='store_true') - args = parser.parse_args() - - bits = args.bits - debug = args.debug - adder = args.adder - - if (adder): - gen_half_adder() - gen_full_adder() - - gen_multiplier(bits) - gen_partial_products(bits) - - if (gen_adder_tree(bits, debug) == -1): - return -1 - - print("----------- GENERATION COMPLETE WITHOUT ERROR ----------- \n\n") - -if __name__ == "__main__": - main() -- cgit v1.2.3