Module ariths_gen.multi_bit_circuits.approximate_adders.quad
Implementation of QuAdder
For more information, see: M. A. Hanif, R. Hafiz, O. Hasan and M. Shafique, "QuAd: Design and analysis of Quality-area optimal Low-Latency approximate Adders," 2017 54th ACM/EDAC/IEEE Design Automation Conference (DAC), Austin, TX, USA, 2017, pp. 1-6, doi: 10.1145/3061639.3062306.
Classes
class QuAdder (a, b, R, P, prefix, name='quad', adder_type=None, use_log=False, **kwargs)
-
Implementation of QuAd
<https://ieeexplore.ieee.org/document/8060326> The implementation is inspired by Matlab code from the authors of the paper: ```matlab temp_count=1; for iij=1:length(R_vect) fprintf(fileID,['wire [' num2str(R_vect(iij)+P_vect(iij)) ':0] temp' num2str(temp_count) ';
']); temp_count=temp_count + 1; end
temp_count=1; for iiij=1:length(R_vect) if (sum(R_vect(1:iiij))+P_vect(1)-1) == (sum(R_vect(1:iiij))+P_vect(1)-R_vect(iiij)-P_vect(iiij)) fprintf(fileID,['aassign temp' num2str(temp_count) '[' num2str(R_vect(iiij)+P_vect(iiij)) ':0] = in1[' num2str(sum(R_vect(1:iiij))+P_vect(1)-1) '] + in2[' num2str(sum(R_vect(1:iiij))+P_vect(1)-1) '];
']); else disp(R_vect(1:iiij)) fprintf(fileID,['bassign temp' num2str(temp_count) '[' num2str(R_vect(iiij)+P_vect(iiij)) ':0] = in1[' num2str(sum(R_vect(1:iiij))+P_vect(1)-1) ':' num2str(sum(R_vect(1:iiij))+P_vect(1)-R_vect(iiij)-P_vect(iiij)) '] + in2[' num2str(sum(R_vect(1:iiij))+P_vect(1)-1) ':' num2str(sum(R_vect(1:iiij))+P_vect(1)-R_vect(iiij)-P_vect(iiij)) ']; ']); end temp_count=temp_count+1; end
statement='};
'; temp_count=1; for iiij=1:length(R_vect) if iiij ~= length(R_vect) if (R_vect(iiij)==1) statement = [', temp' num2str(temp_count) '[' num2str(R_vect(iiij)+P_vect(iiij)-1) '] ' statement]; else statement = [', temp' num2str(temp_count) '[' num2str(R_vect(iiij)+P_vect(iiij)-1) ':' num2str(P_vect(iiij)) '] ' statement]; end else statement = ['assign res[' num2str(N) ':0] =' '{ temp' num2str(temp_count) '[' num2str(R_vect(iiij)+P_vect(iiij)) ':' num2str(P_vect(iiij)) '] ' statement]; end temp_count=temp_count+1; end ```
:param a: Bus first input :param b: Bus second input :param R: list of integers, defines the resultant bits of all the sub-adders (the first index specifies the resultant bits of sub-adder 1 and so on) :param P: list of integers, defines the prediction bits of all the sub-adders (again the first index specifies the prediction bits of sub-adder 1 and so on)
Expand source code
class QuAdder(GeneralCircuit): """ Implementation of QuAd https://ieeexplore.ieee.org/document/8060326 The implementation is inspired by Matlab code from the authors of the paper: ```matlab temp_count=1; for iij=1:length(R_vect) fprintf(fileID,['wire [' num2str(R_vect(iij)+P_vect(iij)) ':0] temp' num2str(temp_count) ';\n']); temp_count=temp_count + 1; end temp_count=1; for iiij=1:length(R_vect) if (sum(R_vect(1:iiij))+P_vect(1)-1) == (sum(R_vect(1:iiij))+P_vect(1)-R_vect(iiij)-P_vect(iiij)) fprintf(fileID,['aassign temp' num2str(temp_count) '[' num2str(R_vect(iiij)+P_vect(iiij)) ':0] = in1[' num2str(sum(R_vect(1:iiij))+P_vect(1)-1) '] + in2[' num2str(sum(R_vect(1:iiij))+P_vect(1)-1) '];\n']); else disp(R_vect(1:iiij)) fprintf(fileID,['bassign temp' num2str(temp_count) '[' num2str(R_vect(iiij)+P_vect(iiij)) ':0] = in1[' num2str(sum(R_vect(1:iiij))+P_vect(1)-1) ':' num2str(sum(R_vect(1:iiij))+P_vect(1)-R_vect(iiij)-P_vect(iiij)) '] + in2[' num2str(sum(R_vect(1:iiij))+P_vect(1)-1) ':' num2str(sum(R_vect(1:iiij))+P_vect(1)-R_vect(iiij)-P_vect(iiij)) '];\n']); end temp_count=temp_count+1; end statement='};\n'; temp_count=1; for iiij=1:length(R_vect) if iiij ~= length(R_vect) if (R_vect(iiij)==1) statement = [', temp' num2str(temp_count) '[' num2str(R_vect(iiij)+P_vect(iiij)-1) '] ' statement]; else statement = [', temp' num2str(temp_count) '[' num2str(R_vect(iiij)+P_vect(iiij)-1) ':' num2str(P_vect(iiij)) '] ' statement]; end else statement = ['assign res[' num2str(N) ':0] =' '{ temp' num2str(temp_count) '[' num2str(R_vect(iiij)+P_vect(iiij)) ':' num2str(P_vect(iiij)) '] ' statement]; end temp_count=temp_count+1; end ``` """ def log(self, *args): if self.use_log: print(*args) def __init__(self, a, b, R, P, prefix, name="quad", adder_type=None, use_log=False, **kwargs): """ :param a: Bus first input :param b: Bus second input :param R: list of integers, defines the resultant bits of all the sub-adders (the first index specifies the resultant bits of sub-adder 1 and so on) :param P: list of integers, defines the prediction bits of all the sub-adders (again the first index specifies the prediction bits of sub-adder 1 and so on) """ if not adder_type: adder_type = UnsignedRippleCarryAdder # Assumptions checks assert len(R) == len(P), "R and P must have the same length" print([P[i] < P[i-1] + R[i-1] for i in range(1, len(P))]) assert all([P[i] < P[i-1] + R[i-1] for i in range(1, len(P))] ), "Pi must be lower than Pi-1 + Ri-1" assert sum(R) == a.N, "Sum of R must be equal to number of bits" self.use_log = use_log self.N = max(a.N, b.N) super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N+1, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) self.b.bus_extend(N=self.N, prefix=b.prefix) # warnings.warn("QuAdder is not tested yet") # Connect all outputs to zero for i in range(self.N+1): self.out[i] = ConstantWireValue0() # Declaration of temporary wires (just for debug purposes) temp_count = 0 for iiij in range(0, len(R)): self.log('wire [' + str(R[iiij]+P[iiij]) + ':0] temp' + str(temp_count) + ';') temp_count = temp_count + 1 def bus_subconnect(out_bus, in_bus, out_indexes, in_indexes): out_indexes = list(out_indexes) in_indexes = list(in_indexes) assert len(out_indexes) == len(in_indexes) for i, j in zip(out_indexes, in_indexes): if j >= in_bus.N: out_bus[i] = ConstantWireValue0() # unsigned extension else: out_bus.connect(i, in_bus.get_wire(j)) # [i] = in_bus[j] # Connection of adders temp_count = 0 temp_bus = [] for iiij in range(0, len(R)): # Former verilog output self.log("assign temp{}[{}:0] = in1[{}:{}] + in2[{}:{}];".format( temp_count, R[iiij]+P[iiij], sum(R[0:iiij + 1]) + P[0]-1, sum(R[0:iiij + 1]) + P[0]-R[iiij]-P[iiij], sum(R[0:iiij + 1]) + P[0]-1, sum(R[0:iiij + 1]) + P[0]-R[iiij]-P[iiij] )) a1 = Bus(f"{prefix}_temp_{temp_count}_a", R[iiij]+P[iiij]) b1 = Bus(f"{prefix}_temp_{temp_count}_b", R[iiij]+P[iiij]) bus_subconnect(b1, self.b, range(R[iiij]+P[iiij]), range(sum(R[0:iiij + 1])+P[0]-R[iiij]-P[iiij], sum(R[0:iiij + 1])+P[0])) bus_subconnect(a1, self.a, range(R[iiij]+P[iiij]), range(sum(R[0:iiij + 1])+P[0]-R[iiij]-P[iiij], sum(R[0:iiij + 1])+P[0])) temp_bus.append(self.add_component( adder_type(a1, b1, prefix=f"{prefix}_add_{temp_count}") )) temp_count = temp_count+1 # Final connection temp_count = 0 statement = "}" wire_id = 0 for iiij in range(0, len(R)): if iiij != len(R) - 1: if R[iiij] == 1: statement = ', temp{}[{}]'.format( temp_count, R[iiij]+P[iiij] - 1) + statement else: statement = ', temp{}[{}:{}]'.format( temp_count, R[iiij]+P[iiij] - 1, P[iiij]) + statement else: statement = 'assign res[' + str(self.N) + ':0] =' + '{ temp' + str( temp_count) + '[' + str(R[iiij]+P[iiij]) + ':' + str(P[iiij]) + '] ' + statement self.log(statement) for i in range(P[iiij], R[iiij]+P[iiij]): self.log(temp_count, i, wire_id, temp_bus[temp_count].out[i]) self.out[wire_id] = temp_bus[temp_count].out[i] wire_id += 1 temp_count = temp_count+1 # Last carry (MSB) self.out[wire_id] = temp_bus[temp_count - 1].out[R[iiij]+P[iiij]]
Ancestors
Methods
def log(self, *args)
-
Expand source code
def log(self, *args): if self.use_log: print(*args)
Inherited members
GeneralCircuit
:add_component
get_blif_code_flat
get_blif_code_hier
get_c_code_flat
get_c_code_hier
get_cgp_code_flat
get_circuit_blif
get_circuit_c
get_circuit_def
get_circuit_gates
get_circuit_v
get_circuit_wire_index
get_circuit_wires
get_component_types
get_declaration_blif
get_declaration_c_flat
get_declaration_c_hier
get_declaration_v_flat
get_declaration_v_hier
get_declarations_c_hier
get_declarations_v_hier
get_function_blif_flat
get_function_block_blif
get_function_block_c
get_function_block_v
get_function_blocks_blif
get_function_blocks_c
get_function_blocks_v
get_function_out_blif
get_function_out_c_flat
get_function_out_c_hier
get_function_out_python_flat
get_function_out_v_flat
get_function_out_v_hier
get_hier_subcomponent_def
get_includes_c
get_init_c_flat
get_init_c_hier
get_init_python_flat
get_init_v_flat
get_init_v_hier
get_instance_num
get_invocation_blif_hier
get_invocations_blif_hier
get_multi_bit_components
get_one_bit_components
get_out_invocation_c
get_out_invocation_v
get_outputs_cgp
get_parameters_cgp
get_previous_component
get_prototype_blif
get_prototype_c
get_prototype_python
get_prototype_v
get_python_code_flat
get_triplets_cgp
get_unique_types
get_v_code_flat
get_v_code_hier
save_wire_id