aboutsummaryrefslogtreecommitdiff
path: root/multiplier/gen_wallace.py
diff options
context:
space:
mode:
authorfunctionpointersuss <joshua@joshuayun.com>2023-12-23 10:23:39 +0800
committerfunctionpointersuss <joshua@joshuayun.com>2023-12-23 10:23:39 +0800
commit5b04327dfa7a3005819045c9cc19e558e86d59d5 (patch)
tree7cc3ae2e9d5ed5129fcf0bc85c3d2fb600594489 /multiplier/gen_wallace.py
parentc2f4f7dad93d68d2757b86ff28c1058982c22da5 (diff)
downloadriscv-processor-5b04327dfa7a3005819045c9cc19e558e86d59d5.tar.gz
renamed to sv
Diffstat (limited to 'multiplier/gen_wallace.py')
-rwxr-xr-xmultiplier/gen_wallace.py354
1 files changed, 0 insertions, 354 deletions
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()