diff --git a/ariths_gen/core/arithmetic_circuits/__init__.py b/ariths_gen/core/arithmetic_circuits/__init__.py index 1119134..c30a209 100644 --- a/ariths_gen/core/arithmetic_circuits/__init__.py +++ b/ariths_gen/core/arithmetic_circuits/__init__.py @@ -1,10 +1,7 @@ -from .arithmetic_circuit import ( - ArithmeticCircuit, - ThreeInputArithmeticCircuit +from .general_circuit import ( + GeneralCircuit ) -from .general_circuit import (GeneralCircuit) - from .multiplier_circuit import ( MultiplierCircuit ) diff --git a/ariths_gen/core/arithmetic_circuits/arithmetic_circuit.py b/ariths_gen/core/arithmetic_circuits/arithmetic_circuit.py deleted file mode 100644 index 608550f..0000000 --- a/ariths_gen/core/arithmetic_circuits/arithmetic_circuit.py +++ /dev/null @@ -1,247 +0,0 @@ -from ariths_gen.core.logic_gate_circuits.logic_gate_circuit import OneInputLogicGate, TwoInputLogicGate - -from ariths_gen.wire_components import ( - Wire, - ConstantWireValue0, - ConstantWireValue1, - Bus -) - -from ariths_gen.core.arithmetic_circuits.general_circuit import GeneralCircuit - - -class ArithmeticCircuit(GeneralCircuit): - """Class represents a general arithmetic circuit and ensures its generation to various representations. - - The __init__ method fills some mandatory attributes concerning arithmetic circuit - that are later used for generation into various representations. - """ - - def __init__(self, a, b, prefix: str, name: str, out_N: int, inner_component: bool = False, one_bit_circuit: bool = False, signed: bool = False, **kwargs): - super().__init__(prefix, name, out_N, inner_component, inputs=[a, b], signed=signed, one_bit_circuit=one_bit_circuit, **kwargs) - - """ C CODE GENERATION """ - def get_prototype_c(self): - """Generates C code function header to describe corresponding arithmetic circuit's interface in C code. - - Returns: - str: Function's name and parameters in C code. - """ - return f"{self.c_data_type} {self.prefix}({self.c_data_type} {self.a.prefix}, {self.c_data_type} {self.b.prefix})" + "{" + "\n" - - """ VERILOG CODE GENERATION """ - def get_prototype_v(self): - """Generates Verilog code module header to describe corresponding arithmetic circuit's interface in Verilog code. - - Returns: - str: Module's name and parameters in Verilog code. - """ - return f"module {self.prefix}(input [{self.N-1}:0] {self.a.prefix}, input [{self.N-1}:0] {self.b.prefix}, output [{self.out.N-1}:0] {self.out.prefix});\n" - - """ BLIF CODE GENERATION """ - def get_declaration_blif(self): - """Generates flat Blif code declaration of input/output circuit wires. - - Returns: - str: Flat Blif code containing declaration of circuit's wires. - """ - if self.N == 1: - return f".inputs {self.a.prefix} {self.b.prefix}\n" + \ - f".outputs{self.out.get_wire_declaration_blif()}\n" + \ - f".names vdd\n1\n" + \ - f".names gnd\n0\n" - else: - return f".inputs{self.a.get_wire_declaration_blif()}{self.b.get_wire_declaration_blif()}\n" + \ - f".outputs{self.out.get_wire_declaration_blif()}\n" + \ - f".names vdd\n1\n" + \ - f".names gnd\n0\n" - - -class ThreeInputArithmeticCircuit(GeneralCircuit): - """Class represents a general three input arithmetic circuit and ensures its generation to various representations. - - The __init__ method fills some mandatory attributes concerning arithmetic circuit - that are later used for generation into various representations. - """ - - def __init__(self, a, b, c, prefix: str, name: str, out_N: int, inner_component: bool = False, one_bit_circuit: bool = False, signed: bool = False, **kwargs): - super().__init__(prefix, name, out_N, inner_component, inputs=[a, b, c], signed=signed, **kwargs) - if one_bit_circuit is False: - if prefix == "": - self.prefix = name - else: - self.prefix = prefix + "_" + name - - self.inner_component = inner_component - if self.inner_component is True: - self.a = Bus(prefix=f"{self.prefix}_{a.prefix}", wires_list=a.bus) - self.b = Bus(prefix=f"{self.prefix}_{b.prefix}", wires_list=b.bus) - self.c = Bus(prefix=f"{self.prefix}_{c.prefix}", wires_list=c.bus) - - if a.is_output_bus(): - self.a.connect_bus(connecting_bus=a) - if b.is_output_bus(): - self.b.connect_bus(connecting_bus=b) - if c.is_output_bus(): - self.c.connect_bus(connecting_bus=c) - else: - self.a = Bus(prefix=f"{a.prefix}", wires_list=a.bus) - self.b = Bus(prefix=f"{b.prefix}", wires_list=b.bus) - self.c = Bus(prefix=f"{c.prefix}", wires_list=c.bus) - - """ C CODE GENERATION """ - def get_prototype_c(self): - """Generates C code function header to describe corresponding arithmetic circuit's interface in C code. - - Returns: - str: Function's name and parameters in C code. - """ - return f"{self.c_data_type} {self.prefix}({self.c_data_type} {self.a.prefix}, {self.c_data_type} {self.b.prefix}, {self.c_data_type} {self.c.prefix})" + "{" + "\n" - - def get_function_block_c(self): - """Generates hierarchical C code representation of corresponding multi-bit arithmetic circuit used as function block in hierarchical circuit description. - - Returns: - str: Hierarchical C code of multi-bit arithmetic circuit's function block description. - """ - # Obtain proper circuit name with its bit width - circuit_prefix = self.__class__( - a=Bus("a"), b=Bus("b"), c=Bus("c")).prefix + str(self.N) - circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus( - N=self.N, prefix="b"), c=Bus( - N=self.N, prefix="c"), name=circuit_prefix, **self._parent_kwargs) - return f"{circuit_block.get_circuit_c()}\n\n" - - def get_declaration_c_hier(self): - """Generates hierarchical C code declaration of corresponding subcomponent input/output wires inside the upper component. - - Generates wires used to connect input/output values to/from invocation of the corresponding function block into inner wires present - inside the upper component from which function block has been invoked. - - Returns: - str: Hierarchical C code of subcomponent arithmetic circuit's wires declaration. - """ - return f" {self.c_data_type} {self.a.prefix} = 0;\n" + \ - f" {self.c_data_type} {self.b.prefix} = 0;\n" + \ - f" {self.c_data_type} {self.c.prefix} = 0;\n" + \ - f" {self.c_data_type} {self.out.prefix} = 0;\n" - - def get_out_invocation_c(self): - """Generates hierarchical C code invocation of corresponding arithmetic circuit's generated function block. - - Assigns input values from other subcomponents into multi-bit input buses used as inputs for function block invocation. - Assigns output values from invocation of the corresponding function block into inner wires present inside - the upper component from which function block has been invoked. - - Returns: - str: Hierarchical C code of subcomponent's C function invocation and output assignment. - """ - # Getting name of circuit type for proper C code generation without affecting actual generated composition - circuit_type = self.__class__(a=Bus("a"), b=Bus("b"), c=Bus("c")).prefix + str(self.N) - return self.a.return_bus_wires_values_c_hier() + self.b.return_bus_wires_values_c_hier() + self.c.return_bus_wires_values_c_hier() + \ - f" {self.out.prefix} = {circuit_type}({self.a.prefix}, {self.b.prefix}, {self.c.prefix});\n" - - """ VERILOG CODE GENERATION """ - def get_prototype_v(self): - """Generates Verilog code module header to describe corresponding arithmetic circuit's interface in Verilog code. - - Returns: - str: Module's name and parameters in Verilog code. - """ - return f"module {self.prefix}(input [{self.N-1}:0] {self.a.prefix}, input [{self.N-1}:0] {self.b.prefix}, input [{self.N-1}:0] {self.c.prefix}, output [{self.out.N-1}:0] {self.out.prefix});\n" - - def get_function_block_v(self): - """Generates hierarchical Verilog code representation of corresponding multi-bit arithmetic circuit used as function block in hierarchical circuit description. - - Returns: - str: Hierarchical Verilog code of multi-bit arithmetic circuit's function block description. - """ - # Obtain proper circuit name with its bit width - circuit_prefix = self.__class__( - a=Bus("a"), b=Bus("b"), c=Bus("c")).prefix + str(self.N) - circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus( - N=self.N, prefix="b"), c=Bus(N=self.N, prefix="c"), name=circuit_prefix, **self._parent_kwargs) - return f"{circuit_block.get_circuit_v()}\n\n" - - def get_declaration_v_hier(self): - """Generates hierarchical Verilog code declaration of corresponding subcomponent input/output wires inside the upper component. - - Generates wires used to connect input/output values to/from invocation of the corresponding function block into inner wires present - inside the upper component from which function block has been invoked. - - Returns: - str: Hierarchical Verilog code of subcomponent arithmetic circuit's wires declaration. - """ - return f" wire [{self.a.N-1}:0] {self.a.prefix};\n" + \ - f" wire [{self.b.N-1}:0] {self.b.prefix};\n" + \ - f" wire [{self.c.N-1}:0] {self.c.prefix};\n" + \ - f" wire [{self.out.N-1}:0] {self.out.prefix};\n" - - def get_out_invocation_v(self): - """Generates hierarchical Verilog code invocation of corresponding arithmetic circuit's generated function block. - - Assigns input values from other subcomponents into multi-bit input buses used as inputs for function block invocation. - Assigns output values from invocation of the corresponding function block into inner wires present inside - the upper component from which function block has been invoked. - - Returns: - str: Hierarchical Verilog code of subcomponent's module invocation and output assignment. - """ - # Getting name of circuit type and insitu copying out bus for proper Verilog code generation without affecting actual generated composition - circuit_type = self.__class__(a=Bus("a"), b=Bus("b"), c=Bus("c")).prefix + str(self.N) - circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus( - N=self.N, prefix="b"), c=Bus( - N=self.N, prefix="c"), name=circuit_type) - return self.a.return_bus_wires_values_v_hier() + self.b.return_bus_wires_values_v_hier() + self.c.return_bus_wires_values_v_hier() + \ - f" {circuit_type} {circuit_type}_{self.out.prefix}(.{circuit_block.a.prefix}({self.a.prefix}), .{circuit_block.b.prefix}({self.b.prefix}), .{circuit_block.c.prefix}({self.c.prefix}), .{circuit_block.out.prefix}({self.out.prefix}));\n" - - """ BLIF CODE GENERATION """ - def get_declaration_blif(self): - """Generates flat Blif code declaration of input/output circuit wires. - - Returns: - str: Flat Blif code containing declaration of circuit's wires. - """ - if self.N == 1: - return f".inputs {self.a.prefix} {self.b.prefix} {self.c.prefix}\n" + \ - f".outputs{self.out.get_wire_declaration_blif()}\n" + \ - f".names vdd\n1\n" + \ - f".names gnd\n0\n" - else: - return f".inputs{self.a.get_wire_declaration_blif()}{self.b.get_wire_declaration_blif()}{self.c.get_wire_declaration_blif()}\n" + \ - f".outputs{self.out.get_wire_declaration_blif()}\n" + \ - f".names vdd\n1\n" + \ - f".names gnd\n0\n" - - def get_invocation_blif_hier(self): - """Generates hierarchical Blif code invocation of corresponding arithmetic circuit's generated function block. - - Used for multi-bit subcomponent's modul invocation. - - Returns: - str: Hierarchical Blif code of subcomponent's model invocation and output assignment. - """ - # Getting name of circuit type for proper Blif code generation without affecting actual generated composition - circuit_type = self.__class__(a=Bus("a"), b=Bus("b"), c=Bus("c")).prefix + str(self.N) - return f"{self.a.get_wire_assign_blif(output=True)}" + \ - f"{self.b.get_wire_assign_blif(output=True)}" + \ - f"{self.c.get_wire_assign_blif(output=True)}" + \ - f".subckt {circuit_type}" + \ - "".join([f" a[{self.a.bus.index(w)}]={self.a.prefix}[{self.a.bus.index(w)}]" for w in self.a.bus]) + \ - "".join([f" b[{self.b.bus.index(w)}]={self.b.prefix}[{self.b.bus.index(w)}]" for w in self.b.bus]) + \ - "".join([f" c[{self.c.bus.index(w)}]={self.c.prefix}[{self.c.bus.index(w)}]" for w in self.c.bus]) + \ - "".join( - [f" {circuit_type}_out[{self.out.bus.index(o)}]={o.name}" for o in self.out.bus]) + "\n" - - def get_function_block_blif(self): - """Generates hierarchical Blif code representation of corresponding multi-bit arithmetic circuit used as function block in hierarchical circuit description. - - Returns: - str: Hierarchical Blif code of multi-bit arithmetic circuit's function block description. - """ - # Obtain proper circuit name with its bit width - circuit_prefix = self.__class__( - a=Bus("a"), b=Bus("b"), c=Bus("c")).prefix + str(self.N) - circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus( - N=self.N, prefix="b"), c=Bus(N=self.N, prefix="c"), name=circuit_prefix, **self._parent_kwargs) - return f"{circuit_block.get_circuit_blif()}" diff --git a/ariths_gen/core/arithmetic_circuits/general_circuit.py b/ariths_gen/core/arithmetic_circuits/general_circuit.py index bdf9df8..9feec93 100644 --- a/ariths_gen/core/arithmetic_circuits/general_circuit.py +++ b/ariths_gen/core/arithmetic_circuits/general_circuit.py @@ -1,13 +1,14 @@ -from typing import Dict -from ariths_gen.core.logic_gate_circuits.logic_gate_circuit import OneInputLogicGate, TwoInputLogicGate - +from ariths_gen.core.logic_gate_circuits.logic_gate_circuit import ( + OneInputLogicGate, + TwoInputLogicGate +) from ariths_gen.wire_components import ( Wire, - ConstantWireValue0, - ConstantWireValue1, Bus ) - +from typing import Dict +import inspect +import copy from io import StringIO @@ -17,7 +18,6 @@ class GeneralCircuit(): The __init__ method fills some mandatory attributes concerning arithmetic circuit that are later used for generation into various representations. """ - def __init__(self, prefix: str, name: str, out_N: int, inner_component: bool = False, inputs: list = [], one_bit_circuit: bool = False, signed: bool = False, outname=None, **kwargs): if prefix == "": self.prefix = name @@ -25,29 +25,19 @@ class GeneralCircuit(): self.prefix = prefix + "_" + name self.inner_component = inner_component - if one_bit_circuit is False: - # Dynamic input bus assignment - self.inputs = [] - input_names = "abcdefghijklmnopqrstuvwxyz" # This should be enough.. - assert len(input_names) >= len(inputs) - for i, input in enumerate(inputs): - attr_name = input_names[i] - full_prefix = f"{self.prefix}_{input.prefix}" if self.inner_component else f"{input.prefix}" - if isinstance(input, Bus): - bus = Bus(prefix=full_prefix, wires_list=input.bus) - setattr(self, attr_name, bus) - self.inputs.append(bus) - - # If the input bus is an output bus, connect it - if input.is_output_bus(): - getattr(self, attr_name).connect_bus(connecting_bus=input) - else: - wire = Wire(name=input.name, prefix=full_prefix) - setattr(self, attr_name, wire) - self.inputs.append(wire) - - else: - self.inputs = inputs + # Dynamic input bus assignment + self.inputs = [] + for i, input in enumerate(inputs): + attr_name = chr(97+i) + full_prefix = f"{self.prefix}_{input.prefix}" if self.inner_component else f"{input.prefix}" + if isinstance(input, Bus) or isinstance(input, Wire): + circuit_input = copy.deepcopy(input) + circuit_input.prefix = full_prefix + setattr(self, attr_name, circuit_input) + self.inputs.append(circuit_input) + # If the input bus is an output bus, connect it + if isinstance(input, Bus) and input.is_output_bus(): + getattr(self, attr_name).connect_bus(connecting_bus=input) if not outname: outname = self.prefix+"_out" @@ -75,17 +65,50 @@ class GeneralCircuit(): def __str__(self): return f"<{type(self).__name__} prefix={self.prefix} " + (", ".join([f"input={i}" for i in self.inputs])) + ">" - # super().__init__(prefix, name, out_N, inner_component, inputs=[a, b], signed=signed, **kwargs) + def get_hier_subcomponent_def(self, parent_kwargs: dict = {}): + """ Creates and returns a new instance of the current circuit block used for definition of a subcomponent in a hierarchical circuit. + + Args: + parent_kwargs (dict): Dictionary containing all the configuration settings of the parent circuit block. + + Returns: + GeneralCircuit: A new instance of the current circuit block with proper prefix and input wires. + """ + # Obtain proper circuit name with its input bit widths + init_signature = inspect.signature(self.__class__.__init__) + init_params = list(init_signature.parameters.keys()) + default_circuit_name = init_signature.parameters['name'].default + circuit_type = default_circuit_name + "x".join(str(getattr(self, chr(97+i)).N) for i, _ in enumerate(self.inputs)) + # Initialize and fill args for the new instance based on the current instance + init_args = {} + + for param in init_params[1:]: # Skip 'self' + attr = getattr(self, param, None) # Get the attribute from the current instance + + if attr is not None: # If attribute does not exist, it will use default value from the signature + if isinstance(attr, Bus): # If the input is a Bus, create a copy of the Bus object with same length, but proper prefix + init_args[param] = Bus(N=attr.N, prefix=param) + elif isinstance(attr, Wire): # If the input is a Wire, create a copy of the Wire object with proper prefix + init_args[param] = Wire(name=param) + else: # Copy other types of attributes + init_args[param] = copy.deepcopy(attr) + + init_args['name'] = circuit_type + init_args['prefix'] = "" + + circuit_block = self.__class__(**init_args, **parent_kwargs) + return circuit_block def get_circuit_def(self) -> Dict[str, Wire]: """ returns IDs and wires of the inputs and output""" - #.{circuit_block.a.prefix}({self.a.prefix}), .{circuit_block.b.prefix}({self.b.prefix}), .{circuit_block.out.prefix}({self.out.prefix}));\n" + # TODO delete? (probably replaced by get_hier_subcomponent_def) + #.{circuit_block.a.prefix}({self.a.prefix}), .{circuit_block.b.prefix}({self.b.prefix}), .{circuit_block.out.prefix}({self.out.prefix}));\n" r = {chr(97 + i): self.inputs[i] for i in range(len(self.inputs))} r['out'] = self.get_global_prefix() + "_out" return r - + def add_component(self, component): """Adds a component into list of circuit's inner subcomponents. @@ -95,7 +118,7 @@ class GeneralCircuit(): Args: component: Subcomponent to be added into list of components composing described circuit. """ - # TODO will be redone in ArithsGen rework + # TODO should be refactored in ArithsGen rework # We should probably check also wire names for especially hierarchical generation if isinstance(component, TwoInputLogicGate): if component.disable_generation is False: @@ -166,7 +189,7 @@ class GeneralCircuit(): for c in self.components: if isinstance(c, TwoInputLogicGate): continue - elif isinstance(getattr(c, 'a'), Wire): + elif all(isinstance(i, Wire) for i in self.inputs): one_bit_comps.append(c) else: one_bit_comps.extend(c.get_one_bit_components()) @@ -183,14 +206,15 @@ class GeneralCircuit(): for c in self.components: if isinstance(c, TwoInputLogicGate): continue - elif isinstance(getattr(c, 'a'), Wire): + elif all(isinstance(i, Wire) for i in self.inputs): continue else: multi_bit_comps.append(c) + multi_bit_comps.extend(c.get_multi_bit_components()) return multi_bit_comps @staticmethod - def get_unique_types(components: list, multi_bit: bool = False): + def get_unique_types(components: list, name="", multi_bit: bool = False): """Retrieves just the unique representatives of class types present inside the provided components list. Args: @@ -201,7 +225,7 @@ class GeneralCircuit(): list: List of unique composite class types. """ if multi_bit is True: - return list({(type(c), c.N): c for c in components}.values()) + return list({(type(c), tuple(i.N for i in c.inputs)): c for c in components[::-1]}.values()) else: return list({type(c): c for c in components}.values()) @@ -218,7 +242,7 @@ class GeneralCircuit(): gate_comps = self.get_unique_types(components=self.get_circuit_gates(verilog_output)) one_bit_comps = self.get_unique_types( components=self.get_one_bit_components()) - multi_bit_comps = self.get_unique_types( + multi_bit_comps = self.get_unique_types(name=self.prefix, components=self.get_multi_bit_components(), multi_bit=True) all_components = gate_comps + one_bit_comps + multi_bit_comps @@ -328,8 +352,6 @@ class GeneralCircuit(): file_object (TextIOWrapper): Destination file object where circuit's representation will be written to. """ file_object.write(self.get_prototype_python()) - # file_object.write(self.out.get_declaration_python()) - # file_object.write(self.get_declaration_python_flat()+"\n") file_object.write(self.get_init_python_flat()+"\n") file_object.write(self.get_function_out_python_flat()) file_object.write(self.out.return_bus_wires_sign_extend_python_flat()) @@ -403,8 +425,6 @@ class GeneralCircuit(): """ # Retrieve all unique component types composing this circuit and add them kwargs from the parent circuit to allow propagatation of config settings for subcomponents self.component_types = self.get_component_types() - for c in self.component_types: - c._parent_kwargs = self.kwargs return "".join([c.get_function_block_c() for c in self.component_types]) def get_function_block_c(self): @@ -413,12 +433,7 @@ class GeneralCircuit(): Returns: str: Hierarchical C code of multi-bit arithmetic circuit's function block description. """ - # Obtain proper circuit name with its bit width - circuit_prefix = self.__class__( - a=Bus("a", self.N), b=Bus("b", self.N)).prefix + str(self.N) - circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus( - N=self.N, prefix="b"), name=circuit_prefix, **self._parent_kwargs) - return f"{circuit_block.get_circuit_c()}\n\n" + return f"{self.get_hier_subcomponent_def(parent_kwargs=self.kwargs).get_circuit_c()}\n\n" def get_declarations_c_hier(self): """Generates hierarchical C code declaration of input/output circuit wires. @@ -437,9 +452,8 @@ class GeneralCircuit(): Returns: str: Hierarchical C code of subcomponent arithmetic circuit's wires declaration. """ - return f" {self.c_data_type} {self.a.prefix} = 0;\n" + \ - f" {self.c_data_type} {self.b.prefix} = 0;\n" + \ - f" {self.c_data_type} {self.out.prefix} = 0;\n" + return ";\n".join([f" {self.c_data_type} {i.prefix} = 0" for i in self.inputs]) + ";\n" + \ + f" {self.c_data_type} {self.out.prefix} = 0;\n" def get_init_c_hier(self): """Generates hierarchical C code initialization and assignment of corresponding arithmetic circuit's input/output wires. @@ -460,9 +474,12 @@ class GeneralCircuit(): str: Hierarchical C code of subcomponent's C function invocation and output assignment. """ # Getting name of circuit type for proper C code generation without affecting actual generated composition - circuit_type = self.__class__(a=Bus("a", self.N), b=Bus("b", self.N)).prefix + str(self.N) - return self.a.return_bus_wires_values_c_hier() + self.b.return_bus_wires_values_c_hier() + \ - f" {self.out.prefix} = {circuit_type}({self.a.prefix}, {self.b.prefix});\n" + init_signature = inspect.signature(self.__class__.__init__) + default_circuit_name = init_signature.parameters['name'].default + circuit_type = default_circuit_name + "x".join(str(getattr(self, chr(97+i)).N) for i, _ in enumerate(self.inputs)) + # TODO .. now only works for input buses + return "".join(w.return_bus_wires_values_c_hier() for w in self.inputs) + \ + f" {self.out.prefix} = {circuit_type}({', '.join(w.prefix if isinstance(w, Bus) else w.get_wire_value_c_hier() for w in self.inputs)});\n" def get_function_out_c_hier(self): """Generates hierarchical C code assignment of corresponding arithmetic circuit's output bus wires. @@ -499,14 +516,13 @@ class GeneralCircuit(): """ VERILOG CODE GENERATION """ # FLAT VERILOG # - def get_prototype_v(self): """Generates Verilog code module header to describe corresponding arithmetic circuit's interface in Verilog code. Returns: str: Module's name and parameters in Verilog code. """ - return f"module {self.prefix}(" + ",".join(f"input [{x.N-1}:0] {x.prefix}" for x in self.inputs) + f", output [{self.out.N-1}:0] {self.out.prefix});\n" + return f"module {self.prefix}(" + ", ".join(f"input [{x.N-1}:0] {x.prefix}" for x in self.inputs) + f", output [{self.out.N-1}:0] {self.out.prefix});\n" def get_declaration_v_flat(self): """Generates flat Verilog code declaration of input/output circuit wires. @@ -554,8 +570,6 @@ class GeneralCircuit(): """ # Retrieve all unique component types composing this circuit and add them kwargs from the parent circuit to allow propagatation of config settings for subcomponents self.component_types = self.get_component_types(verilog_output=True) - for c in self.component_types: - c._parent_kwargs = self.kwargs return "".join([c.get_function_block_v() for c in self.component_types]) def get_function_block_v(self): @@ -565,11 +579,7 @@ class GeneralCircuit(): str: Hierarchical Verilog code of multi-bit arithmetic circuit's function block description. """ # Obtain proper circuit name with its bit width - circuit_prefix = self.__class__( - a=Bus("a", self.N), b=Bus("b", self.N)).prefix + str(self.N) - circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus( - N=self.N, prefix="b"), name=circuit_prefix, **self._parent_kwargs) - return f"{circuit_block.get_circuit_v()}\n\n" + return f"{self.get_hier_subcomponent_def(parent_kwargs=self.kwargs).get_circuit_v()}\n\n" def get_declarations_v_hier(self): """Generates hierarchical Verilog code declaration of input/output circuit wires. @@ -590,10 +600,7 @@ class GeneralCircuit(): """ return "".join(w.get_wire_declaration_v() for w in self.inputs + [self.out]) + "\n" - # TODO del.. - return f" wire [{self.a.N-1}:0] {self.a.prefix};\n" + \ - f" wire [{self.b.N-1}:0] {self.b.prefix};\n" + \ - f" wire [{self.out.N-1}:0] {self.out.prefix};\n" + #return "".join(b.get_wire_declaration_v() for b in self.inputs + [self.out] if not all((w.is_const()) or (w.parent_bus is not None and w.prefix == b.prefix) for w in b.bus)) + "\n" def get_init_v_hier(self): """Generates hierarchical Verilog code initialization and assignment of corresponding arithmetic circuit's input/output wires. @@ -614,12 +621,13 @@ class GeneralCircuit(): str: Hierarchical Verilog code of subcomponent's module invocation and output assignment. """ # Getting name of circuit type and insitu copying out bus for proper Verilog code generation without affecting actual generated composition - circuit_type = self.__class__(a=Bus("a", self.N), b=Bus("b", self.N)).prefix + str(self.N) - circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus( - N=self.N, prefix="b"), name=circuit_type) + init_signature = inspect.signature(self.__class__.__init__) + default_circuit_name = init_signature.parameters['name'].default + circuit_type = default_circuit_name + "x".join(str(getattr(self, chr(97+i)).N) for i, _ in enumerate(self.inputs)) + circuit_block = self.get_hier_subcomponent_def(parent_kwargs=self.kwargs) + # TODO .. now only works for input buses return "".join([c.return_bus_wires_values_v_hier() for c in self.inputs]) + \ - f" {circuit_type} {circuit_type}_{self.out.prefix}(" + ",".join([f".{a.prefix}({b.prefix})" for a, b in zip(circuit_block.inputs, self.inputs)]) + f", .{circuit_block.out.prefix}({self.out.prefix}));\n" - #.{circuit_block.a.prefix}({self.a.prefix}), .{circuit_block.b.prefix}({self.b.prefix}), .{circuit_block.out.prefix}({self.out.prefix}));\n" + f" {circuit_type} {circuit_type}_{self.out.prefix}(" + ",".join([f".{a.prefix}({b.prefix})" for a, b in zip(circuit_block.inputs, self.inputs)]) + f", .{circuit_block.out.prefix}({self.out.prefix}));\n" def get_function_out_v_hier(self): """Generates hierarchical Verilog code assignment of corresponding arithmetic circuit's output bus wires. @@ -668,10 +676,16 @@ class GeneralCircuit(): Returns: str: Flat Blif code containing declaration of circuit's wires. """ - return f".inputs{''.join([w.get_wire_declaration_blif() for w in self.inputs])}\n" + \ - f".outputs{self.out.get_wire_declaration_blif()}\n" + \ - f".names vdd\n1\n" + \ - f".names gnd\n0\n" + if self.N == 1: + return f".inputs {' '.join([w.prefix for w in self.inputs])}\n" + \ + f".outputs{self.out.get_wire_declaration_blif()}\n" + \ + f".names vdd\n1\n" + \ + f".names gnd\n0\n" + else: + return f".inputs{''.join([w.get_wire_declaration_blif() for w in self.inputs])}\n" + \ + f".outputs{self.out.get_wire_declaration_blif()}\n" + \ + f".names vdd\n1\n" + \ + f".names gnd\n0\n" def get_function_blif_flat(self): """Generates flat Blif code with invocation of subcomponents logic gates functions via their corresponding truth tables. @@ -720,7 +734,15 @@ class GeneralCircuit(): str: Hierarchical Blif code of subcomponent's model invocation and output assignment. """ # Getting name of circuit type for proper Blif code generation without affecting actual generated composition - circuit_type = self.__class__(a=Bus("a", self.N), b=Bus("b", self.N)).prefix + str(self.N) + init_signature = inspect.signature(self.__class__.__init__) + default_circuit_name = init_signature.parameters['name'].default + circuit_type = default_circuit_name + "x".join(str(getattr(self, chr(97+i)).N) for i, _ in enumerate(self.inputs)) + return "".join([w.get_wire_assign_blif(output=True) for w in self.inputs]) + \ + f".subckt {circuit_type}" + \ + "".join([f" {chr(97+i)}[{b.bus.index(w)}]={b.prefix}[{b.bus.index(w)}]" for i, b in enumerate(self.inputs) for w in b.bus]) + \ + "".join([f" {circuit_type}_out[{self.out.bus.index(o)}]={o.name}" for o in self.out.bus]) + "\n" + + # TODO delete return f"{self.a.get_wire_assign_blif(output=True)}" + \ f"{self.b.get_wire_assign_blif(output=True)}" + \ f".subckt {circuit_type}" + \ @@ -749,8 +771,6 @@ class GeneralCircuit(): # Retrieve all unique component types composing this circuit and add them kwargs from the parent circuit to allow propagatation of config settings for subcomponents # (iterating backwards as opposed to other representations so the top modul is always above its subcomponents) self.component_types = self.get_component_types() - for c in self.component_types: - c._parent_kwargs = self.kwargs return "\n".join([c.get_function_block_blif() for c in self.component_types[::-1]]) def get_function_block_blif(self): @@ -760,11 +780,7 @@ class GeneralCircuit(): str: Hierarchical Blif code of multi-bit arithmetic circuit's function block description. """ # Obtain proper circuit name with its bit width - circuit_prefix = self.__class__( - a=Bus("a", self.N), b=Bus("b", self.N)).prefix + str(self.N) - circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus( - N=self.N, prefix="b"), name=circuit_prefix, **self._parent_kwargs) - return f"{circuit_block.get_circuit_blif()}" + return f"{self.get_hier_subcomponent_def(parent_kwargs=self.kwargs).get_circuit_blif()}" # Generating hierarchical BLIF code representation of circuit def get_blif_code_hier(self, file_object): diff --git a/ariths_gen/core/arithmetic_circuits/multiplier_circuit.py b/ariths_gen/core/arithmetic_circuits/multiplier_circuit.py index dfc0854..f939029 100644 --- a/ariths_gen/core/arithmetic_circuits/multiplier_circuit.py +++ b/ariths_gen/core/arithmetic_circuits/multiplier_circuit.py @@ -1,36 +1,24 @@ -from .arithmetic_circuit import ( - ArithmeticCircuit +from .general_circuit import ( + GeneralCircuit ) - -from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate -) - from ariths_gen.wire_components import ( - Wire, - ConstantWireValue0, - ConstantWireValue1, Bus ) - +from ariths_gen.one_bit_circuits.logic_gates import ( + AndGate, + NandGate +) import math -class MultiplierCircuit(ArithmeticCircuit): - """Class represents a general multiplier circuit derived from `ArithmeticCircuit` class. +class MultiplierCircuit(GeneralCircuit): + """Class represents a general multiplier circuit derived from `GeneralCircuit` class. - The __init__ method calls parent class __init__ method which fills some mandatory attributes concerning arithmetic circuit + The __init__ method calls parent class __init__ method which fills some mandatory attributes concerning general circuit that are later used for generation into various representations. """ - - def __init__(self, a, b, prefix: str, name: str, out_N: int, **kwargs): - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=out_N, **kwargs) + def __init__(self, prefix: str, name: str, out_N: int, inner_component: bool = False, inputs: list = [], one_bit_circuit: bool = False, signed: bool = False, outname: str = "", **kwargs): + super().__init__(prefix=prefix, name=name, out_N=out_N, inner_component=inner_component, inputs=inputs, one_bit_circuit=one_bit_circuit, signed=signed, outname=outname, **kwargs) # Array/approximate multipliers def get_previous_partial_product(self, a_index: int, b_index: int, mult_type=""): @@ -266,7 +254,7 @@ class MultiplierCircuit(ArithmeticCircuit): else: return self.columns[column][bit+1] - def update_column_wires(self, curr_column: int, adder: ArithmeticCircuit, next_column: int = 0): + def update_column_wires(self, curr_column: int, adder: GeneralCircuit, next_column: int = 0): """Provides bit height reduction of the chosen column. Inserts chosen column's top bits into an `adder` circuit to reduce its bit height. @@ -274,7 +262,7 @@ class MultiplierCircuit(ArithmeticCircuit): Args: curr_column (int): Current pp column index. - adder (ArithmeticCircuit): Two/three input one bit adder. + adder (GeneralCircuit): Two/three input one bit adder. next_column (int, optional): Subsequent pp column index. Defaults to 0. """ if hasattr(adder, "c"): diff --git a/ariths_gen/core/cgp_circuit.py b/ariths_gen/core/cgp_circuit.py index be1a6cb..a453a7a 100644 --- a/ariths_gen/core/cgp_circuit.py +++ b/ariths_gen/core/cgp_circuit.py @@ -1,5 +1,4 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, ConstantWireValue1, Bus @@ -7,14 +6,6 @@ from ariths_gen.wire_components import ( from ariths_gen.core.arithmetic_circuits import ( GeneralCircuit ) - -from ariths_gen.core.logic_gate_circuits import ( - MultipleInputLogicGate -) -from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder -) from ariths_gen.one_bit_circuits.logic_gates import ( AndGate, NandGate, diff --git a/ariths_gen/core/logic_gate_circuits/logic_gate_circuit.py b/ariths_gen/core/logic_gate_circuits/logic_gate_circuit.py index c24c2c2..38f91d8 100644 --- a/ariths_gen/core/logic_gate_circuits/logic_gate_circuit.py +++ b/ariths_gen/core/logic_gate_circuits/logic_gate_circuit.py @@ -1,4 +1,4 @@ -from ariths_gen.wire_components.wires import Wire, ConstantWireValue0, ConstantWireValue1 +from ariths_gen.wire_components.wires import Wire from ariths_gen.wire_components.buses import Bus import math diff --git a/ariths_gen/core/one_bit_circuits/four_input_one_bit_circuit.py b/ariths_gen/core/one_bit_circuits/four_input_one_bit_circuit.py index 4c8a262..b9e8eee 100644 --- a/ariths_gen/core/one_bit_circuits/four_input_one_bit_circuit.py +++ b/ariths_gen/core/one_bit_circuits/four_input_one_bit_circuit.py @@ -1,11 +1,13 @@ from .two_input_one_bit_circuit import ( TwoInputOneBitCircuit ) - +from ariths_gen.core.arithmetic_circuits import ( + GeneralCircuit +) from ariths_gen.wire_components.wires import Wire -class FourInputOneBitCircuit(TwoInputOneBitCircuit): +class FourInputOneBitCircuit(TwoInputOneBitCircuit, GeneralCircuit): """Class represents a general four input one bit circuit and implements their generation to various representations. It is derived from `TwoInputOneBitCircuit` class. Description of the __init__ method. @@ -18,13 +20,8 @@ class FourInputOneBitCircuit(TwoInputOneBitCircuit): prefix (str, optional): Prefix name of circuit. Defaults to "four_input_one_bit_circuit". """ def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), c: Wire = Wire(name="c"), d: Wire = Wire(name="d"), prefix: str = "four_input_one_bit_circuit"): - super().__init__() + GeneralCircuit.__init__(self, inputs=[a, b, c, d], prefix=prefix, name="", out_N=1) self.c_data_type = "uint8_t" - self.prefix = prefix - self.a = a - self.b = b - self.c = c - self.d = d """ C CODE GENERATION """ # FLAT C # diff --git a/ariths_gen/core/one_bit_circuits/three_input_one_bit_circuit.py b/ariths_gen/core/one_bit_circuits/three_input_one_bit_circuit.py index a552d59..5586f22 100644 --- a/ariths_gen/core/one_bit_circuits/three_input_one_bit_circuit.py +++ b/ariths_gen/core/one_bit_circuits/three_input_one_bit_circuit.py @@ -1,11 +1,13 @@ from .two_input_one_bit_circuit import ( TwoInputOneBitCircuit ) - +from ariths_gen.core.arithmetic_circuits import ( + GeneralCircuit +) from ariths_gen.wire_components.wires import Wire -class ThreeInputOneBitCircuit(TwoInputOneBitCircuit): +class ThreeInputOneBitCircuit(TwoInputOneBitCircuit, GeneralCircuit): """Class represents a general three input one bit circuit and implements their generation to various representations. It is derived from `TwoInputOneBitCircuit` class. Description of the __init__ method. @@ -17,12 +19,8 @@ class ThreeInputOneBitCircuit(TwoInputOneBitCircuit): prefix (str, optional): Prefix name of circuit. Defaults to "three_input_one_bit_circuit". """ def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), c: Wire = Wire(name="cin"), prefix: str = "three_input_one_bit_circuit"): - super().__init__() + GeneralCircuit.__init__(self, inputs=[a, b, c], prefix=prefix, name="", out_N=1) self.c_data_type = "uint8_t" - self.prefix = prefix - self.a = a - self.b = b - self.c = c """ C CODE GENERATION """ # FLAT C # diff --git a/ariths_gen/core/one_bit_circuits/two_input_one_bit_circuit.py b/ariths_gen/core/one_bit_circuits/two_input_one_bit_circuit.py index 1f81423..1d442a0 100644 --- a/ariths_gen/core/one_bit_circuits/two_input_one_bit_circuit.py +++ b/ariths_gen/core/one_bit_circuits/two_input_one_bit_circuit.py @@ -1,11 +1,11 @@ from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit + GeneralCircuit ) from ariths_gen.wire_components.wires import Wire -class TwoInputOneBitCircuit(ArithmeticCircuit): +class TwoInputOneBitCircuit(GeneralCircuit): """Class represents a general two input one bit circuit and implements their generation to various representations. It is derived from `ArithmeticCircuit` class. Description of the __init__ method. @@ -16,11 +16,8 @@ class TwoInputOneBitCircuit(ArithmeticCircuit): prefix (str, optional): Prefix name of circuit. Defaults to "two_input_one_bit_circuit". """ def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), prefix: str = "two_input_one_bit_circuit"): - super().__init__(a=a, b=b, prefix=prefix, name="", out_N=1, one_bit_circuit=True) + super().__init__(inputs=[a, b], prefix=prefix, name="", out_N=1, one_bit_circuit=True) self.c_data_type = "uint8_t" - self.prefix = prefix - self.a = a - self.b = b """ C CODE GENERATION """ # FLAT C # diff --git a/ariths_gen/multi_bit_circuits/adders/__init__.py b/ariths_gen/multi_bit_circuits/adders/__init__.py index 0ba1f34..f0ba494 100644 --- a/ariths_gen/multi_bit_circuits/adders/__init__.py +++ b/ariths_gen/multi_bit_circuits/adders/__init__.py @@ -67,4 +67,4 @@ from ariths_gen.multi_bit_circuits.adders.conditional_sum_adder import ( from ariths_gen.multi_bit_circuits.adders.carry_increment_adder import ( UnsignedCarryIncrementAdder, SignedCarryIncrementAdder -) \ No newline at end of file +) diff --git a/ariths_gen/multi_bit_circuits/adders/brent_kung_adder.py b/ariths_gen/multi_bit_circuits/adders/brent_kung_adder.py index d8bc322..5415a8e 100644 --- a/ariths_gen/multi_bit_circuits/adders/brent_kung_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/brent_kung_adder.py @@ -1,41 +1,22 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, PGSumLogic, GreyCell, BlackCell ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate -) -from ariths_gen.multi_bit_circuits.adders import ( - UnsignedCarryLookaheadAdder, - UnsignedPGRippleCarryAdder, - UnsignedRippleCarryAdder, - SignedCarryLookaheadAdder, - SignedPGRippleCarryAdder, - SignedRippleCarryAdder + XorGate ) import math -class UnsignedBrentKungAdder(ArithmeticCircuit): +class UnsignedBrentKungAdder(GeneralCircuit): """Class representing unsigned Brent-Kung adder (using valency-2 logic gates). The Brent-Kung adder belongs to a type of tree (parallel-prefix) adders. @@ -87,7 +68,7 @@ class UnsignedBrentKungAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_bka", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -155,7 +136,7 @@ class UnsignedBrentKungAdder(ArithmeticCircuit): self.generate_sig[i_wire+1].append(self.get_previous_component().get_generate_wire()) -class SignedBrentKungAdder(UnsignedBrentKungAdder, ArithmeticCircuit): +class SignedBrentKungAdder(UnsignedBrentKungAdder, GeneralCircuit): """Class representing signed Brent-Kung adder (using valency-2 logic gates). The Brent-Kung adder belongs to a type of tree (parallel-prefix) adders. diff --git a/ariths_gen/multi_bit_circuits/adders/carry_increment_adder.py b/ariths_gen/multi_bit_circuits/adders/carry_increment_adder.py index f633508..aa1ad9a 100644 --- a/ariths_gen/multi_bit_circuits/adders/carry_increment_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/carry_increment_adder.py @@ -1,13 +1,9 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, - Bus, - wires + Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.core.logic_gate_circuits import ( MultipleInputLogicGate @@ -15,21 +11,16 @@ from ariths_gen.core.logic_gate_circuits import ( from ariths_gen.one_bit_circuits.one_bit_components import ( HalfAdder, FullAdder, - FullAdderP, - TwoOneMultiplexer + FullAdderP ) from ariths_gen.one_bit_circuits.logic_gates import ( AndGate, - NandGate, OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + XorGate ) -class UnsignedCarryIncrementAdder(ArithmeticCircuit): +class UnsignedCarryIncrementAdder(GeneralCircuit): """Class representing unsigned carry increment adder. Carry increment adder represents a modified carry select adder that achieves about the same critical delay @@ -71,7 +62,7 @@ class UnsignedCarryIncrementAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, increment_block_size: int = 4, prefix: str = "", name: str = "u_cia", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -115,7 +106,7 @@ class UnsignedCarryIncrementAdder(ArithmeticCircuit): self.out.connect(self.N, cin) -class SignedCarryIncrementAdder(UnsignedCarryIncrementAdder, ArithmeticCircuit): +class SignedCarryIncrementAdder(UnsignedCarryIncrementAdder, GeneralCircuit): """Class representing signed carry increment adder. Carry increment adder represents a modified carry select adder that achieves about the same critical delay diff --git a/ariths_gen/multi_bit_circuits/adders/carry_lookahead_adder.py b/ariths_gen/multi_bit_circuits/adders/carry_lookahead_adder.py index 439286c..e4e82bc 100644 --- a/ariths_gen/multi_bit_circuits/adders/carry_lookahead_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/carry_lookahead_adder.py @@ -1,34 +1,24 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.core.logic_gate_circuits import ( MultipleInputLogicGate ) from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, - FullAdderPG, PGLogicBlock ) from ariths_gen.one_bit_circuits.logic_gates import ( AndGate, - NandGate, OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + XorGate ) -class UnsignedCarryLookaheadAdder(ArithmeticCircuit): +class UnsignedCarryLookaheadAdder(GeneralCircuit): """Class representing unsigned carry-lookahead adder. Unsigned carry-lookahead adder represents faster adder circuit which is composed @@ -67,7 +57,7 @@ class UnsignedCarryLookaheadAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, cla_block_size: int = 4, prefix: str = "", name: str = "u_cla", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -128,7 +118,7 @@ class UnsignedCarryLookaheadAdder(ArithmeticCircuit): self.out.connect(self.N, cin) -class SignedCarryLookaheadAdder(UnsignedCarryLookaheadAdder, ArithmeticCircuit): +class SignedCarryLookaheadAdder(UnsignedCarryLookaheadAdder, GeneralCircuit): """Class representing signed carry-lookahead adder. Signed carry-lookahead adder represents faster adder circuit which is composed diff --git a/ariths_gen/multi_bit_circuits/adders/carry_save_adder.py b/ariths_gen/multi_bit_circuits/adders/carry_save_adder.py index a770862..bc0be5b 100644 --- a/ariths_gen/multi_bit_circuits/adders/carry_save_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/carry_save_adder.py @@ -1,38 +1,20 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - ThreeInputArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, FullAdder ) -from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate -) from ariths_gen.multi_bit_circuits.adders import ( - UnsignedCarryLookaheadAdder, - UnsignedPGRippleCarryAdder, - UnsignedRippleCarryAdder, - SignedCarryLookaheadAdder, - SignedPGRippleCarryAdder, - SignedRippleCarryAdder + UnsignedCarryLookaheadAdder ) -class CarrySaveAdderComponent(ThreeInputArithmeticCircuit): +class CarrySaveAdderComponent(GeneralCircuit): """Class representing carry save adder component. The carry save adder component is especially useful when constructing tree multiplier architectures to reduce the propagation delay as opposed to traditional implementation of tree multipliers with half/full adders. @@ -70,7 +52,8 @@ class CarrySaveAdderComponent(ThreeInputArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, c: Bus, prefix: str = "", name: str = "csa_component", signed: bool = False, **kwargs): self.N = max(a.N, b.N, c.N) - super().__init__(a=a, b=b, c=c, prefix=prefix, name=name, out_N=(2*self.N)+2, signed=signed, **kwargs) + super().__init__(inputs=[a, b, c], prefix=prefix, name=name, out_N=(2*self.N)+2, signed=signed, **kwargs) + self.out.signed = False # CSA component has always unsigned output bus_extension_wire = ConstantWireValue1() if self.signed is True else ConstantWireValue0() self.a.bus_extend(N=self.N, prefix=a.prefix, desired_extension_wire=bus_extension_wire) @@ -94,7 +77,7 @@ class CarrySaveAdderComponent(ThreeInputArithmeticCircuit): [self.out.connect(o, self.carry_bits.get_wire(o-int(self.out.N/2))) for o in range(int(self.out.N/2), self.out.N)] -class UnsignedCarrySaveAdder(ThreeInputArithmeticCircuit): +class UnsignedCarrySaveAdder(GeneralCircuit): """Class representing unsigned carry save adder. Unsigned carry save adder represents 3 input N-bit unsigned adder which is composed of @@ -132,7 +115,7 @@ class UnsignedCarrySaveAdder(ThreeInputArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, c: Bus, prefix: str = "", name: str = "u_csa", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs): self.N = max(a.N, b.N, c.N) - super().__init__(a=a, b=b, c=c, prefix=prefix, name=name, out_N=self.N+2, **kwargs) + super().__init__(inputs=[a, b, c], prefix=prefix, name=name, out_N=self.N+2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) diff --git a/ariths_gen/multi_bit_circuits/adders/carry_select_adder.py b/ariths_gen/multi_bit_circuits/adders/carry_select_adder.py index 36c7fa4..6d97ff1 100644 --- a/ariths_gen/multi_bit_circuits/adders/carry_select_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/carry_select_adder.py @@ -1,34 +1,23 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, ConstantWireValue1, - Bus, - wires + Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit -) -from ariths_gen.core.logic_gate_circuits import ( - MultipleInputLogicGate + GeneralCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, FullAdder, TwoOneMultiplexer ) from ariths_gen.one_bit_circuits.logic_gates import ( AndGate, - NandGate, OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + XorGate ) -class UnsignedCarrySelectAdder(ArithmeticCircuit): +class UnsignedCarrySelectAdder(GeneralCircuit): """Class representing unsigned carry select adder. Carry select adder's logic is divided into a number of carry select blocks. @@ -75,7 +64,7 @@ class UnsignedCarrySelectAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, select_block_size: int = 4, prefix: str = "", name: str = "u_csla", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -125,7 +114,7 @@ class UnsignedCarrySelectAdder(ArithmeticCircuit): self.out.connect(self.N, cin) -class SignedCarrySelectAdder(UnsignedCarrySelectAdder, ArithmeticCircuit): +class SignedCarrySelectAdder(UnsignedCarrySelectAdder, GeneralCircuit): """Class representing signed carry select adder. Carry select adder's logic is divided into a number of carry select blocks. diff --git a/ariths_gen/multi_bit_circuits/adders/carry_skip_adder.py b/ariths_gen/multi_bit_circuits/adders/carry_skip_adder.py index c4ea318..938d890 100644 --- a/ariths_gen/multi_bit_circuits/adders/carry_skip_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/carry_skip_adder.py @@ -1,13 +1,9 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, - Bus, - wires + Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.core.logic_gate_circuits import ( MultipleInputLogicGate @@ -19,16 +15,11 @@ from ariths_gen.one_bit_circuits.one_bit_components import ( ) from ariths_gen.one_bit_circuits.logic_gates import ( AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + XorGate ) -class UnsignedCarrySkipAdder(ArithmeticCircuit): +class UnsignedCarrySkipAdder(GeneralCircuit): """Class representing unsigned carry skip (bypass) adder composed of smaller carry bypass blocks of chosen size to reduce propagation delay. Unsigned carry skip (bypass) adder represents faster adder circuit which is composed @@ -72,7 +63,7 @@ class UnsignedCarrySkipAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, bypass_block_size: int = 4, prefix: str = "", name: str = "u_cska", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -120,7 +111,7 @@ class UnsignedCarrySkipAdder(ArithmeticCircuit): self.out.connect(self.N, cin) -class SignedCarrySkipAdder(UnsignedCarrySkipAdder, ArithmeticCircuit): +class SignedCarrySkipAdder(UnsignedCarrySkipAdder, GeneralCircuit): """Class representing signed carry skip (bypass) adder composed of smaller carry bypass blocks of chosen size to reduce propagation delay. Signed carry skip (bypass) adder represents faster adder circuit which is composed diff --git a/ariths_gen/multi_bit_circuits/adders/conditional_sum_adder.py b/ariths_gen/multi_bit_circuits/adders/conditional_sum_adder.py index c66661d..5463294 100644 --- a/ariths_gen/multi_bit_circuits/adders/conditional_sum_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/conditional_sum_adder.py @@ -1,35 +1,22 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, ConstantWireValue1, - Bus, - wires + Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit -) -from ariths_gen.core.logic_gate_circuits import ( - MultipleInputLogicGate + GeneralCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, FullAdder, TwoOneMultiplexer ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + XorGate ) import math -class UnsignedConditionalSumAdder(ArithmeticCircuit): +class UnsignedConditionalSumAdder(GeneralCircuit): """Class representing unsigned conditional sum adder. Conditional sum adder performs carry-select addition starting with @@ -108,7 +95,7 @@ class UnsignedConditionalSumAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_cosa", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -191,7 +178,7 @@ class UnsignedConditionalSumAdder(ArithmeticCircuit): self.out.connect(self.N, self.carry_sig[i_wire+1][0][-1]) -class SignedConditionalSumAdder(UnsignedConditionalSumAdder, ArithmeticCircuit): +class SignedConditionalSumAdder(UnsignedConditionalSumAdder, GeneralCircuit): """Class representing signed conditional sum adder. Conditional sum adder performs carry-select addition starting with diff --git a/ariths_gen/multi_bit_circuits/adders/han_carlson_adder.py b/ariths_gen/multi_bit_circuits/adders/han_carlson_adder.py index c6b4b8e..6321418 100644 --- a/ariths_gen/multi_bit_circuits/adders/han_carlson_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/han_carlson_adder.py @@ -1,41 +1,22 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, PGSumLogic, GreyCell, BlackCell ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate -) -from ariths_gen.multi_bit_circuits.adders import ( - UnsignedCarryLookaheadAdder, - UnsignedPGRippleCarryAdder, - UnsignedRippleCarryAdder, - SignedCarryLookaheadAdder, - SignedPGRippleCarryAdder, - SignedRippleCarryAdder + XorGate ) import math -class UnsignedHanCarlsonAdder(ArithmeticCircuit): +class UnsignedHanCarlsonAdder(GeneralCircuit): """Class representing unsigned Han-Carlson adder (using valency-2 logic gates). The Han-Carlson adder belongs to a type of tree (parallel-prefix) adders. @@ -88,7 +69,7 @@ class UnsignedHanCarlsonAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_hca", config_choice: int = 1, **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -184,7 +165,7 @@ class UnsignedHanCarlsonAdder(ArithmeticCircuit): self.generate_sig[i_wire+1].append(self.get_previous_component().get_generate_wire()) -class SignedHanCarlsonAdder(UnsignedHanCarlsonAdder, ArithmeticCircuit): +class SignedHanCarlsonAdder(UnsignedHanCarlsonAdder, GeneralCircuit): """Class representing signed Han-Carlson adder (using valency-2 logic gates). The Han-Carlson adder belongs to a type of tree (parallel-prefix) adders. diff --git a/ariths_gen/multi_bit_circuits/adders/knowles_adder.py b/ariths_gen/multi_bit_circuits/adders/knowles_adder.py index 4f724cf..bea9e87 100644 --- a/ariths_gen/multi_bit_circuits/adders/knowles_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/knowles_adder.py @@ -1,41 +1,22 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, PGSumLogic, GreyCell, BlackCell ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate -) -from ariths_gen.multi_bit_circuits.adders import ( - UnsignedCarryLookaheadAdder, - UnsignedPGRippleCarryAdder, - UnsignedRippleCarryAdder, - SignedCarryLookaheadAdder, - SignedPGRippleCarryAdder, - SignedRippleCarryAdder + XorGate ) import math -class UnsignedKnowlesAdder(ArithmeticCircuit): +class UnsignedKnowlesAdder(GeneralCircuit): """Class representing unsigned Knowles adder (using valency-2 logic gates). The Knowles adder belongs to a type of tree (parallel-prefix) adders. @@ -88,7 +69,7 @@ class UnsignedKnowlesAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_ka", config_choice: int = 1, **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -143,7 +124,7 @@ class UnsignedKnowlesAdder(ArithmeticCircuit): self.generate_sig[i_wire+1].append(self.get_previous_component().get_generate_wire()) -class SignedKnowlesAdder(UnsignedKnowlesAdder, ArithmeticCircuit): +class SignedKnowlesAdder(UnsignedKnowlesAdder, GeneralCircuit): """Class representing signed Knowles adder (using valency-2 logic gates). The Knowles adder belongs to a type of tree (parallel-prefix) adders. diff --git a/ariths_gen/multi_bit_circuits/adders/kogge_stone_adder.py b/ariths_gen/multi_bit_circuits/adders/kogge_stone_adder.py index e3a263f..3aa7d7c 100644 --- a/ariths_gen/multi_bit_circuits/adders/kogge_stone_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/kogge_stone_adder.py @@ -1,41 +1,22 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, PGSumLogic, GreyCell, BlackCell ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate -) -from ariths_gen.multi_bit_circuits.adders import ( - UnsignedCarryLookaheadAdder, - UnsignedPGRippleCarryAdder, - UnsignedRippleCarryAdder, - SignedCarryLookaheadAdder, - SignedPGRippleCarryAdder, - SignedRippleCarryAdder + XorGate ) import math -class UnsignedKoggeStoneAdder(ArithmeticCircuit): +class UnsignedKoggeStoneAdder(GeneralCircuit): """Class representing unsigned Kogge-Stone adder (using valency-2 logic gates). The Kogge-Stone adder belongs to a type of tree (parallel-prefix) adders. @@ -86,7 +67,7 @@ class UnsignedKoggeStoneAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_ksa", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -129,7 +110,7 @@ class UnsignedKoggeStoneAdder(ArithmeticCircuit): self.generate_sig[i_wire+1].append(self.get_previous_component().get_generate_wire()) -class SignedKoggeStoneAdder(UnsignedKoggeStoneAdder, ArithmeticCircuit): +class SignedKoggeStoneAdder(UnsignedKoggeStoneAdder, GeneralCircuit): """Class representing signed Kogge-Stone adder (using valency-2 logic gates). The Kogge-Stone adder belongs to a type of tree (parallel-prefix) adders. diff --git a/ariths_gen/multi_bit_circuits/adders/ladner_fischer_adder.py b/ariths_gen/multi_bit_circuits/adders/ladner_fischer_adder.py index 68919dd..a0d170e 100644 --- a/ariths_gen/multi_bit_circuits/adders/ladner_fischer_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/ladner_fischer_adder.py @@ -1,41 +1,22 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, PGSumLogic, GreyCell, BlackCell ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate -) -from ariths_gen.multi_bit_circuits.adders import ( - UnsignedCarryLookaheadAdder, - UnsignedPGRippleCarryAdder, - UnsignedRippleCarryAdder, - SignedCarryLookaheadAdder, - SignedPGRippleCarryAdder, - SignedRippleCarryAdder + XorGate ) import math -class UnsignedLadnerFischerAdder(ArithmeticCircuit): +class UnsignedLadnerFischerAdder(GeneralCircuit): """Class representing unsigned Ladner-Fischer adder (using valency-2 logic gates). The Ladner-Fischer adder belongs to a type of tree (parallel-prefix) adders. @@ -88,7 +69,7 @@ class UnsignedLadnerFischerAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_lfa", config_choice: int = 1, **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -188,7 +169,7 @@ class UnsignedLadnerFischerAdder(ArithmeticCircuit): self.generate_sig[i_wire+1].append(self.get_previous_component().get_generate_wire()) -class SignedLadnerFischerAdder(UnsignedLadnerFischerAdder, ArithmeticCircuit): +class SignedLadnerFischerAdder(UnsignedLadnerFischerAdder, GeneralCircuit): """Class representing signed Ladner-Fischer adder (using valency-2 logic gates). The Ladner-Fischer adder belongs to a type of tree (parallel-prefix) adders. diff --git a/ariths_gen/multi_bit_circuits/adders/pg_ripple_carry_adder.py b/ariths_gen/multi_bit_circuits/adders/pg_ripple_carry_adder.py index 2a41bdf..f100019 100644 --- a/ariths_gen/multi_bit_circuits/adders/pg_ripple_carry_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/pg_ripple_carry_adder.py @@ -1,30 +1,21 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, PGSumLogic ) from ariths_gen.one_bit_circuits.logic_gates import ( AndGate, - NandGate, OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + XorGate ) -class UnsignedPGRippleCarryAdder(ArithmeticCircuit): +class UnsignedPGRippleCarryAdder(GeneralCircuit): """Class representing unsigned ripple carry adder with propagate/generate logic. Unsigned ripple carry adder with PG logic represents slightly different rca implementation @@ -69,7 +60,7 @@ class UnsignedPGRippleCarryAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_pg_rca", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -96,7 +87,7 @@ class UnsignedPGRippleCarryAdder(ArithmeticCircuit): self.out.connect(self.N, obj_or.out) -class SignedPGRippleCarryAdder(UnsignedPGRippleCarryAdder, ArithmeticCircuit): +class SignedPGRippleCarryAdder(UnsignedPGRippleCarryAdder, GeneralCircuit): """Class representing signed ripple carry adder with propagate/generate logic. Signed ripple carry adder with PG logic represents slightly different rca implementation diff --git a/ariths_gen/multi_bit_circuits/adders/ripple_carry_adder.py b/ariths_gen/multi_bit_circuits/adders/ripple_carry_adder.py index 252762b..6daf541 100644 --- a/ariths_gen/multi_bit_circuits/adders/ripple_carry_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/ripple_carry_adder.py @@ -1,29 +1,19 @@ from ariths_gen.wire_components import ( - Wire, - ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( HalfAdder, FullAdder ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + XorGate ) -class UnsignedRippleCarryAdder(ArithmeticCircuit): +class UnsignedRippleCarryAdder(GeneralCircuit): """Class representing unsigned ripple carry adder. Unsigned ripple carry adder represents N-bit unsigned adder which is composed of @@ -53,7 +43,7 @@ class UnsignedRippleCarryAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_rca", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -74,7 +64,7 @@ class UnsignedRippleCarryAdder(ArithmeticCircuit): self.out.connect(self.N, obj_adder.get_carry_wire()) -class SignedRippleCarryAdder(UnsignedRippleCarryAdder, ArithmeticCircuit): +class SignedRippleCarryAdder(UnsignedRippleCarryAdder, GeneralCircuit): """Class representing signed ripple carry adder. Signed ripple carry adder represents N-bit signed adder which is composed of diff --git a/ariths_gen/multi_bit_circuits/adders/sklansky_adder.py b/ariths_gen/multi_bit_circuits/adders/sklansky_adder.py index 84d08ff..1785627 100644 --- a/ariths_gen/multi_bit_circuits/adders/sklansky_adder.py +++ b/ariths_gen/multi_bit_circuits/adders/sklansky_adder.py @@ -1,40 +1,21 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, PGSumLogic, GreyCell, BlackCell ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate -) -from ariths_gen.multi_bit_circuits.adders import ( - UnsignedCarryLookaheadAdder, - UnsignedPGRippleCarryAdder, - UnsignedRippleCarryAdder, - SignedCarryLookaheadAdder, - SignedPGRippleCarryAdder, - SignedRippleCarryAdder + XorGate ) -class UnsignedSklanskyAdder(ArithmeticCircuit): +class UnsignedSklanskyAdder(GeneralCircuit): """Class representing unsigned Sklansky (or divide-and-conquer) adder (using valency-2 logic gates). The Sklansky adder belongs to a type of tree (parallel-prefix) adders. @@ -85,7 +66,7 @@ class UnsignedSklanskyAdder(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_sa", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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) @@ -132,7 +113,7 @@ class UnsignedSklanskyAdder(ArithmeticCircuit): prev_stage_int_value += 2**stage -class SignedSklanskyAdder(UnsignedSklanskyAdder, ArithmeticCircuit): +class SignedSklanskyAdder(UnsignedSklanskyAdder, GeneralCircuit): """Class representing signed Sklansky (or divide-and-conquer) adder (using valency-2 logic gates). The Sklansky adder belongs to a type of tree (parallel-prefix) adders. diff --git a/ariths_gen/multi_bit_circuits/approximate_adders/__init__.py b/ariths_gen/multi_bit_circuits/approximate_adders/__init__.py index 3c027b5..7b10c5c 100644 --- a/ariths_gen/multi_bit_circuits/approximate_adders/__init__.py +++ b/ariths_gen/multi_bit_circuits/approximate_adders/__init__.py @@ -1 +1 @@ -from .quad import QuAdder \ No newline at end of file +from .quad import QuAdder diff --git a/ariths_gen/multi_bit_circuits/approximate_adders/quad.py b/ariths_gen/multi_bit_circuits/approximate_adders/quad.py index 473ee09..8f8b8de 100644 --- a/ariths_gen/multi_bit_circuits/approximate_adders/quad.py +++ b/ariths_gen/multi_bit_circuits/approximate_adders/quad.py @@ -7,33 +7,20 @@ M. A. Hanif, R. Hafiz, O. Hasan and M. Shafique, "QuAd: Design and analysis of Q """ from ...wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) -from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder + +from ariths_gen.multi_bit_circuits.adders.ripple_carry_adder import ( + UnsignedRippleCarryAdder ) -from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate -) -from ariths_gen.multi_bit_circuits.adders.ripple_carry_adder import UnsignedRippleCarryAdder import warnings -class QuAdder(ArithmeticCircuit): +class QuAdder(GeneralCircuit): """ Implementation of QuAd @@ -102,13 +89,13 @@ class QuAdder(ArithmeticCircuit): self.use_log = use_log self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N+1, **kwargs) + 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") + # warnings.warn("QuAdder is not tested yet") # Connect all outputs to zero for i in range(self.N+1): @@ -128,7 +115,7 @@ class QuAdder(ArithmeticCircuit): for i, j in zip(out_indexes, in_indexes): if j >= in_bus.N: - out_bus[i] = ConstantWireValue0() # unsigned extension + out_bus[i] = ConstantWireValue0() # unsigned extension else: out_bus.connect(i, in_bus.get_wire(j)) # [i] = in_bus[j] diff --git a/ariths_gen/multi_bit_circuits/approximate_multipliers/broken_array_multiplier.py b/ariths_gen/multi_bit_circuits/approximate_multipliers/broken_array_multiplier.py index fb2177d..c3ecc9d 100644 --- a/ariths_gen/multi_bit_circuits/approximate_multipliers/broken_array_multiplier.py +++ b/ariths_gen/multi_bit_circuits/approximate_multipliers/broken_array_multiplier.py @@ -1,11 +1,8 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, MultiplierCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( @@ -13,17 +10,7 @@ from ariths_gen.one_bit_circuits.one_bit_components import ( FullAdder ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate -) -from ariths_gen.multi_bit_circuits.multipliers import ( - UnsignedArrayMultiplier, - SignedArrayMultiplier + AndGate ) @@ -107,7 +94,7 @@ class UnsignedBrokenArrayMultiplier(MultiplierCircuit): # Vertical cut should be greater or equal to horizontal cut assert vertical_cut >= horizontal_cut - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) diff --git a/ariths_gen/multi_bit_circuits/approximate_multipliers/broken_carry_save_multiplier.py b/ariths_gen/multi_bit_circuits/approximate_multipliers/broken_carry_save_multiplier.py index 141500b..910bc9c 100644 --- a/ariths_gen/multi_bit_circuits/approximate_multipliers/broken_carry_save_multiplier.py +++ b/ariths_gen/multi_bit_circuits/approximate_multipliers/broken_carry_save_multiplier.py @@ -1,11 +1,8 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, MultiplierCircuit, ) from ariths_gen.core.logic_gate_circuits import ( @@ -16,13 +13,7 @@ from ariths_gen.one_bit_circuits.one_bit_components import ( FullAdder ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + AndGate ) from ariths_gen.multi_bit_circuits.adders import ( UnsignedCarryLookaheadAdder @@ -114,7 +105,7 @@ class UnsignedBrokenCarrySaveMultiplier(MultiplierCircuit): # Vertical cut should be greater or equal to horizontal cut assert vertical_cut >= horizontal_cut - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) @@ -213,7 +204,6 @@ class UnsignedBrokenCarrySaveMultiplier(MultiplierCircuit): adder_name = unsigned_adder_class_name(a=a, b=b).prefix + str(final_cpa_N) adder_a = Bus(prefix=f"a", wires_list=previous_sums) adder_b = Bus(prefix=f"b", wires_list=previous_carries) - final_adder = unsigned_adder_class_name(a=adder_a, b=adder_b, prefix=self.prefix, name=adder_name, inner_component=True) self.add_component(final_adder) [self.out.connect(o, final_adder.out.get_wire(o-max(self.N, self.vertical_cut)), inserted_wire_desired_index=o-max(self.N, self.vertical_cut)) for o in range(max(self.N, self.vertical_cut), self.out.N)] diff --git a/ariths_gen/multi_bit_circuits/approximate_multipliers/recursive_multiplier.py b/ariths_gen/multi_bit_circuits/approximate_multipliers/recursive_multiplier.py index b5f67dc..9795bdc 100644 --- a/ariths_gen/multi_bit_circuits/approximate_multipliers/recursive_multiplier.py +++ b/ariths_gen/multi_bit_circuits/approximate_multipliers/recursive_multiplier.py @@ -11,11 +11,9 @@ from ariths_gen.one_bit_circuits.logic_gates import ( XorGate, NotGate ) - from ariths_gen.multi_bit_circuits.adders import ( UnsignedCarryLookaheadAdder ) - import math @@ -55,7 +53,7 @@ class UnsignedAccurateTwoBitMultiplier(MultiplierCircuit): def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_2bit_accm", **kwargs): self.N = max(a.N, b.N) assert self.N == 2 - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) @@ -98,14 +96,14 @@ class UnsignedApproximateTwoBitMultiplierM1(MultiplierCircuit): """Class representing unsigned two-bit approximate multiplier variant M1. M1 ax variant defined here: https://ieeexplore.ieee.org/document/8727537 - + ``` A1B1 A1B0 A0B1 A0B0 │ │ │ │ │ │ │ │ ┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐ │AND│ │AND│ │AND│ │AND│ └─┬─┘ └─┬─┘ └─┬─┘ └─┬─┘ - │ │ └┐ │ + │ │ └┐ │ │ └─────┐ │ │ └──────┐ ┌▼─▼┐ │ │ │ OR│ │ @@ -126,7 +124,7 @@ class UnsignedApproximateTwoBitMultiplierM1(MultiplierCircuit): def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_2bit_axm1", **kwargs): self.N = max(a.N, b.N) assert self.N == 2 - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) @@ -165,7 +163,7 @@ class UnsignedApproximateTwoBitMultiplierM2(MultiplierCircuit): """Class representing unsigned two-bit approximate multiplier variant M2. M2 ax variant defined here: https://ieeexplore.ieee.org/document/8727537 - + ``` A1B1 A1B0 A0B1 │ │ │ │ │ │ @@ -200,7 +198,7 @@ class UnsignedApproximateTwoBitMultiplierM2(MultiplierCircuit): def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_2bit_axm1", **kwargs): self.N = max(a.N, b.N) assert self.N == 2 - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) @@ -241,7 +239,7 @@ class UnsignedApproximateTwoBitMultiplierM3(MultiplierCircuit): """Class representing unsigned two-bit approximate multiplier variant M3. M3 ax variant defined here: https://ieeexplore.ieee.org/document/8727537 - + ``` A1B1 A1B0 A0B1 A0B0 │ │ │ │ │ │ │ │ @@ -280,7 +278,7 @@ class UnsignedApproximateTwoBitMultiplierM3(MultiplierCircuit): def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_2bit_axm3", **kwargs): self.N = max(a.N, b.N) assert self.N == 2 - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) @@ -330,7 +328,7 @@ class UnsignedApproximateTwoBitMultiplierM4(MultiplierCircuit): ┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐ │AND│ │AND│ │AND│ │AND│ └─┬─┘ └─┬─┘ └─┬─┘ └─┬─┘ - │ │ └┐ │ + │ │ └┐ │ │ └─────┐ │ │ └──────┐ ┌▼─▼┐ │ │ │XOR│ │ @@ -351,7 +349,7 @@ class UnsignedApproximateTwoBitMultiplierM4(MultiplierCircuit): def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_2bit_axm4", **kwargs): self.N = max(a.N, b.N) assert self.N == 2 - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) @@ -390,12 +388,12 @@ class UnsignedRecursiveMultiplier(MultiplierCircuit): """Class representing unsigned recursive multiplier. Input bit-vector length N can be any power of two greater than 1 (e.g. 2, 4, 8, ...). - + The internal structure of the recursive multiplier is composed of subsequent two-bit submultipliers provided in the input `submultipliers` list. The `submultipliers` list should contain the classes of the two-bit submultipliers that will be used for instantiation. If None are provided, accurate two-bit submultipliers are assumed. - + The number of submultipliers required is equal to (N/2)² for N > 2. For N = 2, only one two-bit submultiplier is required. - + Description of the __init__ method. Args: @@ -410,7 +408,7 @@ class UnsignedRecursiveMultiplier(MultiplierCircuit): def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_rm", submultipliers: list = None, unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs): self.N = max(a.N, b.N) assert self.N > 1 and self.N & (self.N-1) == 0 # assure that N is a power of two greater than 1 (So allowed N is 2, 4, 8, ..) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) @@ -424,7 +422,7 @@ class UnsignedRecursiveMultiplier(MultiplierCircuit): assert (self.N > 2 and len(submultipliers) == (self.N//2)**2) or (self.N == 2 and len(submultipliers) == 1) - if self.N == 2: # Base case for just one two-bit multiplier + if self.N == 2: # Base case for just one two-bit multiplier # TODO add suffix in ariths_gen rework mult = submultipliers[0](Bus(prefix=self.prefix + "_a", wires_list=self.a.bus), Bus(prefix=self.prefix + "_b", wires_list=self.b.bus), prefix=self.prefix + "_" + str(self.get_instance_num(cls=submultipliers[0])), **kwargs) self.add_component(mult) @@ -467,7 +465,7 @@ class UnsignedRecursiveMultiplier(MultiplierCircuit): # Create wire vectors holding partial products for final summation pp = Bus(prefix=f"pp_{m}", N=self.out.N, wires_list=[ConstantWireValue0() for _ in range(self.out.N)]) - #[pp.connect_bus(submult.out, offset=(self.out.N-4)-(a_bus_offset+b_bus_offset))] + # [pp.connect_bus(submult.out, offset=(self.out.N-4)-(a_bus_offset+b_bus_offset))] [pp.connect((self.out.N-1)-(a_bus_offset+b_bus_offset)-i, submult.out[3-i], inserted_wire_desired_index=3-i) for i in range(4)] partial_products.append(pp) diff --git a/ariths_gen/multi_bit_circuits/approximate_multipliers/truncated_array_multiplier.py b/ariths_gen/multi_bit_circuits/approximate_multipliers/truncated_array_multiplier.py index dcaa949..5a6bf8a 100644 --- a/ariths_gen/multi_bit_circuits/approximate_multipliers/truncated_array_multiplier.py +++ b/ariths_gen/multi_bit_circuits/approximate_multipliers/truncated_array_multiplier.py @@ -1,11 +1,8 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, MultiplierCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( @@ -13,13 +10,7 @@ from ariths_gen.one_bit_circuits.one_bit_components import ( FullAdder ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + AndGate ) @@ -87,7 +78,7 @@ class UnsignedTruncatedArrayMultiplier(MultiplierCircuit): # Cut level should be: 0 <= truncation_cut < N assert truncation_cut < self.N - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) diff --git a/ariths_gen/multi_bit_circuits/approximate_multipliers/truncated_carry_save_multiplier.py b/ariths_gen/multi_bit_circuits/approximate_multipliers/truncated_carry_save_multiplier.py index 0a455cf..a20f9b4 100644 --- a/ariths_gen/multi_bit_circuits/approximate_multipliers/truncated_carry_save_multiplier.py +++ b/ariths_gen/multi_bit_circuits/approximate_multipliers/truncated_carry_save_multiplier.py @@ -1,11 +1,8 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, MultiplierCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( @@ -14,12 +11,6 @@ from ariths_gen.one_bit_circuits.one_bit_components import ( ) from ariths_gen.one_bit_circuits.logic_gates import ( AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate ) from ariths_gen.multi_bit_circuits.adders import ( UnsignedCarryLookaheadAdder @@ -101,7 +92,7 @@ class UnsignedTruncatedCarrySaveMultiplier(MultiplierCircuit): # Cut level should be: 0 <= truncation_cut < N assert truncation_cut < self.N - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) diff --git a/ariths_gen/multi_bit_circuits/dividers/array_divider.py b/ariths_gen/multi_bit_circuits/dividers/array_divider.py index 946266e..32dbce7 100644 --- a/ariths_gen/multi_bit_circuits/dividers/array_divider.py +++ b/ariths_gen/multi_bit_circuits/dividers/array_divider.py @@ -1,31 +1,20 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, - ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - MultiplierCircuit + GeneralCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, TwoOneMultiplexer, FullSubtractor ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, NotGate ) -class ArrayDivider(ArithmeticCircuit): +class ArrayDivider(GeneralCircuit): """Class representing array divider. Array divider performs division between two N bit numbers and stores their @@ -96,7 +85,7 @@ class ArrayDivider(ArithmeticCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "arrdiv", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) diff --git a/ariths_gen/multi_bit_circuits/multipliers/array_multiplier.py b/ariths_gen/multi_bit_circuits/multipliers/array_multiplier.py index 38c4330..3979f17 100644 --- a/ariths_gen/multi_bit_circuits/multipliers/array_multiplier.py +++ b/ariths_gen/multi_bit_circuits/multipliers/array_multiplier.py @@ -1,11 +1,9 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, MultiplierCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( @@ -15,11 +13,8 @@ from ariths_gen.one_bit_circuits.one_bit_components import ( from ariths_gen.one_bit_circuits.logic_gates import ( AndGate, NandGate, - OrGate, NorGate, - XorGate, - XnorGate, - NotGate + XorGate ) @@ -83,7 +78,7 @@ class UnsignedArrayMultiplier(MultiplierCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_arrmul", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) @@ -190,7 +185,7 @@ class SignedArrayMultiplier(MultiplierCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_arrmul", **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, signed=True, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, signed=True, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) diff --git a/ariths_gen/multi_bit_circuits/multipliers/carry_save_multiplier.py b/ariths_gen/multi_bit_circuits/multipliers/carry_save_multiplier.py index e7d2602..8390860 100644 --- a/ariths_gen/multi_bit_circuits/multipliers/carry_save_multiplier.py +++ b/ariths_gen/multi_bit_circuits/multipliers/carry_save_multiplier.py @@ -1,11 +1,9 @@ from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, MultiplierCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( @@ -15,11 +13,7 @@ from ariths_gen.one_bit_circuits.one_bit_components import ( from ariths_gen.one_bit_circuits.logic_gates import ( AndGate, NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + NorGate ) from ariths_gen.multi_bit_circuits.adders import ( UnsignedCarryLookaheadAdder @@ -96,7 +90,7 @@ class UnsignedCarrySaveMultiplier(MultiplierCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_csamul", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) @@ -219,7 +213,7 @@ class SignedCarrySaveMultiplier(MultiplierCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_csamul", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, signed=True, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, signed=True, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) diff --git a/ariths_gen/multi_bit_circuits/multipliers/dadda_multiplier.py b/ariths_gen/multi_bit_circuits/multipliers/dadda_multiplier.py index 2da77c8..c6f9971 100644 --- a/ariths_gen/multi_bit_circuits/multipliers/dadda_multiplier.py +++ b/ariths_gen/multi_bit_circuits/multipliers/dadda_multiplier.py @@ -1,12 +1,12 @@ -from ariths_gen.multi_bit_circuits.adders.carry_lookahead_adder import UnsignedCarryLookaheadAdder +from ariths_gen.multi_bit_circuits.adders.carry_lookahead_adder import ( + UnsignedCarryLookaheadAdder +) from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, MultiplierCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( @@ -14,13 +14,7 @@ from ariths_gen.one_bit_circuits.one_bit_components import ( FullAdder ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + XorGate ) @@ -50,7 +44,7 @@ class UnsignedDaddaMultiplier(MultiplierCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_dadda_cla", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) @@ -154,7 +148,7 @@ class SignedDaddaMultiplier(MultiplierCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_dadda_cla", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, signed=True, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, signed=True, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) diff --git a/ariths_gen/multi_bit_circuits/multipliers/wallace_multiplier.py b/ariths_gen/multi_bit_circuits/multipliers/wallace_multiplier.py index 24ba4ad..6cf165a 100644 --- a/ariths_gen/multi_bit_circuits/multipliers/wallace_multiplier.py +++ b/ariths_gen/multi_bit_circuits/multipliers/wallace_multiplier.py @@ -1,12 +1,12 @@ -from ariths_gen.multi_bit_circuits.adders.carry_lookahead_adder import UnsignedCarryLookaheadAdder +from ariths_gen.multi_bit_circuits.adders.carry_lookahead_adder import ( + UnsignedCarryLookaheadAdder +) from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, ConstantWireValue1, Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, MultiplierCircuit ) from ariths_gen.one_bit_circuits.one_bit_components import ( @@ -14,13 +14,7 @@ from ariths_gen.one_bit_circuits.one_bit_components import ( FullAdder ) from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + XorGate ) from ariths_gen.multi_bit_circuits.adders import ( CarrySaveAdderComponent, @@ -86,7 +80,7 @@ class UnsignedWallaceMultiplier(MultiplierCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_wallace_cla", use_csa: bool = True, unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) @@ -249,7 +243,7 @@ class SignedWallaceMultiplier(MultiplierCircuit): """ def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_wallace_cla", use_csa: bool = True, unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs): self.N = max(a.N, b.N) - super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, signed=True, **kwargs) + super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N*2, signed=True, **kwargs) # Bus sign extension in case buses have different lengths self.a.bus_extend(N=self.N, prefix=a.prefix) diff --git a/ariths_gen/multi_bit_circuits/others/bit_reduce.py b/ariths_gen/multi_bit_circuits/others/bit_reduce.py index 9752c67..2cabd83 100644 --- a/ariths_gen/multi_bit_circuits/others/bit_reduce.py +++ b/ariths_gen/multi_bit_circuits/others/bit_reduce.py @@ -1,53 +1,25 @@ -""" - -""" - from ariths_gen.wire_components import ( - Wire, - ConstantWireValue0, - ConstantWireValue1, - Bus, - wires + Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - GeneralCircuit, - MultiplierCircuit -) -from ariths_gen.core.logic_gate_circuits import ( - MultipleInputLogicGate -) -from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, - FullAdderP, - TwoOneMultiplexer + GeneralCircuit ) from ariths_gen.one_bit_circuits.logic_gates import ( AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate + OrGate +) +from ariths_gen.core.logic_gate_circuits import ( + TwoInputLogicGate ) -from ariths_gen.core.logic_gate_circuits import TwoInputLogicGate, TwoInputInvertedLogicGate, OneInputLogicGate -from ariths_gen.multi_bit_circuits.adders import UnsignedRippleCarryAdder - -from math import log2, ceil class BitReduce(GeneralCircuit): """Class representing tree reducer circuit. Doent work for NAND gate! """ - def __init__(self, a: Bus, gate : TwoInputLogicGate, prefix : str = "", name : str = "bitreduce", **kwargs): + def __init__(self, a: Bus, gate: TwoInputLogicGate, prefix: str = "", name: str = "bitreduce", **kwargs): self.N = a.N - self.a = a - - outc = 1 - super().__init__(name=name, prefix=prefix, inputs = [self.a], out_N=outc) + super().__init__(name=name, prefix=prefix, inputs=[a], out_N=1, **kwargs) # tree reduction def create_tree(a: Bus, depth: int, branch="A"): diff --git a/ariths_gen/multi_bit_circuits/others/compare.py b/ariths_gen/multi_bit_circuits/others/compare.py index ab89fd1..0c252ec 100644 --- a/ariths_gen/multi_bit_circuits/others/compare.py +++ b/ariths_gen/multi_bit_circuits/others/compare.py @@ -1,43 +1,20 @@ -""" - -""" - from ariths_gen.wire_components import ( - Wire, ConstantWireValue0, ConstantWireValue1, - Bus, - wires + Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - GeneralCircuit, - MultiplierCircuit -) - -from ariths_gen.core.logic_gate_circuits import ( - MultipleInputLogicGate -) -from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, - FullAdderP, - TwoOneMultiplexer + GeneralCircuit ) from ariths_gen.one_bit_circuits.logic_gates import ( AndGate, - NandGate, - OrGate, - NorGate, - XorGate, XnorGate, NotGate ) +from ariths_gen.multi_bit_circuits.others import ( + OrReduce +) -from ariths_gen.multi_bit_circuits.others import OrReduce - - -from math import log2, ceil class UnsignedCompareLT(GeneralCircuit): """Class representing unsigned compare @@ -47,12 +24,8 @@ class UnsignedCompareLT(GeneralCircuit): """ def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_lt", **kwargs): - self.a = a - self.b = b self.N = max(a.N, b.N) - - super().__init__(name=name, prefix=prefix, - inputs = [self.a, self.b], out_N=1) + super().__init__(name=name, prefix=prefix, inputs=[a, b], out_N=1) # create wires psum = ConstantWireValue1() @@ -84,12 +57,8 @@ class UnsignedCompareLTE(GeneralCircuit): """ def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_lte", **kwargs): - self.a = a - self.b = b self.N = max(a.N, b.N) - - super().__init__(name=name, prefix=prefix, - inputs = [self.a, self.b], out_N=1) + super().__init__(name=name, prefix=prefix, inputs=[a, b], out_N=1) # create wires psum = ConstantWireValue1() @@ -125,12 +94,8 @@ class UnsignedCompareGT(GeneralCircuit): """ def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_gt", **kwargs): - self.a = a - self.b = b self.N = max(a.N, b.N) - - super().__init__(name=name, prefix=prefix, - inputs = [self.a, self.b], out_N=1) + super().__init__(name=name, prefix=prefix, inputs=[a, b], out_N=1) # create wires psum = ConstantWireValue1() @@ -162,12 +127,8 @@ class UnsignedCompareGTE(GeneralCircuit): """ def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_gte", **kwargs): - self.a = a - self.b = b self.N = max(a.N, b.N) - - super().__init__(name=name, prefix=prefix, - inputs = [self.a, self.b], out_N=1) + super().__init__(name=name, prefix=prefix, inputs=[a, b], out_N=1) # create wires psum = ConstantWireValue1() diff --git a/ariths_gen/multi_bit_circuits/others/popcount.py b/ariths_gen/multi_bit_circuits/others/popcount.py index 16fd141..000cae1 100644 --- a/ariths_gen/multi_bit_circuits/others/popcount.py +++ b/ariths_gen/multi_bit_circuits/others/popcount.py @@ -1,43 +1,17 @@ -""" - -""" -from typing import Union, Optional - from ariths_gen.wire_components import ( - Wire, - ConstantWireValue0, - ConstantWireValue1, - Bus, - wires + Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, GeneralCircuit, - MultiplierCircuit + GeneralCircuit ) -from ariths_gen.core.logic_gate_circuits import ( - MultipleInputLogicGate +from ariths_gen.multi_bit_circuits.adders import ( + UnsignedRippleCarryAdder ) -from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, - FullAdderP, - TwoOneMultiplexer -) -from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate -) - -from ariths_gen.multi_bit_circuits.adders import UnsignedRippleCarryAdder - +from typing import Optional from math import log2, ceil + class UnsignedPopCount(GeneralCircuit): """Class representing unsigned popcount circuit. @@ -45,14 +19,11 @@ class UnsignedPopCount(GeneralCircuit): """ - def __init__(self, a: Bus, adder : Optional[ArithmeticCircuit] = None, prefix : str = "", name : str = "popcnt", **kwargs): + def __init__(self, a: Bus, adder : Optional[GeneralCircuit] = None, prefix : str = "", name : str = "popcnt", **kwargs): self.N = a.N - self.a = a - outc = ceil(log2(self.N + 1)) #print("outc", outc) - super().__init__(name=name, prefix=prefix, inputs = [self.a], out_N=outc) - + super().__init__(name=name, prefix=prefix, inputs=[a], out_N=outc) self.a.bus_extend(2**(outc - 1), prefix=a.prefix) #print(self.a) @@ -62,7 +33,6 @@ class UnsignedPopCount(GeneralCircuit): # tree reduction def create_tree(a: Bus, depth: int, branch="A"): - #print(a) if a.N == 1: return a @@ -70,17 +40,17 @@ class UnsignedPopCount(GeneralCircuit): half = a.N // 2 b_in = Bus(N=half, prefix=f"b_inn_{branch}_{depth}A") c_in = Bus(N=a.N - half, prefix=f"b_inn_{branch}_{depth}B") + #print(b_in.prefix) #print(a, half, a.N) - - for i, j in enumerate(range(half)): b_in[i] = a[j] - for i, j in enumerate(range(half, a.N)): c_in[i] = a[j] b = create_tree(b_in, depth=depth + 1, branch = branch + "A") - c = create_tree(c_in, depth= depth + 1, branch = branch + "B") + c = create_tree(c_in, depth=depth + 1, branch = branch + "B") + + d = self.adder(a=b, b=c, prefix = f"{self.prefix}_add{branch}_{depth}") self.add_component(d) return d.out diff --git a/ariths_gen/multi_bit_circuits/others/popcount_compare.py b/ariths_gen/multi_bit_circuits/others/popcount_compare.py index 6b8570d..f9a6b20 100644 --- a/ariths_gen/multi_bit_circuits/others/popcount_compare.py +++ b/ariths_gen/multi_bit_circuits/others/popcount_compare.py @@ -1,45 +1,15 @@ -""" - -""" - -from ariths_gen.multi_bit_circuits.others import UnsignedPopCount -from ariths_gen.multi_bit_circuits.others.compare import UnsignedCompareGTE from ariths_gen.wire_components import ( - Wire, - ConstantWireValue0, - ConstantWireValue1, - Bus, - wires + Bus ) from ariths_gen.core.arithmetic_circuits import ( - ArithmeticCircuit, - GeneralCircuit, - MultiplierCircuit + GeneralCircuit ) -from ariths_gen.core.logic_gate_circuits import ( - MultipleInputLogicGate -) -from ariths_gen.one_bit_circuits.one_bit_components import ( - HalfAdder, - FullAdder, - FullAdderP, - TwoOneMultiplexer -) -from ariths_gen.one_bit_circuits.logic_gates import ( - AndGate, - NandGate, - OrGate, - NorGate, - XorGate, - XnorGate, - NotGate +from ariths_gen.multi_bit_circuits.others import ( + UnsignedPopCount, + UnsignedCompareGTE ) -from ariths_gen.multi_bit_circuits.others import OrReduce - - -from math import log2, ceil class PopCountCompare(GeneralCircuit): """Class representing a circiut @@ -60,22 +30,21 @@ class PopCountCompare(GeneralCircuit): """ def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "popcnt_cmp", **kwargs): - self.a = a - self.b = b - - super().__init__(name=name, prefix=prefix, - inputs = [self.a, self.b], out_N=1) + super().__init__(name=name, prefix=prefix, inputs=[a, b], out_N=1, **kwargs) - p1 = self.add_component(UnsignedPopCount(self.a, + p1 = self.add_component(UnsignedPopCount(a=Bus(wires_list=self.a.bus, prefix=f"{prefix}_popcount1_a"), prefix=f"{prefix}_popcount1", inner_component=True)).out - p2 = self.add_component(UnsignedPopCount(self.b, + p2 = self.add_component(UnsignedPopCount(a=Bus(wires_list=self.b.bus, prefix=f"{prefix}_popcount2_a"), prefix=f"{prefix}_popcount2", inner_component=True)).out - + print(p1) #N = max(p1.N, p2.N) #p1.bus_extend(N) #p2.bus_extend(N) - - red = self.add_component(UnsignedCompareGTE(p1, p2, prefix=f"{prefix}_cmp", inner_component = True)) + cmp_gte_a = Bus(wires_list=p1.bus, prefix=f"{prefix}_cmp_gte_a") + cmp_gte_a.connect_bus(p1) + cmp_gte_b = Bus(wires_list=p2.bus, prefix=f"{prefix}_cmp_gte_b") + cmp_gte_b.connect_bus(p2) + red = self.add_component(UnsignedCompareGTE(cmp_gte_a, cmp_gte_b, prefix=f"{prefix}_cmp", inner_component = True)) self.out.connect_bus(red.out) diff --git a/ariths_gen/wire_components/wires.py b/ariths_gen/wire_components/wires.py index 6c8f993..de1a653 100644 --- a/ariths_gen/wire_components/wires.py +++ b/ariths_gen/wire_components/wires.py @@ -74,7 +74,7 @@ class Wire(): return f"({self.c_const})" # If wire is part of an input bus (where wire names are concatenated from bus prefix and their index position inside the bus in square brackets) # then the wire value is obtained from bitwise shifting the required wire from the parent bus ('parent_bus.prefix' is the same value as 'self.prefix') - elif self.is_buswire(): + elif self.is_buswire() and self.name == f"{self.prefix}[{self.index}]": return f"(({self.prefix} >> {self.index}) & 0x01)" else: return f"(({self.name} >> 0) & 0x01)" diff --git a/generate_mac.py b/generate_mac.py index 68afed3..8d68437 100644 --- a/generate_mac.py +++ b/generate_mac.py @@ -1,9 +1,8 @@ -from ariths_gen.core.arithmetic_circuits.arithmetic_circuit import ArithmeticCircuit from ariths_gen.core.arithmetic_circuits import GeneralCircuit from ariths_gen.wire_components import Bus, Wire from ariths_gen.multi_bit_circuits.adders import UnsignedRippleCarryAdder -from ariths_gen.multi_bit_circuits.multipliers import UnsignedArrayMultiplier, UnsignedDaddaMultiplier +from ariths_gen.multi_bit_circuits.multipliers import UnsignedArrayMultiplier import os diff --git a/tests/test_ax.py b/tests/test_ax.py index a833fe7..1042576 100644 --- a/tests/test_ax.py +++ b/tests/test_ax.py @@ -8,13 +8,8 @@ DIR_PATH = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, os.path.join(DIR_PATH, '..')) import numpy as np import itertools - -from ariths_gen.core.arithmetic_circuits.arithmetic_circuit import ArithmeticCircuit -from ariths_gen.core.arithmetic_circuits import GeneralCircuit -from ariths_gen.wire_components import Bus, Wire -from ariths_gen.multi_bit_circuits.adders import UnsignedRippleCarryAdder +from ariths_gen.wire_components import Bus from ariths_gen.multi_bit_circuits.approximate_adders import QuAdder -from ariths_gen.multi_bit_circuits.multipliers import UnsignedArrayMultiplier, UnsignedDaddaMultiplier def test_quadder():