From 717e7a720dddeb8d5131a1cdad31e8eaf1e995b3 Mon Sep 17 00:00:00 2001 From: mrazekv Date: Thu, 13 Jan 2022 15:18:39 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20ehw-fit/?= =?UTF-8?q?ariths-gen@d445f9e3c7944c5424ce14fa3b8fc01d2ed646a4=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/arithmetic_circuits/general_circuit.html | 70 +- .../multiplier_circuit.html | 89 +- index.html | 10 +- .../adders/carry_lookahead_adder.html | 4 +- .../adders/pg_ripple_carry_adder.html | 4 +- .../broken_array_multiplier.html | 1000 +++++++++++++++++ .../approximate_multipliers/index.html | 84 ++ .../truncated_multiplier.html | 885 +++++++++++++++ multi_bit_circuits/index.html | 5 + .../multipliers/array_multiplier.html | 4 +- .../three_input_one_bit_components.html | 146 ++- .../two_input_one_bit_components.html | 140 ++- pdk.html | 103 ++ wire_components/buses.html | 30 +- 14 files changed, 2510 insertions(+), 64 deletions(-) create mode 100644 multi_bit_circuits/approximate_multipliers/broken_array_multiplier.html create mode 100644 multi_bit_circuits/approximate_multipliers/index.html create mode 100644 multi_bit_circuits/approximate_multipliers/truncated_multiplier.html create mode 100644 pdk.html diff --git a/core/arithmetic_circuits/general_circuit.html b/core/arithmetic_circuits/general_circuit.html index 49e0318..6108216 100644 --- a/core/arithmetic_circuits/general_circuit.html +++ b/core/arithmetic_circuits/general_circuit.html @@ -155,16 +155,20 @@ class GeneralCircuit(): return multi_bit_comps @staticmethod - def get_unique_types(components: list): + def get_unique_types(components: list, multi_bit: bool = False): """Retrieves just the unique representatives of class types present inside the provided components list. Args: components (list): List of components to be filtered. + multi_bit (bool): Specifies whether the provided components list is composed of multi bit type circuits. Defaults to False. Returns: list: List of unique composite class types. """ - return list({type(c): c for c in components}.values()) + if multi_bit is True: + return list({(type(c), c.N): c for c in components}.values()) + else: + return list({type(c): c for c in components}.values()) def get_component_types(self): """Retrieves a list of all the unique types of subcomponents composing the circuit. @@ -178,7 +182,7 @@ class GeneralCircuit(): one_bit_comps = self.get_unique_types( components=self.get_one_bit_components()) multi_bit_comps = self.get_unique_types( - components=self.get_multi_bit_components()) + components=self.get_multi_bit_components(), multi_bit=True) all_components = gate_comps + one_bit_comps + multi_bit_comps return all_components @@ -435,7 +439,7 @@ 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.prefix.replace(circuit_prefix+"_", "") + circuit_type = self.__class__(a=Bus("a"), b=Bus("b")).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" @@ -587,13 +591,9 @@ 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.prefix.replace(circuit_prefix+"_", "") - - # Obtain proper circuit name with its bit width - circuit_prefix = self.__class__( - a=Bus("a"), b=Bus("b")).prefix + str(self.N) + circuit_type = self.__class__(a=Bus("a"), b=Bus("b")).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) + N=self.N, prefix="b"), name=circuit_type) return self.a.return_bus_wires_values_v_hier() + self.b.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.out.prefix}({self.out.prefix}));\n" @@ -699,7 +699,7 @@ 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.prefix.replace(circuit_prefix+"_", "") + circuit_type = self.__class__(a=Bus("a"), b=Bus("b")).prefix + str(self.N) return f"{self.a.get_wire_assign_blif(output=True)}" + \ f"{self.b.get_wire_assign_blif(output=True)}" + \ f".subckt {circuit_type}" + \ @@ -945,16 +945,20 @@ that are later used for generation into various representations.

return multi_bit_comps @staticmethod - def get_unique_types(components: list): + def get_unique_types(components: list, multi_bit: bool = False): """Retrieves just the unique representatives of class types present inside the provided components list. Args: components (list): List of components to be filtered. + multi_bit (bool): Specifies whether the provided components list is composed of multi bit type circuits. Defaults to False. Returns: list: List of unique composite class types. """ - return list({type(c): c for c in components}.values()) + if multi_bit is True: + return list({(type(c), c.N): c for c in components}.values()) + else: + return list({type(c): c for c in components}.values()) def get_component_types(self): """Retrieves a list of all the unique types of subcomponents composing the circuit. @@ -968,7 +972,7 @@ that are later used for generation into various representations.

one_bit_comps = self.get_unique_types( components=self.get_one_bit_components()) multi_bit_comps = self.get_unique_types( - components=self.get_multi_bit_components()) + components=self.get_multi_bit_components(), multi_bit=True) all_components = gate_comps + one_bit_comps + multi_bit_comps return all_components @@ -1225,7 +1229,7 @@ that are later used for generation into various representations.

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.prefix.replace(circuit_prefix+"_", "") + circuit_type = self.__class__(a=Bus("a"), b=Bus("b")).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" @@ -1377,13 +1381,9 @@ that are later used for generation into various representations.

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.prefix.replace(circuit_prefix+"_", "") - - # Obtain proper circuit name with its bit width - circuit_prefix = self.__class__( - a=Bus("a"), b=Bus("b")).prefix + str(self.N) + circuit_type = self.__class__(a=Bus("a"), b=Bus("b")).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) + N=self.N, prefix="b"), name=circuit_type) return self.a.return_bus_wires_values_v_hier() + self.b.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.out.prefix}({self.out.prefix}));\n" @@ -1489,7 +1489,7 @@ that are later used for generation into various representations.

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.prefix.replace(circuit_prefix+"_", "") + circuit_type = self.__class__(a=Bus("a"), b=Bus("b")).prefix + str(self.N) return f"{self.a.get_wire_assign_blif(output=True)}" + \ f"{self.b.get_wire_assign_blif(output=True)}" + \ f".subckt {circuit_type}" + \ @@ -1626,7 +1626,7 @@ def get_includes_c():
-def get_unique_types(components: list) +def get_unique_types(components: list, multi_bit: bool = False)

Retrieves just the unique representatives of class types present inside the provided components list.

@@ -1634,6 +1634,8 @@ def get_includes_c():
components : list
List of components to be filtered.
+
multi_bit : bool
+
Specifies whether the provided components list is composed of multi bit type circuits. Defaults to False.

Returns

@@ -1645,16 +1647,20 @@ def get_includes_c(): Expand source code
@staticmethod
-def get_unique_types(components: list):
+def get_unique_types(components: list, multi_bit: bool = False):
     """Retrieves just the unique representatives of class types present inside the provided components list.
 
     Args:
         components (list): List of components to be filtered.
+        multi_bit (bool): Specifies whether the provided components list is composed of multi bit type circuits. Defaults to False.
 
     Returns:
         list: List of unique composite class types.
     """
-    return list({type(c): c for c in components}.values())
+ if multi_bit is True: + return list({(type(c), c.N): c for c in components}.values()) + else: + return list({type(c): c for c in components}.values())
@@ -2062,7 +2068,7 @@ Other wires indexes start counting from 2 and up.

one_bit_comps = self.get_unique_types( components=self.get_one_bit_components()) multi_bit_comps = self.get_unique_types( - components=self.get_multi_bit_components()) + components=self.get_multi_bit_components(), multi_bit=True) all_components = gate_comps + one_bit_comps + multi_bit_comps return all_components @@ -2750,7 +2756,7 @@ inside the upper component from which function block has been invoked.

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.prefix.replace(circuit_prefix+"_", "") + circuit_type = self.__class__(a=Bus("a"), b=Bus("b")).prefix + str(self.N) return f"{self.a.get_wire_assign_blif(output=True)}" + \ f"{self.b.get_wire_assign_blif(output=True)}" + \ f".subckt {circuit_type}" + \ @@ -2882,7 +2888,7 @@ the upper component from which function block has been invoked.

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.prefix.replace(circuit_prefix+"_", "") + circuit_type = self.__class__(a=Bus("a"), b=Bus("b")).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" @@ -2923,13 +2929,9 @@ the upper component from which function block has been invoked.

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.prefix.replace(circuit_prefix+"_", "") - - # Obtain proper circuit name with its bit width - circuit_prefix = self.__class__( - a=Bus("a"), b=Bus("b")).prefix + str(self.N) + circuit_type = self.__class__(a=Bus("a"), b=Bus("b")).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) + N=self.N, prefix="b"), name=circuit_type) return self.a.return_bus_wires_values_v_hier() + self.b.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.out.prefix}({self.out.prefix}));\n" diff --git a/core/arithmetic_circuits/multiplier_circuit.html b/core/arithmetic_circuits/multiplier_circuit.html index 47c1bd9..3512e2a 100644 --- a/core/arithmetic_circuits/multiplier_circuit.html +++ b/core/arithmetic_circuits/multiplier_circuit.html @@ -57,22 +57,43 @@ class MultiplierCircuit(ArithmeticCircuit): that are later used for generation into various representations. """ - def __init__(self, a, b, prefix, name, out_N, **kwargs): + 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) # Array multipliers - def get_previous_partial_product(self, a_index: int, b_index: int): + def get_previous_partial_product(self, a_index: int, b_index: int, mult_type=""): """Used in array multipliers to get previous row's component output wires for further connection to another component's input. Args: a_index (int): First input wire index. b_index (int): Second input wire index. + mult_type (string, optional): Specifies what type of multiplier circuit has called this method. It is used for proper retrieval of index into the components list to allow appropriate interconnection of the multiplier circuit's inner subcomponents. It expects "" for ordinary multipliers, `bam` or `tm` for specific approximate multipliers. Defaults to "". Returns: Wire: Previous row's component wire of corresponding pp. """ # To get the index of previous row's connecting adder and its generated pp - index = ((b_index-2) * (self.N*2)) + ((self.N-1)+2*(a_index+2)) + if mult_type == "bam": + #TODO alter to be more compact + ids_sum = 0 + for row in range(self.horizontal_cut + self.ommited_rows, b_index): + first_row_elem_id = self.vertical_cut-row if self.vertical_cut-row > 0 else 0 + # First pp row composed just from gates + if row == self.horizontal_cut + self.ommited_rows: + # Minus one because the first component has index 0 instead of 1 + ids_sum += sum([1 for gate_pos in range(first_row_elem_id, self.N)])-1 + elif row == b_index-1: + ids_sum += sum([2 for gate_adder_pos in range(first_row_elem_id, self.N) if gate_adder_pos <= a_index+1]) + else: + ids_sum += sum([2 for gate_adder_pos in range(first_row_elem_id, self.N)]) + # Index calculation should be redone, but it works even this way + index = ids_sum+2 if a_index == self.N-1 else ids_sum + elif mult_type == "tm": + index = ((b_index-self.truncation_cut-2) * ((self.N-self.truncation_cut)*2)) + ((self.N-self.truncation_cut-1)+2*(a_index-self.truncation_cut+2)) + else: + index = ((b_index-2) * ((self.N)*2)) + ((self.N-1)+2*(a_index+2)) + + # Get carry wire as input for the last adder in current row if a_index == self.N-1: @@ -266,7 +287,7 @@ class MultiplierCircuit(ArithmeticCircuit):
class MultiplierCircuit -(a, b, prefix, name, out_N, **kwargs) +(a, b, prefix: str, name: str, out_N: int, **kwargs)

Class represents a general multiplier circuit derived from ArithmeticCircuit class.

@@ -283,22 +304,43 @@ that are later used for generation into various representations.

that are later used for generation into various representations. """ - def __init__(self, a, b, prefix, name, out_N, **kwargs): + 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) # Array multipliers - def get_previous_partial_product(self, a_index: int, b_index: int): + def get_previous_partial_product(self, a_index: int, b_index: int, mult_type=""): """Used in array multipliers to get previous row's component output wires for further connection to another component's input. Args: a_index (int): First input wire index. b_index (int): Second input wire index. + mult_type (string, optional): Specifies what type of multiplier circuit has called this method. It is used for proper retrieval of index into the components list to allow appropriate interconnection of the multiplier circuit's inner subcomponents. It expects "" for ordinary multipliers, `bam` or `tm` for specific approximate multipliers. Defaults to "". Returns: Wire: Previous row's component wire of corresponding pp. """ # To get the index of previous row's connecting adder and its generated pp - index = ((b_index-2) * (self.N*2)) + ((self.N-1)+2*(a_index+2)) + if mult_type == "bam": + #TODO alter to be more compact + ids_sum = 0 + for row in range(self.horizontal_cut + self.ommited_rows, b_index): + first_row_elem_id = self.vertical_cut-row if self.vertical_cut-row > 0 else 0 + # First pp row composed just from gates + if row == self.horizontal_cut + self.ommited_rows: + # Minus one because the first component has index 0 instead of 1 + ids_sum += sum([1 for gate_pos in range(first_row_elem_id, self.N)])-1 + elif row == b_index-1: + ids_sum += sum([2 for gate_adder_pos in range(first_row_elem_id, self.N) if gate_adder_pos <= a_index+1]) + else: + ids_sum += sum([2 for gate_adder_pos in range(first_row_elem_id, self.N)]) + # Index calculation should be redone, but it works even this way + index = ids_sum+2 if a_index == self.N-1 else ids_sum + elif mult_type == "tm": + index = ((b_index-self.truncation_cut-2) * ((self.N-self.truncation_cut)*2)) + ((self.N-self.truncation_cut-1)+2*(a_index-self.truncation_cut+2)) + else: + index = ((b_index-2) * ((self.N)*2)) + ((self.N-1)+2*(a_index+2)) + + # Get carry wire as input for the last adder in current row if a_index == self.N-1: @@ -487,6 +529,10 @@ that are later used for generation into various representations.

Subclasses

-def get_previous_partial_product(self, a_index: int, b_index: int) +def get_previous_partial_product(self, a_index: int, b_index: int, mult_type='')

Used in array multipliers to get previous row's component output wires for further connection to another component's input.

@@ -743,6 +789,8 @@ if not the wire present at the desired position is returned.

First input wire index.
b_index : int
Second input wire index.
+
mult_type : string, optional
+
Specifies what type of multiplier circuit has called this method. It is used for proper retrieval of index into the components list to allow appropriate interconnection of the multiplier circuit's inner subcomponents. It expects "" for ordinary multipliers, bam or tm for specific approximate multipliers. Defaults to "".

Returns

@@ -753,18 +801,39 @@ if not the wire present at the desired position is returned.

Expand source code -
def get_previous_partial_product(self, a_index: int, b_index: int):
+
def get_previous_partial_product(self, a_index: int, b_index: int, mult_type=""):
     """Used in array multipliers to get previous row's component output wires for further connection to another component's input.
 
     Args:
         a_index (int): First input wire index.
         b_index (int): Second input wire index.
+        mult_type (string, optional): Specifies what type of multiplier circuit has called this method. It is used for proper retrieval of index into the components list to allow appropriate interconnection of the multiplier circuit's inner subcomponents. It expects "" for ordinary multipliers, `bam` or `tm` for specific approximate multipliers. Defaults to "".
 
     Returns:
         Wire: Previous row's component wire of corresponding pp.
     """
     # To get the index of previous row's connecting adder and its generated pp
-    index = ((b_index-2) * (self.N*2)) + ((self.N-1)+2*(a_index+2))
+    if mult_type == "bam":
+        #TODO alter to be more compact
+        ids_sum = 0
+        for row in range(self.horizontal_cut + self.ommited_rows, b_index):
+            first_row_elem_id = self.vertical_cut-row if self.vertical_cut-row > 0 else 0
+            # First pp row composed just from gates
+            if row == self.horizontal_cut + self.ommited_rows:
+                # Minus one because the first component has index 0 instead of 1 
+                ids_sum += sum([1 for gate_pos in range(first_row_elem_id, self.N)])-1
+            elif row == b_index-1:
+                ids_sum += sum([2 for gate_adder_pos in range(first_row_elem_id, self.N) if gate_adder_pos <= a_index+1])
+            else:
+                ids_sum += sum([2 for gate_adder_pos in range(first_row_elem_id, self.N)])
+        # Index calculation should be redone, but it works even this way
+        index = ids_sum+2 if a_index == self.N-1 else ids_sum
+    elif mult_type == "tm":
+        index = ((b_index-self.truncation_cut-2) * ((self.N-self.truncation_cut)*2)) + ((self.N-self.truncation_cut-1)+2*(a_index-self.truncation_cut+2))
+    else:
+        index = ((b_index-2) * ((self.N)*2)) + ((self.N-1)+2*(a_index+2))
+
+
 
     # Get carry wire as input for the last adder in current row
     if a_index == self.N-1:
diff --git a/index.html b/index.html
index 6a8a47b..d851eee 100644
--- a/index.html
+++ b/index.html
@@ -39,8 +39,11 @@ from .one_bit_circuits import (
 from .multi_bit_circuits import (
     adders,
     multipliers,
+    approximate_multipliers,
     dividers
-)
+) + +from .pdk import *
@@ -58,6 +61,10 @@ from .multi_bit_circuits import (
+
ariths_gen.pdk
+
+

Support of custom PDK …

+
ariths_gen.wire_components
@@ -82,6 +89,7 @@ from .multi_bit_circuits import (
  • ariths_gen.core
  • ariths_gen.multi_bit_circuits
  • ariths_gen.one_bit_circuits
  • +
  • ariths_gen.pdk
  • ariths_gen.wire_components
  • diff --git a/multi_bit_circuits/adders/carry_lookahead_adder.html b/multi_bit_circuits/adders/carry_lookahead_adder.html index a07b174..5ac04bc 100644 --- a/multi_bit_circuits/adders/carry_lookahead_adder.html +++ b/multi_bit_circuits/adders/carry_lookahead_adder.html @@ -95,7 +95,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__(a=a, b=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) @@ -486,7 +486,7 @@ Cout S3 S1 S0 S0 """ 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__(a=a, b=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) diff --git a/multi_bit_circuits/adders/pg_ripple_carry_adder.html b/multi_bit_circuits/adders/pg_ripple_carry_adder.html index 771ac77..d10fb17 100644 --- a/multi_bit_circuits/adders/pg_ripple_carry_adder.html +++ b/multi_bit_circuits/adders/pg_ripple_carry_adder.html @@ -93,7 +93,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) - + # 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) @@ -433,7 +433,7 @@ Cout S3 S1 S0 S0 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) - + # 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) diff --git a/multi_bit_circuits/approximate_multipliers/broken_array_multiplier.html b/multi_bit_circuits/approximate_multipliers/broken_array_multiplier.html new file mode 100644 index 0000000..6254f80 --- /dev/null +++ b/multi_bit_circuits/approximate_multipliers/broken_array_multiplier.html @@ -0,0 +1,1000 @@ + + + + + + +ariths_gen.multi_bit_circuits.approximate_multipliers.broken_array_multiplier API documentation + + + + + + + + + + + +
    +
    +
    +

    Module ariths_gen.multi_bit_circuits.approximate_multipliers.broken_array_multiplier

    +
    +
    +
    + +Expand source code + +
    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 (
    +    HalfAdder,
    +    FullAdder,
    +    FullAdderPG
    +)
    +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
    +)
    +
    +
    +class UnsignedBrokenArrayMultiplier(MultiplierCircuit):
    +    """Class representing unsigned broken array multiplier.
    +
    +    It represents an approximative version of unsigned array multiplier with simpler structure.
    +    It is created by modifying an ordinary N-bit unsigned array multiplier by omitting partial product
    +    stage cells by the specified horizontal and vertical cut levels.
    +
    +    The design promises better area and power parameters in exchange for the loss of computation precision.
    +    The BAM design allows to save more partial product stage adders than truncated multiplier.
    +    ```
    +                            VERTICAL CUT=4
    +
    +                                │
    +                                            A3B0       A2B0       A1B0       A0B0
    +                                │          ┌───┐      ┌───┐      ┌───┐      ┌───┐
    +                                           │AND│      │AND│      │AND│      │AND│
    +                                │          └───┘      └───┘      └───┘      └───┘
    +                                 
    +                                │
    +                                      A3B1       A2B1       A1B1       A0B1
    +                                │    ┌───┐      ┌───┐      ┌───┐      ┌───┐
    +                                     │AND│      │AND│      │AND│      │AND│
    +                                │    └───┘      └───┘      └───┘      └───┘
    +                                 
    +                                │ ┌────┐     ┌────┐     ┌────┐     ┌────┐
    +                                  │    │     │    │     │    │     │    │
    +                                │ │ HA │     │ FA │     │ FA │     │ HA │
    +                                  │    │     │    │     │    │     │    │
    +                                │ └────┘     └────┘     └────┘     └────┘
    +                                 
    +              ─ ─ ─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ HORIZONTAL CUT=2
    +                       A3B2           A2B2       A1B2       A0B2
    +                      ┌▼─▼┐     │    ┌───┐      ┌───┐      ┌───┐
    +                      │AND│          │AND│      │AND│      │AND│
    +                      └┬──┘     │    └───┘      └───┘      └───┘
    +                       │         
    +                       │        │ ┌────┐     ┌────┐     ┌────┐
    +                       │          │    │     │    │     │    │
    +                       │        │ │ FA │     │ FA │     │ HA │
    +                       │          │    │     │    │     │    │
    +                       │        │ └────┘     └────┘     └────┘
    +            A3B3       │  A2B3       A1B3      A0B3
    +           ┌▼─▼┐       │ ┌▼─▼┐  │   ┌───┐     ┌───┐
    +           │AND│       │ │AND│      │AND│     │AND│
    +           └┬──┘       │ └┬──┘  │   └───┘     └───┘
    +            │          │  │      
    +           ┌▼───┐     ┌▼──▼┐    │ ┌────┐    ┌────┐
    +           │    │     │    │      │    │    │    │
    +    ┌──────┤ HA │◄────┤ HA │    │ │ FA │    │ HA │ 
    +    │      │    │     │    │      │    │    │    │
    +    │      └──┬─┘     └──┬─┘    │ └────┘    └────┘
    +    │         │          │       
    +    │         │          │      │
    +    ▼         ▼          ▼          ▼           ▼          ▼          ▼          ▼
    +    P7        P6         P5     │   P4=0        P3=0       P2=0       P1=0       P0=0
    +    ```
    +    Description of the __init__ method.
    +
    +    Args:
    +        a (Bus): First input bus.
    +        b (Bus): Second input bus.
    +        horizontal_cut (int, optional): Specifies horizontal cut used in broken array multiplier circuit creation. Defaults to 0.
    +        vertical_cut (int, optional): Specifies vertical cut used in broken array multiplier circuit creation. Defaults to 0.
    +        prefix (str, optional): Prefix name of unsigned broken array multiplier. Defaults to "".
    +        name (str, optional): Name of unsigned broken array multiplier. Defaults to "u_bam".
    +    """
    +    def __init__(self, a: Bus, b: Bus, horizontal_cut: int = 0, vertical_cut: int = 0, prefix: str = "", name: str = "u_bam", **kwargs):
    +        # NOTE: If horizontal/vertical cut is specified as 0 the final circuit is a simple array multiplier
    +        self.horizontal_cut = horizontal_cut
    +        self.vertical_cut = vertical_cut
    +        
    +        self.N = max(a.N, b.N)
    +        # Horizontal cut level should be: 0 <= horizontal_cut < N
    +        # Vertical cut level should be: horizontal_cut <= vertical_cut < 2*N
    +        assert horizontal_cut < self.N
    +        assert vertical_cut < 2*self.N
    +        
    +        # 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)
    +
    +        # 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)
    +        
    +        self.ommited_rows = 0
    +        # Gradual generation of partial products
    +        for b_multiplier_index in range(self.horizontal_cut, self.N):
    +            # Number of elements that should be ommited in the current level based on vertical cut
    +            pp_row_elems_to_skip = self.vertical_cut - b_multiplier_index if self.vertical_cut - b_multiplier_index > 0 else 0
    +            # Number of pp pairs present in the current row 
    +            pp_row_elems = self.N-pp_row_elems_to_skip if self.N-pp_row_elems_to_skip > 0 else 0
    +            self.ommited_rows += 1 if pp_row_elems == 0 else 0
    +            
    +            for a_multiplicand_index in range((self.N-pp_row_elems), self.N): 
    +                # AND gates generation for calculation of partial products
    +                obj_and = AndGate(self.a.get_wire(a_multiplicand_index), self.b.get_wire(b_multiplier_index), prefix=self.prefix+"_and"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                self.add_component(obj_and)
    +
    +                if b_multiplier_index != self.horizontal_cut + self.ommited_rows:
    +                    if b_multiplier_index == self.horizontal_cut + self.ommited_rows + 1:
    +                        previous_product = self.components[a_multiplicand_index + b_multiplier_index - self.vertical_cut].out
    +                    else:
    +                        previous_product = self.get_previous_partial_product(a_index=a_multiplicand_index, b_index=b_multiplier_index, mult_type="bam")
    +
    +                    # HA generation for first 1-bit adder in each row starting from the second one
    +                    if a_multiplicand_index == 0 or self.vertical_cut-b_multiplier_index == a_multiplicand_index:
    +                        obj_adder = HalfAdder(self.get_previous_component().out, previous_product, prefix=self.prefix+"_ha"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +                        # Product generation
    +                        self.out.connect(b_multiplier_index, obj_adder.get_sum_wire())
    +
    +                    # HA generation, last 1-bit adder in second row
    +                    elif a_multiplicand_index == self.N-1 and b_multiplier_index == self.horizontal_cut+self.ommited_rows+1:
    +                        obj_adder = HalfAdder(self.get_previous_component().out, self.get_previous_component(number=2).get_carry_wire(), prefix=self.prefix+"_ha"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +
    +                    # FA generation
    +                    else:
    +                        obj_adder = FullAdder(self.get_previous_component().out, previous_product, self.get_previous_component(number=2).get_carry_wire(), prefix=self.prefix+"_fa"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +
    +                # PRODUCT GENERATION
    +                if (a_multiplicand_index == 0 and b_multiplier_index == self.horizontal_cut) or (self.horizontal_cut + self.ommited_rows == self.N-1):
    +                    self.out.connect(a_multiplicand_index + b_multiplier_index, obj_and.out)
    +                    
    +                    # 1 bit multiplier case
    +                    if a_multiplicand_index == self.N-1 and b_multiplier_index == self.N-1:
    +                        self.out.connect(a_multiplicand_index+b_multiplier_index+1, ConstantWireValue0())
    +
    +                elif b_multiplier_index == self.N-1 and self.horizontal_cut != self.N-1:
    +                    self.out.connect(b_multiplier_index + a_multiplicand_index, obj_adder.get_sum_wire())
    +
    +                    if a_multiplicand_index == self.N-1:
    +                        self.out.connect(self.out.N-1, obj_adder.get_carry_wire())
    +
    +        # Connecting the output bits generated from ommited cells to ground
    +        if self.vertical_cut == 2*self.N-1:
    +            [self.out.connect(out_id, ConstantWireValue0()) for out_id in range(self.out.N)]
    +        else:
    +            for grounded_out_index in range(0, max(self.horizontal_cut, self.vertical_cut)):
    +                self.out.connect(grounded_out_index, ConstantWireValue0())
    +
    +class SignedBrokenArrayMultiplier(MultiplierCircuit):
    +    """Class representing signed broken array multiplier.
    +
    +    It represents an approximative version of signed array multiplier with simpler structure.
    +    It is created by modifying an ordinary N-bit unsigned array multiplier by omitting partial product
    +    stage cells by the specified horizontal and vertical cut levels.
    +
    +    The design promises better area and power parameters in exchange for the loss of computation precision.
    +    The BAM design allows to save more partial product stage adders than truncated multiplier.
    +    TODO
    +    ```
    +                                         A3B0     A2B0     A1B0     A0B0
    +                                         │ │      │ │      │ │      │ │
    +                                        ┌▼─▼─┐   ┌▼─▼┐    ┌▼─▼┐    ┌▼─▼┐
    +                                        │NAND│   │AND│    │AND│    │AND│
    +                                        └┬───┘   └┬──┘    └┬──┘    └─┬─┘
    +                                   A3B1  │  A2B1  │ A1B1   │  A0B1   │
    +                                  ┌▼─▼─┐ │ ┌▼─▼┐  │ ┌▼─▼┐  │ ┌▼─▼┐   │
    +                                  │NAND│ │ │AND│  │ │AND│  │ │AND│   │
    +                                1 └┬───┘ │ └┬──┘  │ └┬──┘  │ └┬──┘   │
    +                                │  │     │  │     │  │     │  │      │
    +                               ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │
    +                               │    │   │    │   │    │   │    │     │
    +                       ┌───────┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │
    +                       │       │    │   │    │   │    │   │    │     │
    +                       │       └┬───┘   └┬───┘   └┬───┘   └─┬──┘     │
    +                       │  A3B2  │  A2B2  │  A1B2  │  A0B2   │        │
    +                       │ ┌▼─▼─┐ │ ┌▼─▼┐  │ ┌▼─▼┐  │ ┌▼─▼┐   │        │
    +                       │ │NAND│ │ │AND│  │ │AND│  │ │AND│   │        │
    +                       │ └┬───┘ │ └┬──┘  │ └┬──┘  │ └┬──┘   │        │
    +                       │  │     │  │     │  │     │  │      │        │
    +                      ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │        │
    +                      │    │   │    │   │    │   │    │     │        │
    +              ┌───────┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │        │
    +              │       │    │   │    │   │    │   │    │     │        │
    +              │       └┬───┘   └┬───┘   └┬───┘   └─┬──┘     │        │
    +              │  A3B3  │  A2B3  │  A1B3  │  A0B3   │        │        │
    +              │ ┌▼─▼┐  │ ┌▼─▼─┐ │ ┌▼─▼─┐ │ ┌▼─▼─┐  │        │        │
    +              │ │AND│  │ │NAND│ │ │NAND│ │ │NAND│  │        │        │
    +      1       │ └┬──┘  │ └┬───┘ │ └┬───┘ │ └┬───┘  │        │        │
    +      │       │  │     │  │     │  │     │  │      │        │        │
    +    ┌─▼──┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │        │        │
    +    │    │   │    │   │    │   │    │   │    │     │        │        │
    +    │XOR │◄──┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │        │        │
    +    │    │   │    │   │    │   │    │   │    │     │        │        │
    +    └─┬──┘   └─┬──┘   └─┬──┘   └─┬──┘   └─┬──┘     │        │        │
    +      │        │        │        │        │        │        │        │
    +      ▼        ▼        ▼        ▼        ▼        ▼        ▼        ▼
    +      P7       P6       P5       P4       P3       P2       P1       P0
    +    ```
    +
    +    Description of the __init__ method.
    +
    +    Args:
    +        a (Bus): First input bus.
    +        b (Bus): Second input bus.
    +        horizontal_cut (int, optional): Specifies horizontal cut used in signed broken array multiplier circuit creation. Defaults to 0.
    +        vertical_cut (int, optional): Specifies vertical cut used in signed broken array multiplier circuit creation. Defaults to 0.
    +        prefix (str, optional): Prefix name of signed broken array multiplier. Defaults to "".
    +        name (str, optional): Name of signed broken array multiplier. Defaults to "s_bam".
    +    """
    +    def __init__(self, a: Bus, b: Bus, horizontal_cut: int = 0, vertical_cut: int = 0, prefix: str = "", name: str = "s_bam", **kwargs):
    +        # NOTE: If horizontal/vertical cut is specified as 0 the final circuit is a simple array multiplier
    +        self.horizontal_cut = horizontal_cut
    +        self.vertical_cut = vertical_cut
    +
    +        self.N = max(a.N, b.N)
    +        # Horizontal cut level should be: 0 <= horizontal_cut < N
    +        # Vertical cut level should be: horizontal_cut <= vertical_cut < 2*N
    +        assert horizontal_cut < self.N
    +        assert vertical_cut < 2*self.N
    +        
    +        # 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, signed=True, **kwargs)
    +        self.c_data_type = "int64_t"
    +        
    +        # 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)
    +
    +        self.ommited_rows = 0
    +        # Gradual generation of partial products
    +        for b_multiplier_index in range(self.horizontal_cut, self.N):
    +            # Number of elements that should be ommited in the current level based on vertical cut
    +            pp_row_elems_to_skip = self.vertical_cut - b_multiplier_index if self.vertical_cut - b_multiplier_index > 0 else 0
    +            # Number of pp pairs present in the current row 
    +            pp_row_elems = self.N-pp_row_elems_to_skip if self.N-pp_row_elems_to_skip > 0 else 0
    +            self.ommited_rows += 1 if pp_row_elems == 0 else 0
    +
    +            for a_multiplicand_index in range(self.N-pp_row_elems, self.N):
    +                # AND and NAND gates generation for calculation of partial products and sign extension
    +                if (b_multiplier_index == self.N-1 and a_multiplicand_index != self.N-1) or (b_multiplier_index != self.N-1 and a_multiplicand_index == self.N-1):
    +                    obj_nand = NandGate(self.a.get_wire(a_multiplicand_index), self.b.get_wire(b_multiplier_index), prefix=self.prefix+"_nand"+str(a_multiplicand_index)+"_"+str(b_multiplier_index), parent_component=self)
    +                    self.add_component(obj_nand)
    +                else:
    +                    obj_and = AndGate(self.a.get_wire(a_multiplicand_index), self.b.get_wire(b_multiplier_index), prefix=self.prefix+"_and"+str(a_multiplicand_index)+"_"+str(b_multiplier_index), parent_component=self)
    +                    self.add_component(obj_and)
    +
    +                if b_multiplier_index != self.horizontal_cut + self.ommited_rows:
    +                    if b_multiplier_index == self.horizontal_cut + self.ommited_rows + 1:
    +                        previous_product = self.components[a_multiplicand_index + b_multiplier_index - self.vertical_cut].out
    +                    else:
    +                        previous_product = self.get_previous_partial_product(a_index=a_multiplicand_index, b_index=b_multiplier_index, mult_type="bam")
    +
    +                    # HA generation for first 1-bit adder in each row starting from the second one
    +                    if a_multiplicand_index == 0 or self.vertical_cut-b_multiplier_index == a_multiplicand_index:
    +                        obj_adder = HalfAdder(self.get_previous_component().out, previous_product, prefix=self.prefix+"_ha"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +                        # Product generation
    +                        self.out.connect(b_multiplier_index, obj_adder.get_sum_wire())
    +
    +                    # FA generation
    +                    else:
    +                        # Constant wire with value 1 used at the last FA in second row (as one of its inputs) for signed multiplication (based on Baugh Wooley algorithm)
    +                        if a_multiplicand_index == self.N-1 and b_multiplier_index == self.horizontal_cut+self.ommited_rows+1:
    +                            previous_product = ConstantWireValue1()
    +
    +                        obj_adder = FullAdder(self.get_previous_component().out, previous_product, self.get_previous_component(number=2).get_carry_wire(), prefix=self.prefix+"_fa"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +
    +                # PRODUCT GENERATION
    +                if (a_multiplicand_index == 0 and b_multiplier_index == self.horizontal_cut) or (self.horizontal_cut + self.ommited_rows == self.N-1):
    +                    self.out.connect(a_multiplicand_index + b_multiplier_index, obj_and.out)
    +                    # 1 bit multiplier case
    +                    if a_multiplicand_index == self.N-1 and b_multiplier_index == self.N-1:
    +                        obj_nor = NorGate(ConstantWireValue1(), self.get_previous_component().out, prefix=self.prefix+"_nor_zero_extend", parent_component=self)
    +                        self.add_component(obj_nor)
    +
    +                        self.out.connect(a_multiplicand_index+1, obj_nor.out)
    +
    +                elif b_multiplier_index == self.N-1 and self.horizontal_cut != self.N-1:
    +                    self.out.connect(b_multiplier_index + a_multiplicand_index, obj_adder.get_sum_wire())
    +
    +                    if a_multiplicand_index == self.N-1:
    +                        obj_xor = XorGate(self.get_previous_component().get_carry_wire(), ConstantWireValue1(), prefix=self.prefix+"_xor"+str(a_multiplicand_index+1)+"_"+str(b_multiplier_index), parent_component=self)
    +                        self.add_component(obj_xor)
    +
    +                        self.out.connect(self.out.N-1, obj_xor.out)
    +        
    +        # Connecting the output bits generated from ommited cells to ground
    +        if self.vertical_cut == 2*self.N-1:
    +            [self.out.connect(out_id, ConstantWireValue0()) for out_id in range(self.out.N)]
    +        else:
    +            for grounded_out_index in range(0, max(self.horizontal_cut, self.vertical_cut)):
    +                self.out.connect(grounded_out_index, ConstantWireValue0())
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class SignedBrokenArrayMultiplier +(a: Bus, b: Bus, horizontal_cut: int = 0, vertical_cut: int = 0, prefix: str = '', name: str = 's_bam', **kwargs) +
    +
    +

    Class representing signed broken array multiplier.

    +

    It represents an approximative version of signed array multiplier with simpler structure. +It is created by modifying an ordinary N-bit unsigned array multiplier by omitting partial product +stage cells by the specified horizontal and vertical cut levels.

    +

    The design promises better area and power parameters in exchange for the loss of computation precision. +The BAM design allows to save more partial product stage adders than truncated multiplier. +TODO

    +
                                         A3B0     A2B0     A1B0     A0B0
    +                                     │ │      │ │      │ │      │ │
    +                                    ┌▼─▼─┐   ┌▼─▼┐    ┌▼─▼┐    ┌▼─▼┐
    +                                    │NAND│   │AND│    │AND│    │AND│
    +                                    └┬───┘   └┬──┘    └┬──┘    └─┬─┘
    +                               A3B1  │  A2B1  │ A1B1   │  A0B1   │
    +                              ┌▼─▼─┐ │ ┌▼─▼┐  │ ┌▼─▼┐  │ ┌▼─▼┐   │
    +                              │NAND│ │ │AND│  │ │AND│  │ │AND│   │
    +                            1 └┬───┘ │ └┬──┘  │ └┬──┘  │ └┬──┘   │
    +                            │  │     │  │     │  │     │  │      │
    +                           ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │
    +                           │    │   │    │   │    │   │    │     │
    +                   ┌───────┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │
    +                   │       │    │   │    │   │    │   │    │     │
    +                   │       └┬───┘   └┬───┘   └┬───┘   └─┬──┘     │
    +                   │  A3B2  │  A2B2  │  A1B2  │  A0B2   │        │
    +                   │ ┌▼─▼─┐ │ ┌▼─▼┐  │ ┌▼─▼┐  │ ┌▼─▼┐   │        │
    +                   │ │NAND│ │ │AND│  │ │AND│  │ │AND│   │        │
    +                   │ └┬───┘ │ └┬──┘  │ └┬──┘  │ └┬──┘   │        │
    +                   │  │     │  │     │  │     │  │      │        │
    +                  ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │        │
    +                  │    │   │    │   │    │   │    │     │        │
    +          ┌───────┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │        │
    +          │       │    │   │    │   │    │   │    │     │        │
    +          │       └┬───┘   └┬───┘   └┬───┘   └─┬──┘     │        │
    +          │  A3B3  │  A2B3  │  A1B3  │  A0B3   │        │        │
    +          │ ┌▼─▼┐  │ ┌▼─▼─┐ │ ┌▼─▼─┐ │ ┌▼─▼─┐  │        │        │
    +          │ │AND│  │ │NAND│ │ │NAND│ │ │NAND│  │        │        │
    +  1       │ └┬──┘  │ └┬───┘ │ └┬───┘ │ └┬───┘  │        │        │
    +  │       │  │     │  │     │  │     │  │      │        │        │
    +┌─▼──┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │        │        │
    +│    │   │    │   │    │   │    │   │    │     │        │        │
    +│XOR │◄──┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │        │        │
    +│    │   │    │   │    │   │    │   │    │     │        │        │
    +└─┬──┘   └─┬──┘   └─┬──┘   └─┬──┘   └─┬──┘     │        │        │
    +  │        │        │        │        │        │        │        │
    +  ▼        ▼        ▼        ▼        ▼        ▼        ▼        ▼
    +  P7       P6       P5       P4       P3       P2       P1       P0
    +
    +

    Description of the init method.

    +

    Args

    +
    +
    a : Bus
    +
    First input bus.
    +
    b : Bus
    +
    Second input bus.
    +
    horizontal_cut : int, optional
    +
    Specifies horizontal cut used in signed broken array multiplier circuit creation. Defaults to 0.
    +
    vertical_cut : int, optional
    +
    Specifies vertical cut used in signed broken array multiplier circuit creation. Defaults to 0.
    +
    prefix : str, optional
    +
    Prefix name of signed broken array multiplier. Defaults to "".
    +
    name : str, optional
    +
    Name of signed broken array multiplier. Defaults to "s_bam".
    +
    +
    + +Expand source code + +
    class SignedBrokenArrayMultiplier(MultiplierCircuit):
    +    """Class representing signed broken array multiplier.
    +
    +    It represents an approximative version of signed array multiplier with simpler structure.
    +    It is created by modifying an ordinary N-bit unsigned array multiplier by omitting partial product
    +    stage cells by the specified horizontal and vertical cut levels.
    +
    +    The design promises better area and power parameters in exchange for the loss of computation precision.
    +    The BAM design allows to save more partial product stage adders than truncated multiplier.
    +    TODO
    +    ```
    +                                         A3B0     A2B0     A1B0     A0B0
    +                                         │ │      │ │      │ │      │ │
    +                                        ┌▼─▼─┐   ┌▼─▼┐    ┌▼─▼┐    ┌▼─▼┐
    +                                        │NAND│   │AND│    │AND│    │AND│
    +                                        └┬───┘   └┬──┘    └┬──┘    └─┬─┘
    +                                   A3B1  │  A2B1  │ A1B1   │  A0B1   │
    +                                  ┌▼─▼─┐ │ ┌▼─▼┐  │ ┌▼─▼┐  │ ┌▼─▼┐   │
    +                                  │NAND│ │ │AND│  │ │AND│  │ │AND│   │
    +                                1 └┬───┘ │ └┬──┘  │ └┬──┘  │ └┬──┘   │
    +                                │  │     │  │     │  │     │  │      │
    +                               ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │
    +                               │    │   │    │   │    │   │    │     │
    +                       ┌───────┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │
    +                       │       │    │   │    │   │    │   │    │     │
    +                       │       └┬───┘   └┬───┘   └┬───┘   └─┬──┘     │
    +                       │  A3B2  │  A2B2  │  A1B2  │  A0B2   │        │
    +                       │ ┌▼─▼─┐ │ ┌▼─▼┐  │ ┌▼─▼┐  │ ┌▼─▼┐   │        │
    +                       │ │NAND│ │ │AND│  │ │AND│  │ │AND│   │        │
    +                       │ └┬───┘ │ └┬──┘  │ └┬──┘  │ └┬──┘   │        │
    +                       │  │     │  │     │  │     │  │      │        │
    +                      ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │        │
    +                      │    │   │    │   │    │   │    │     │        │
    +              ┌───────┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │        │
    +              │       │    │   │    │   │    │   │    │     │        │
    +              │       └┬───┘   └┬───┘   └┬───┘   └─┬──┘     │        │
    +              │  A3B3  │  A2B3  │  A1B3  │  A0B3   │        │        │
    +              │ ┌▼─▼┐  │ ┌▼─▼─┐ │ ┌▼─▼─┐ │ ┌▼─▼─┐  │        │        │
    +              │ │AND│  │ │NAND│ │ │NAND│ │ │NAND│  │        │        │
    +      1       │ └┬──┘  │ └┬───┘ │ └┬───┘ │ └┬───┘  │        │        │
    +      │       │  │     │  │     │  │     │  │      │        │        │
    +    ┌─▼──┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │        │        │
    +    │    │   │    │   │    │   │    │   │    │     │        │        │
    +    │XOR │◄──┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │        │        │
    +    │    │   │    │   │    │   │    │   │    │     │        │        │
    +    └─┬──┘   └─┬──┘   └─┬──┘   └─┬──┘   └─┬──┘     │        │        │
    +      │        │        │        │        │        │        │        │
    +      ▼        ▼        ▼        ▼        ▼        ▼        ▼        ▼
    +      P7       P6       P5       P4       P3       P2       P1       P0
    +    ```
    +
    +    Description of the __init__ method.
    +
    +    Args:
    +        a (Bus): First input bus.
    +        b (Bus): Second input bus.
    +        horizontal_cut (int, optional): Specifies horizontal cut used in signed broken array multiplier circuit creation. Defaults to 0.
    +        vertical_cut (int, optional): Specifies vertical cut used in signed broken array multiplier circuit creation. Defaults to 0.
    +        prefix (str, optional): Prefix name of signed broken array multiplier. Defaults to "".
    +        name (str, optional): Name of signed broken array multiplier. Defaults to "s_bam".
    +    """
    +    def __init__(self, a: Bus, b: Bus, horizontal_cut: int = 0, vertical_cut: int = 0, prefix: str = "", name: str = "s_bam", **kwargs):
    +        # NOTE: If horizontal/vertical cut is specified as 0 the final circuit is a simple array multiplier
    +        self.horizontal_cut = horizontal_cut
    +        self.vertical_cut = vertical_cut
    +
    +        self.N = max(a.N, b.N)
    +        # Horizontal cut level should be: 0 <= horizontal_cut < N
    +        # Vertical cut level should be: horizontal_cut <= vertical_cut < 2*N
    +        assert horizontal_cut < self.N
    +        assert vertical_cut < 2*self.N
    +        
    +        # 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, signed=True, **kwargs)
    +        self.c_data_type = "int64_t"
    +        
    +        # 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)
    +
    +        self.ommited_rows = 0
    +        # Gradual generation of partial products
    +        for b_multiplier_index in range(self.horizontal_cut, self.N):
    +            # Number of elements that should be ommited in the current level based on vertical cut
    +            pp_row_elems_to_skip = self.vertical_cut - b_multiplier_index if self.vertical_cut - b_multiplier_index > 0 else 0
    +            # Number of pp pairs present in the current row 
    +            pp_row_elems = self.N-pp_row_elems_to_skip if self.N-pp_row_elems_to_skip > 0 else 0
    +            self.ommited_rows += 1 if pp_row_elems == 0 else 0
    +
    +            for a_multiplicand_index in range(self.N-pp_row_elems, self.N):
    +                # AND and NAND gates generation for calculation of partial products and sign extension
    +                if (b_multiplier_index == self.N-1 and a_multiplicand_index != self.N-1) or (b_multiplier_index != self.N-1 and a_multiplicand_index == self.N-1):
    +                    obj_nand = NandGate(self.a.get_wire(a_multiplicand_index), self.b.get_wire(b_multiplier_index), prefix=self.prefix+"_nand"+str(a_multiplicand_index)+"_"+str(b_multiplier_index), parent_component=self)
    +                    self.add_component(obj_nand)
    +                else:
    +                    obj_and = AndGate(self.a.get_wire(a_multiplicand_index), self.b.get_wire(b_multiplier_index), prefix=self.prefix+"_and"+str(a_multiplicand_index)+"_"+str(b_multiplier_index), parent_component=self)
    +                    self.add_component(obj_and)
    +
    +                if b_multiplier_index != self.horizontal_cut + self.ommited_rows:
    +                    if b_multiplier_index == self.horizontal_cut + self.ommited_rows + 1:
    +                        previous_product = self.components[a_multiplicand_index + b_multiplier_index - self.vertical_cut].out
    +                    else:
    +                        previous_product = self.get_previous_partial_product(a_index=a_multiplicand_index, b_index=b_multiplier_index, mult_type="bam")
    +
    +                    # HA generation for first 1-bit adder in each row starting from the second one
    +                    if a_multiplicand_index == 0 or self.vertical_cut-b_multiplier_index == a_multiplicand_index:
    +                        obj_adder = HalfAdder(self.get_previous_component().out, previous_product, prefix=self.prefix+"_ha"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +                        # Product generation
    +                        self.out.connect(b_multiplier_index, obj_adder.get_sum_wire())
    +
    +                    # FA generation
    +                    else:
    +                        # Constant wire with value 1 used at the last FA in second row (as one of its inputs) for signed multiplication (based on Baugh Wooley algorithm)
    +                        if a_multiplicand_index == self.N-1 and b_multiplier_index == self.horizontal_cut+self.ommited_rows+1:
    +                            previous_product = ConstantWireValue1()
    +
    +                        obj_adder = FullAdder(self.get_previous_component().out, previous_product, self.get_previous_component(number=2).get_carry_wire(), prefix=self.prefix+"_fa"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +
    +                # PRODUCT GENERATION
    +                if (a_multiplicand_index == 0 and b_multiplier_index == self.horizontal_cut) or (self.horizontal_cut + self.ommited_rows == self.N-1):
    +                    self.out.connect(a_multiplicand_index + b_multiplier_index, obj_and.out)
    +                    # 1 bit multiplier case
    +                    if a_multiplicand_index == self.N-1 and b_multiplier_index == self.N-1:
    +                        obj_nor = NorGate(ConstantWireValue1(), self.get_previous_component().out, prefix=self.prefix+"_nor_zero_extend", parent_component=self)
    +                        self.add_component(obj_nor)
    +
    +                        self.out.connect(a_multiplicand_index+1, obj_nor.out)
    +
    +                elif b_multiplier_index == self.N-1 and self.horizontal_cut != self.N-1:
    +                    self.out.connect(b_multiplier_index + a_multiplicand_index, obj_adder.get_sum_wire())
    +
    +                    if a_multiplicand_index == self.N-1:
    +                        obj_xor = XorGate(self.get_previous_component().get_carry_wire(), ConstantWireValue1(), prefix=self.prefix+"_xor"+str(a_multiplicand_index+1)+"_"+str(b_multiplier_index), parent_component=self)
    +                        self.add_component(obj_xor)
    +
    +                        self.out.connect(self.out.N-1, obj_xor.out)
    +        
    +        # Connecting the output bits generated from ommited cells to ground
    +        if self.vertical_cut == 2*self.N-1:
    +            [self.out.connect(out_id, ConstantWireValue0()) for out_id in range(self.out.N)]
    +        else:
    +            for grounded_out_index in range(0, max(self.horizontal_cut, self.vertical_cut)):
    +                self.out.connect(grounded_out_index, ConstantWireValue0())
    +
    +

    Ancestors

    + +

    Inherited members

    + +
    +
    +class UnsignedBrokenArrayMultiplier +(a: Bus, b: Bus, horizontal_cut: int = 0, vertical_cut: int = 0, prefix: str = '', name: str = 'u_bam', **kwargs) +
    +
    +

    Class representing unsigned broken array multiplier.

    +

    It represents an approximative version of unsigned array multiplier with simpler structure. +It is created by modifying an ordinary N-bit unsigned array multiplier by omitting partial product +stage cells by the specified horizontal and vertical cut levels.

    +

    The design promises better area and power parameters in exchange for the loss of computation precision. +The BAM design allows to save more partial product stage adders than truncated multiplier.

    +
                            VERTICAL CUT=4
    +
    +                            │
    +                                        A3B0       A2B0       A1B0       A0B0
    +                            │          ┌───┐      ┌───┐      ┌───┐      ┌───┐
    +                                       │AND│      │AND│      │AND│      │AND│
    +                            │          └───┘      └───┘      └───┘      └───┘
    +
    +                            │
    +                                  A3B1       A2B1       A1B1       A0B1
    +                            │    ┌───┐      ┌───┐      ┌───┐      ┌───┐
    +                                 │AND│      │AND│      │AND│      │AND│
    +                            │    └───┘      └───┘      └───┘      └───┘
    +
    +                            │ ┌────┐     ┌────┐     ┌────┐     ┌────┐
    +                              │    │     │    │     │    │     │    │
    +                            │ │ HA │     │ FA │     │ FA │     │ HA │
    +                              │    │     │    │     │    │     │    │
    +                            │ └────┘     └────┘     └────┘     └────┘
    +
    +          ─ ─ ─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ HORIZONTAL CUT=2
    +                   A3B2           A2B2       A1B2       A0B2
    +                  ┌▼─▼┐     │    ┌───┐      ┌───┐      ┌───┐
    +                  │AND│          │AND│      │AND│      │AND│
    +                  └┬──┘     │    └───┘      └───┘      └───┘
    +                   │         
    +                   │        │ ┌────┐     ┌────┐     ┌────┐
    +                   │          │    │     │    │     │    │
    +                   │        │ │ FA │     │ FA │     │ HA │
    +                   │          │    │     │    │     │    │
    +                   │        │ └────┘     └────┘     └────┘
    +        A3B3       │  A2B3       A1B3      A0B3
    +       ┌▼─▼┐       │ ┌▼─▼┐  │   ┌───┐     ┌───┐
    +       │AND│       │ │AND│      │AND│     │AND│
    +       └┬──┘       │ └┬──┘  │   └───┘     └───┘
    +        │          │  │      
    +       ┌▼───┐     ┌▼──▼┐    │ ┌────┐    ┌────┐
    +       │    │     │    │      │    │    │    │
    +┌──────┤ HA │◄────┤ HA │    │ │ FA │    │ HA │ 
    +│      │    │     │    │      │    │    │    │
    +│      └──┬─┘     └──┬─┘    │ └────┘    └────┘
    +│         │          │       
    +│         │          │      │
    +▼         ▼          ▼          ▼           ▼          ▼          ▼          ▼
    +P7        P6         P5     │   P4=0        P3=0       P2=0       P1=0       P0=0
    +
    +

    Description of the init method.

    +

    Args

    +
    +
    a : Bus
    +
    First input bus.
    +
    b : Bus
    +
    Second input bus.
    +
    horizontal_cut : int, optional
    +
    Specifies horizontal cut used in broken array multiplier circuit creation. Defaults to 0.
    +
    vertical_cut : int, optional
    +
    Specifies vertical cut used in broken array multiplier circuit creation. Defaults to 0.
    +
    prefix : str, optional
    +
    Prefix name of unsigned broken array multiplier. Defaults to "".
    +
    name : str, optional
    +
    Name of unsigned broken array multiplier. Defaults to "u_bam".
    +
    +
    + +Expand source code + +
    class UnsignedBrokenArrayMultiplier(MultiplierCircuit):
    +    """Class representing unsigned broken array multiplier.
    +
    +    It represents an approximative version of unsigned array multiplier with simpler structure.
    +    It is created by modifying an ordinary N-bit unsigned array multiplier by omitting partial product
    +    stage cells by the specified horizontal and vertical cut levels.
    +
    +    The design promises better area and power parameters in exchange for the loss of computation precision.
    +    The BAM design allows to save more partial product stage adders than truncated multiplier.
    +    ```
    +                            VERTICAL CUT=4
    +
    +                                │
    +                                            A3B0       A2B0       A1B0       A0B0
    +                                │          ┌───┐      ┌───┐      ┌───┐      ┌───┐
    +                                           │AND│      │AND│      │AND│      │AND│
    +                                │          └───┘      └───┘      └───┘      └───┘
    +                                 
    +                                │
    +                                      A3B1       A2B1       A1B1       A0B1
    +                                │    ┌───┐      ┌───┐      ┌───┐      ┌───┐
    +                                     │AND│      │AND│      │AND│      │AND│
    +                                │    └───┘      └───┘      └───┘      └───┘
    +                                 
    +                                │ ┌────┐     ┌────┐     ┌────┐     ┌────┐
    +                                  │    │     │    │     │    │     │    │
    +                                │ │ HA │     │ FA │     │ FA │     │ HA │
    +                                  │    │     │    │     │    │     │    │
    +                                │ └────┘     └────┘     └────┘     └────┘
    +                                 
    +              ─ ─ ─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ HORIZONTAL CUT=2
    +                       A3B2           A2B2       A1B2       A0B2
    +                      ┌▼─▼┐     │    ┌───┐      ┌───┐      ┌───┐
    +                      │AND│          │AND│      │AND│      │AND│
    +                      └┬──┘     │    └───┘      └───┘      └───┘
    +                       │         
    +                       │        │ ┌────┐     ┌────┐     ┌────┐
    +                       │          │    │     │    │     │    │
    +                       │        │ │ FA │     │ FA │     │ HA │
    +                       │          │    │     │    │     │    │
    +                       │        │ └────┘     └────┘     └────┘
    +            A3B3       │  A2B3       A1B3      A0B3
    +           ┌▼─▼┐       │ ┌▼─▼┐  │   ┌───┐     ┌───┐
    +           │AND│       │ │AND│      │AND│     │AND│
    +           └┬──┘       │ └┬──┘  │   └───┘     └───┘
    +            │          │  │      
    +           ┌▼───┐     ┌▼──▼┐    │ ┌────┐    ┌────┐
    +           │    │     │    │      │    │    │    │
    +    ┌──────┤ HA │◄────┤ HA │    │ │ FA │    │ HA │ 
    +    │      │    │     │    │      │    │    │    │
    +    │      └──┬─┘     └──┬─┘    │ └────┘    └────┘
    +    │         │          │       
    +    │         │          │      │
    +    ▼         ▼          ▼          ▼           ▼          ▼          ▼          ▼
    +    P7        P6         P5     │   P4=0        P3=0       P2=0       P1=0       P0=0
    +    ```
    +    Description of the __init__ method.
    +
    +    Args:
    +        a (Bus): First input bus.
    +        b (Bus): Second input bus.
    +        horizontal_cut (int, optional): Specifies horizontal cut used in broken array multiplier circuit creation. Defaults to 0.
    +        vertical_cut (int, optional): Specifies vertical cut used in broken array multiplier circuit creation. Defaults to 0.
    +        prefix (str, optional): Prefix name of unsigned broken array multiplier. Defaults to "".
    +        name (str, optional): Name of unsigned broken array multiplier. Defaults to "u_bam".
    +    """
    +    def __init__(self, a: Bus, b: Bus, horizontal_cut: int = 0, vertical_cut: int = 0, prefix: str = "", name: str = "u_bam", **kwargs):
    +        # NOTE: If horizontal/vertical cut is specified as 0 the final circuit is a simple array multiplier
    +        self.horizontal_cut = horizontal_cut
    +        self.vertical_cut = vertical_cut
    +        
    +        self.N = max(a.N, b.N)
    +        # Horizontal cut level should be: 0 <= horizontal_cut < N
    +        # Vertical cut level should be: horizontal_cut <= vertical_cut < 2*N
    +        assert horizontal_cut < self.N
    +        assert vertical_cut < 2*self.N
    +        
    +        # 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)
    +
    +        # 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)
    +        
    +        self.ommited_rows = 0
    +        # Gradual generation of partial products
    +        for b_multiplier_index in range(self.horizontal_cut, self.N):
    +            # Number of elements that should be ommited in the current level based on vertical cut
    +            pp_row_elems_to_skip = self.vertical_cut - b_multiplier_index if self.vertical_cut - b_multiplier_index > 0 else 0
    +            # Number of pp pairs present in the current row 
    +            pp_row_elems = self.N-pp_row_elems_to_skip if self.N-pp_row_elems_to_skip > 0 else 0
    +            self.ommited_rows += 1 if pp_row_elems == 0 else 0
    +            
    +            for a_multiplicand_index in range((self.N-pp_row_elems), self.N): 
    +                # AND gates generation for calculation of partial products
    +                obj_and = AndGate(self.a.get_wire(a_multiplicand_index), self.b.get_wire(b_multiplier_index), prefix=self.prefix+"_and"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                self.add_component(obj_and)
    +
    +                if b_multiplier_index != self.horizontal_cut + self.ommited_rows:
    +                    if b_multiplier_index == self.horizontal_cut + self.ommited_rows + 1:
    +                        previous_product = self.components[a_multiplicand_index + b_multiplier_index - self.vertical_cut].out
    +                    else:
    +                        previous_product = self.get_previous_partial_product(a_index=a_multiplicand_index, b_index=b_multiplier_index, mult_type="bam")
    +
    +                    # HA generation for first 1-bit adder in each row starting from the second one
    +                    if a_multiplicand_index == 0 or self.vertical_cut-b_multiplier_index == a_multiplicand_index:
    +                        obj_adder = HalfAdder(self.get_previous_component().out, previous_product, prefix=self.prefix+"_ha"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +                        # Product generation
    +                        self.out.connect(b_multiplier_index, obj_adder.get_sum_wire())
    +
    +                    # HA generation, last 1-bit adder in second row
    +                    elif a_multiplicand_index == self.N-1 and b_multiplier_index == self.horizontal_cut+self.ommited_rows+1:
    +                        obj_adder = HalfAdder(self.get_previous_component().out, self.get_previous_component(number=2).get_carry_wire(), prefix=self.prefix+"_ha"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +
    +                    # FA generation
    +                    else:
    +                        obj_adder = FullAdder(self.get_previous_component().out, previous_product, self.get_previous_component(number=2).get_carry_wire(), prefix=self.prefix+"_fa"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +
    +                # PRODUCT GENERATION
    +                if (a_multiplicand_index == 0 and b_multiplier_index == self.horizontal_cut) or (self.horizontal_cut + self.ommited_rows == self.N-1):
    +                    self.out.connect(a_multiplicand_index + b_multiplier_index, obj_and.out)
    +                    
    +                    # 1 bit multiplier case
    +                    if a_multiplicand_index == self.N-1 and b_multiplier_index == self.N-1:
    +                        self.out.connect(a_multiplicand_index+b_multiplier_index+1, ConstantWireValue0())
    +
    +                elif b_multiplier_index == self.N-1 and self.horizontal_cut != self.N-1:
    +                    self.out.connect(b_multiplier_index + a_multiplicand_index, obj_adder.get_sum_wire())
    +
    +                    if a_multiplicand_index == self.N-1:
    +                        self.out.connect(self.out.N-1, obj_adder.get_carry_wire())
    +
    +        # Connecting the output bits generated from ommited cells to ground
    +        if self.vertical_cut == 2*self.N-1:
    +            [self.out.connect(out_id, ConstantWireValue0()) for out_id in range(self.out.N)]
    +        else:
    +            for grounded_out_index in range(0, max(self.horizontal_cut, self.vertical_cut)):
    +                self.out.connect(grounded_out_index, ConstantWireValue0())
    +
    +

    Ancestors

    + +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/multi_bit_circuits/approximate_multipliers/index.html b/multi_bit_circuits/approximate_multipliers/index.html new file mode 100644 index 0000000..c984d6d --- /dev/null +++ b/multi_bit_circuits/approximate_multipliers/index.html @@ -0,0 +1,84 @@ + + + + + + +ariths_gen.multi_bit_circuits.approximate_multipliers API documentation + + + + + + + + + + + +
    +
    +
    +

    Module ariths_gen.multi_bit_circuits.approximate_multipliers

    +
    +
    +
    + +Expand source code + +
    from ariths_gen.multi_bit_circuits.approximate_multipliers.truncated_multiplier import (
    +    UnsignedTruncatedMultiplier,
    +    SignedTruncatedMultiplier
    +)
    +
    +from ariths_gen.multi_bit_circuits.approximate_multipliers.broken_array_multiplier import (
    +    UnsignedBrokenArrayMultiplier,
    +    SignedBrokenArrayMultiplier
    +)
    +
    +
    +
    +

    Sub-modules

    +
    +
    ariths_gen.multi_bit_circuits.approximate_multipliers.broken_array_multiplier
    +
    +
    +
    +
    ariths_gen.multi_bit_circuits.approximate_multipliers.truncated_multiplier
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/multi_bit_circuits/approximate_multipliers/truncated_multiplier.html b/multi_bit_circuits/approximate_multipliers/truncated_multiplier.html new file mode 100644 index 0000000..5d67247 --- /dev/null +++ b/multi_bit_circuits/approximate_multipliers/truncated_multiplier.html @@ -0,0 +1,885 @@ + + + + + + +ariths_gen.multi_bit_circuits.approximate_multipliers.truncated_multiplier API documentation + + + + + + + + + + + +
    +
    +
    +

    Module ariths_gen.multi_bit_circuits.approximate_multipliers.truncated_multiplier

    +
    +
    +
    + +Expand source code + +
    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 (
    +    HalfAdder,
    +    FullAdder,
    +    FullAdderPG
    +)
    +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
    +)
    +
    +class UnsignedTruncatedMultiplier(MultiplierCircuit):
    +    """Class representing unsigned truncated multiplier.
    +
    +    It represents an approximative version of unsigned array multiplier with simpler structure.
    +    It is created by modifying an ordinary N-bit unsigned array multiplier by ignoring
    +    (truncating) some of the partial products.
    +
    +    The design promises better area and power parameters in exchange for the loss of computation precision.        
    +    ```
    +                                                           CUT=2
    +                                           A3B0    A2B0      │   A1B0    A0B0
    +                                          ┌───┐   ┌───┐         ┌───┐   ┌───┐
    +                                          │AND│   │AND│      │  │AND│   │AND│
    +                                          └───┘   └───┘         └───┘   └───┘
    +                                                     ┌ ─ ─ ─ ┘
    +                                     A3B1       A2B1       A1B1       A0B1
    +                                    ┌───┐      ┌───┐ │    ┌───┐      ┌───┐
    +                                    │AND│      │AND│      │AND│      │AND│
    +                                    └───┘      └───┘ │    └───┘      └───┘
    +                                 ┌────┐     ┌────┐     ┌────┐     ┌────┐
    +                                 │    │     │    │   │ │    │     │    │
    +                                 │ HA │     │ FA │     │ FA │     │ HA │
    +                                 │    │     │    │   │ │    │     │    │
    +                                 └────┘     └────┘     └────┘     └────┘         
    +              ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┬ ─ ─ ─ ─ ┴─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ CUT=2
    +                       A3B2         A2B2         A1B2       A0B2
    +                      ┌▼─▼┐        ┌▼─▼┐   │    ┌───┐      ┌───┐
    +                      │AND│        │AND│        │AND│      │AND│
    +                      └┬──┘        └┬──┘   │    └───┘      └───┘
    +                       │            │        ┌────┐     ┌────┐
    +                       │            │      │ │    │     │    │
    +                       │        ┌ ─ ┼─ ─ ─ ┘ │ FA │     │ HA │
    +                       │            │        │    │     │    │
    +                       │        │   │        └────┘     └────┘
    +               A3B3    │  A2B3      │  A1B3      A0B3
    +              ┌◄─►┐    │ ┌◄─►┐  │   │ ┌───┐     ┌───┐
    +              │AND│    │ │AND│      │ │AND│     │AND│
    +              └┬──┘    │ └┬──┘  │   │ └───┘     └───┘
    +           ┌───▼┐     ┌▼──▼┐       ┌┼───┐    ┌────┐
    +           │    │     │    │    │  ││   │    │    │
    +    ┌──────┤ HA │◄────┤ HA │       ││FA │    │ HA │
    +    │      │    │     │    │    │  ││   │    │    │
    +    │      └──┬─┘     └──┬─┘       └┼───┘    └────┘
    +    │         │          │      │   │
    +    ▼         ▼          ▼          ▼           ▼          ▼          ▼          ▼
    +    P7        P6         P5     │   P4          P3=0       P2=0       P1=0       P0=0
    +    ```
    +    Description of the __init__ method.
    +
    +    Args:
    +        a (Bus): First input bus.
    +        b (Bus): Second input bus.
    +        truncation_cut (int, optional): Specifies truncation cut level used in the truncated multiplier circuit creation. Note: If equal to 0, the final circuit behaves as an ordinary array multiplier. Defaults to 0.
    +        prefix (str, optional): Prefix name of unsigned truncated multiplier. Defaults to "".
    +        name (str, optional): Name of unsigned truncated multiplier. Defaults to "u_tm".
    +    """
    +    def __init__(self, a: Bus, b: Bus, truncation_cut: int = 0, prefix: str = "", name: str = "u_tm", **kwargs):
    +        # NOTE: If truncation_cut is specified as 0 the final circuit is a simple array multiplier
    +        self.truncation_cut = truncation_cut
    +        
    +        self.N = max(a.N, b.N)
    +        # 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)
    +
    +        # 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)
    +
    +        # Gradual generation of partial products
    +        for b_multiplier_index in range(self.truncation_cut, self.N):
    +            for a_multiplicand_index in range(self.truncation_cut, self.N):
    +                # AND gates generation for calculation of partial products
    +                obj_and = AndGate(self.a.get_wire(a_multiplicand_index), self.b.get_wire(b_multiplier_index), prefix=self.prefix+"_and"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                self.add_component(obj_and)
    +
    +                if b_multiplier_index != self.truncation_cut:
    +                    previous_product = self.components[a_multiplicand_index + b_multiplier_index - 2*self.truncation_cut].out if b_multiplier_index == self.truncation_cut + 1 else self.get_previous_partial_product(a_index=a_multiplicand_index, b_index=b_multiplier_index, mult_type="tm")
    +
    +                    # HA generation for first 1-bit adder in each row starting from the second one
    +                    if a_multiplicand_index == self.truncation_cut:
    +                        obj_adder = HalfAdder(self.get_previous_component().out, previous_product, prefix=self.prefix+"_ha"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +                        # Product generation
    +                        self.out.connect(b_multiplier_index + self.truncation_cut, obj_adder.get_sum_wire())
    +
    +                    # HA generation, last 1-bit adder in second row
    +                    elif a_multiplicand_index == self.N-1 and b_multiplier_index == self.truncation_cut+1:
    +                        obj_adder = HalfAdder(self.get_previous_component().out, self.get_previous_component(number=2).get_carry_wire(), prefix=self.prefix+"_ha"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +
    +                    # FA generation
    +                    else:
    +                        obj_adder = FullAdder(self.get_previous_component().out, previous_product, self.get_previous_component(number=2).get_carry_wire(), prefix=self.prefix+"_fa"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +
    +               # PRODUCT GENERATION
    +                if (a_multiplicand_index == self.truncation_cut and b_multiplier_index == self.truncation_cut) or (self.truncation_cut == self.N-1):
    +                    self.out.connect(a_multiplicand_index + b_multiplier_index, obj_and.out)
    +                    
    +                    # 1 bit multiplier case
    +                    if a_multiplicand_index == self.N-1 and b_multiplier_index == self.N-1:
    +                        self.out.connect(a_multiplicand_index+b_multiplier_index+1, ConstantWireValue0())
    +
    +                elif b_multiplier_index == self.N-1 and self.truncation_cut != self.N-1:
    +                    self.out.connect(b_multiplier_index + a_multiplicand_index, obj_adder.get_sum_wire())
    +
    +                    if a_multiplicand_index == self.N-1:
    +                        self.out.connect(self.out.N-1, obj_adder.get_carry_wire())
    +
    +        # Connecting the output bits generated from ommited cells to ground
    +        for grounded_out_index in range(0, self.truncation_cut*2):
    +            self.out.connect(grounded_out_index, ConstantWireValue0())
    +
    +class SignedTruncatedMultiplier(MultiplierCircuit):
    +    """Class representing signed truncated multiplier.
    +
    +    It represents an approximative version of signed array multiplier with simpler structure.
    +    It is created by modifying an ordinary N-bit signed array multiplier by ignoring
    +    (truncating) some of the partial products.
    +
    +    The design promises better area and power parameters in exchange for the loss of computation precision.
    +
    +    ```TODO
    +                                         A3B0     A2B0     A1B0     A0B0
    +                                         │ │      │ │      │ │      │ │
    +                                        ┌▼─▼─┐   ┌▼─▼┐    ┌▼─▼┐    ┌▼─▼┐
    +                                        │NAND│   │AND│    │AND│    │AND│
    +                                        └┬───┘   └┬──┘    └┬──┘    └─┬─┘
    +                                   A3B1  │  A2B1  │ A1B1   │  A0B1   │
    +                                  ┌▼─▼─┐ │ ┌▼─▼┐  │ ┌▼─▼┐  │ ┌▼─▼┐   │
    +                                  │NAND│ │ │AND│  │ │AND│  │ │AND│   │
    +                                1 └┬───┘ │ └┬──┘  │ └┬──┘  │ └┬──┘   │
    +                                │  │     │  │     │  │     │  │      │
    +                               ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │
    +                               │    │   │    │   │    │   │    │     │
    +                       ┌───────┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │
    +                       │       │    │   │    │   │    │   │    │     │
    +                       │       └┬───┘   └┬───┘   └┬───┘   └─┬──┘     │
    +                       │  A3B2  │  A2B2  │  A1B2  │  A0B2   │        │
    +                       │ ┌▼─▼─┐ │ ┌▼─▼┐  │ ┌▼─▼┐  │ ┌▼─▼┐   │        │
    +                       │ │NAND│ │ │AND│  │ │AND│  │ │AND│   │        │
    +                       │ └┬───┘ │ └┬──┘  │ └┬──┘  │ └┬──┘   │        │
    +                       │  │     │  │     │  │     │  │      │        │
    +                      ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │        │
    +                      │    │   │    │   │    │   │    │     │        │
    +              ┌───────┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │        │
    +              │       │    │   │    │   │    │   │    │     │        │
    +              │       └┬───┘   └┬───┘   └┬───┘   └─┬──┘     │        │
    +              │  A3B3  │  A2B3  │  A1B3  │  A0B3   │        │        │
    +              │ ┌▼─▼┐  │ ┌▼─▼─┐ │ ┌▼─▼─┐ │ ┌▼─▼─┐  │        │        │
    +              │ │AND│  │ │NAND│ │ │NAND│ │ │NAND│  │        │        │
    +      1       │ └┬──┘  │ └┬───┘ │ └┬───┘ │ └┬───┘  │        │        │
    +      │       │  │     │  │     │  │     │  │      │        │        │
    +    ┌─▼──┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │        │        │
    +    │    │   │    │   │    │   │    │   │    │     │        │        │
    +    │XOR │◄──┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │        │        │
    +    │    │   │    │   │    │   │    │   │    │     │        │        │
    +    └─┬──┘   └─┬──┘   └─┬──┘   └─┬──┘   └─┬──┘     │        │        │
    +      │        │        │        │        │        │        │        │
    +      ▼        ▼        ▼        ▼        ▼        ▼        ▼        ▼
    +      P7       P6       P5       P4       P3       P2       P1       P0
    +    ```
    +
    +    Description of the __init__ method.
    +
    +    Args:
    +        a (Bus): First input bus.
    +        b (Bus): Second input bus.
    +        truncation_cut (int, optional): Specifies truncation cut level used in the truncated multiplier circuit creation. Note: If equal to 0, the final circuit behaves as an ordinary array multiplier. Defaults to 0.
    +        prefix (str, optional): Prefix name of signed truncated multiplier. Defaults to "".
    +        name (str, optional): Name of signed truncated multiplier. Defaults to "s_tm".
    +    """
    +    def __init__(self, a: Bus, b: Bus, truncation_cut: int = 0, prefix: str = "", name: str = "s_tm", **kwargs):
    +        # NOTE: If truncation_cut is specified as 0 the final circuit is a simple array multiplier
    +        self.truncation_cut = truncation_cut
    +        
    +        self.N = max(a.N, b.N)
    +        # 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, signed=True, **kwargs)
    +        self.c_data_type = "int64_t"
    +        
    +        # 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)
    +
    +        # Gradual generation of partial products
    +        for b_multiplier_index in range(self.truncation_cut, self.N):
    +            for a_multiplicand_index in range(self.truncation_cut, self.N):
    +                # AND and NAND gates generation for calculation of partial products and sign extension
    +                if (b_multiplier_index == self.N-1 and a_multiplicand_index != self.N-1) or (b_multiplier_index != self.N-1 and a_multiplicand_index == self.N-1):
    +                    obj_nand = NandGate(self.a.get_wire(a_multiplicand_index), self.b.get_wire(b_multiplier_index), prefix=self.prefix+"_nand"+str(a_multiplicand_index)+"_"+str(b_multiplier_index), parent_component=self)
    +                    self.add_component(obj_nand)
    +                else:
    +                    obj_and = AndGate(self.a.get_wire(a_multiplicand_index), self.b.get_wire(b_multiplier_index), prefix=self.prefix+"_and"+str(a_multiplicand_index)+"_"+str(b_multiplier_index), parent_component=self)
    +                    self.add_component(obj_and)
    +
    +                if b_multiplier_index != self.truncation_cut:
    +                    previous_product = self.components[a_multiplicand_index + b_multiplier_index - 2*self.truncation_cut].out if b_multiplier_index == self.truncation_cut + 1 else self.get_previous_partial_product(a_index=a_multiplicand_index, b_index=b_multiplier_index, mult_type="tm")
    +                    # HA generation for first 1-bit adder in each row starting from the second one
    +                    if a_multiplicand_index == self.truncation_cut:
    +                        obj_adder = HalfAdder(self.get_previous_component().out, previous_product, prefix=self.prefix+"_ha"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +                        # Product generation
    +                        self.out.connect(b_multiplier_index + self.truncation_cut, obj_adder.get_sum_wire())
    +
    +                    # FA generation
    +                    else:
    +                        # Constant wire with value 1 used at the last FA in second row (as one of its inputs) for signed multiplication (based on Baugh Wooley algorithm)
    +                        if a_multiplicand_index == self.N-1 and b_multiplier_index == self.truncation_cut+1:
    +                            previous_product = ConstantWireValue1()
    +
    +                        obj_adder = FullAdder(self.get_previous_component().out, previous_product, self.get_previous_component(number=2).get_carry_wire(), prefix=self.prefix+"_fa"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +
    +                # PRODUCT GENERATION
    +                if (a_multiplicand_index == self.truncation_cut and b_multiplier_index == self.truncation_cut) or (self.truncation_cut == self.N-1):
    +                    self.out.connect(a_multiplicand_index + b_multiplier_index, obj_and.out)
    +
    +                    # 1 bit multiplier case
    +                    if a_multiplicand_index == self.N-1 and b_multiplier_index == self.N-1:
    +                        obj_nor = NorGate(ConstantWireValue1(), self.get_previous_component().out, prefix=self.prefix+"_nor_zero_extend", parent_component=self)
    +                        self.add_component(obj_nor)
    +
    +                        self.out.connect(a_multiplicand_index+1, obj_nor.out)
    +
    +                elif b_multiplier_index == self.N-1 and self.truncation_cut != self.N-1:
    +                    self.out.connect(b_multiplier_index + a_multiplicand_index, obj_adder.get_sum_wire())
    +
    +                    if a_multiplicand_index == self.N-1:
    +                        obj_xor = XorGate(self.get_previous_component().get_carry_wire(), ConstantWireValue1(), prefix=self.prefix+"_xor"+str(a_multiplicand_index+1)+"_"+str(b_multiplier_index), parent_component=self)
    +                        self.add_component(obj_xor)
    +
    +                        self.out.connect(self.out.N-1, obj_xor.out)
    +        
    +        # Connecting the output bits generated from ommited cells to ground
    +        for grounded_out_index in range(0, self.truncation_cut*2):
    +            self.out.connect(grounded_out_index, ConstantWireValue0())
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class SignedTruncatedMultiplier +(a: Bus, b: Bus, truncation_cut: int = 0, prefix: str = '', name: str = 's_tm', **kwargs) +
    +
    +

    Class representing signed truncated multiplier.

    +

    It represents an approximative version of signed array multiplier with simpler structure. +It is created by modifying an ordinary N-bit signed array multiplier by ignoring +(truncating) some of the partial products.

    +

    The design promises better area and power parameters in exchange for the loss of computation precision.

    +
                                         A3B0     A2B0     A1B0     A0B0
    +                                     │ │      │ │      │ │      │ │
    +                                    ┌▼─▼─┐   ┌▼─▼┐    ┌▼─▼┐    ┌▼─▼┐
    +                                    │NAND│   │AND│    │AND│    │AND│
    +                                    └┬───┘   └┬──┘    └┬──┘    └─┬─┘
    +                               A3B1  │  A2B1  │ A1B1   │  A0B1   │
    +                              ┌▼─▼─┐ │ ┌▼─▼┐  │ ┌▼─▼┐  │ ┌▼─▼┐   │
    +                              │NAND│ │ │AND│  │ │AND│  │ │AND│   │
    +                            1 └┬───┘ │ └┬──┘  │ └┬──┘  │ └┬──┘   │
    +                            │  │     │  │     │  │     │  │      │
    +                           ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │
    +                           │    │   │    │   │    │   │    │     │
    +                   ┌───────┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │
    +                   │       │    │   │    │   │    │   │    │     │
    +                   │       └┬───┘   └┬───┘   └┬───┘   └─┬──┘     │
    +                   │  A3B2  │  A2B2  │  A1B2  │  A0B2   │        │
    +                   │ ┌▼─▼─┐ │ ┌▼─▼┐  │ ┌▼─▼┐  │ ┌▼─▼┐   │        │
    +                   │ │NAND│ │ │AND│  │ │AND│  │ │AND│   │        │
    +                   │ └┬───┘ │ └┬──┘  │ └┬──┘  │ └┬──┘   │        │
    +                   │  │     │  │     │  │     │  │      │        │
    +                  ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │        │
    +                  │    │   │    │   │    │   │    │     │        │
    +          ┌───────┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │        │
    +          │       │    │   │    │   │    │   │    │     │        │
    +          │       └┬───┘   └┬───┘   └┬───┘   └─┬──┘     │        │
    +          │  A3B3  │  A2B3  │  A1B3  │  A0B3   │        │        │
    +          │ ┌▼─▼┐  │ ┌▼─▼─┐ │ ┌▼─▼─┐ │ ┌▼─▼─┐  │        │        │
    +          │ │AND│  │ │NAND│ │ │NAND│ │ │NAND│  │        │        │
    +  1       │ └┬──┘  │ └┬───┘ │ └┬───┘ │ └┬───┘  │        │        │
    +  │       │  │     │  │     │  │     │  │      │        │        │
    +┌─▼──┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │        │        │
    +│    │   │    │   │    │   │    │   │    │     │        │        │
    +│XOR │◄──┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │        │        │
    +│    │   │    │   │    │   │    │   │    │     │        │        │
    +└─┬──┘   └─┬──┘   └─┬──┘   └─┬──┘   └─┬──┘     │        │        │
    +  │        │        │        │        │        │        │        │
    +  ▼        ▼        ▼        ▼        ▼        ▼        ▼        ▼
    +  P7       P6       P5       P4       P3       P2       P1       P0
    +
    +

    Description of the init method.

    +

    Args

    +
    +
    a : Bus
    +
    First input bus.
    +
    b : Bus
    +
    Second input bus.
    +
    truncation_cut : int, optional
    +
    Specifies truncation cut level used in the truncated multiplier circuit creation. Note: If equal to 0, the final circuit behaves as an ordinary array multiplier. Defaults to 0.
    +
    prefix : str, optional
    +
    Prefix name of signed truncated multiplier. Defaults to "".
    +
    name : str, optional
    +
    Name of signed truncated multiplier. Defaults to "s_tm".
    +
    +
    + +Expand source code + +
    class SignedTruncatedMultiplier(MultiplierCircuit):
    +    """Class representing signed truncated multiplier.
    +
    +    It represents an approximative version of signed array multiplier with simpler structure.
    +    It is created by modifying an ordinary N-bit signed array multiplier by ignoring
    +    (truncating) some of the partial products.
    +
    +    The design promises better area and power parameters in exchange for the loss of computation precision.
    +
    +    ```TODO
    +                                         A3B0     A2B0     A1B0     A0B0
    +                                         │ │      │ │      │ │      │ │
    +                                        ┌▼─▼─┐   ┌▼─▼┐    ┌▼─▼┐    ┌▼─▼┐
    +                                        │NAND│   │AND│    │AND│    │AND│
    +                                        └┬───┘   └┬──┘    └┬──┘    └─┬─┘
    +                                   A3B1  │  A2B1  │ A1B1   │  A0B1   │
    +                                  ┌▼─▼─┐ │ ┌▼─▼┐  │ ┌▼─▼┐  │ ┌▼─▼┐   │
    +                                  │NAND│ │ │AND│  │ │AND│  │ │AND│   │
    +                                1 └┬───┘ │ └┬──┘  │ └┬──┘  │ └┬──┘   │
    +                                │  │     │  │     │  │     │  │      │
    +                               ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │
    +                               │    │   │    │   │    │   │    │     │
    +                       ┌───────┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │
    +                       │       │    │   │    │   │    │   │    │     │
    +                       │       └┬───┘   └┬───┘   └┬───┘   └─┬──┘     │
    +                       │  A3B2  │  A2B2  │  A1B2  │  A0B2   │        │
    +                       │ ┌▼─▼─┐ │ ┌▼─▼┐  │ ┌▼─▼┐  │ ┌▼─▼┐   │        │
    +                       │ │NAND│ │ │AND│  │ │AND│  │ │AND│   │        │
    +                       │ └┬───┘ │ └┬──┘  │ └┬──┘  │ └┬──┘   │        │
    +                       │  │     │  │     │  │     │  │      │        │
    +                      ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │        │
    +                      │    │   │    │   │    │   │    │     │        │
    +              ┌───────┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │        │
    +              │       │    │   │    │   │    │   │    │     │        │
    +              │       └┬───┘   └┬───┘   └┬───┘   └─┬──┘     │        │
    +              │  A3B3  │  A2B3  │  A1B3  │  A0B3   │        │        │
    +              │ ┌▼─▼┐  │ ┌▼─▼─┐ │ ┌▼─▼─┐ │ ┌▼─▼─┐  │        │        │
    +              │ │AND│  │ │NAND│ │ │NAND│ │ │NAND│  │        │        │
    +      1       │ └┬──┘  │ └┬───┘ │ └┬───┘ │ └┬───┘  │        │        │
    +      │       │  │     │  │     │  │     │  │      │        │        │
    +    ┌─▼──┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐   ┌▼──▼┐     │        │        │
    +    │    │   │    │   │    │   │    │   │    │     │        │        │
    +    │XOR │◄──┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │     │        │        │
    +    │    │   │    │   │    │   │    │   │    │     │        │        │
    +    └─┬──┘   └─┬──┘   └─┬──┘   └─┬──┘   └─┬──┘     │        │        │
    +      │        │        │        │        │        │        │        │
    +      ▼        ▼        ▼        ▼        ▼        ▼        ▼        ▼
    +      P7       P6       P5       P4       P3       P2       P1       P0
    +    ```
    +
    +    Description of the __init__ method.
    +
    +    Args:
    +        a (Bus): First input bus.
    +        b (Bus): Second input bus.
    +        truncation_cut (int, optional): Specifies truncation cut level used in the truncated multiplier circuit creation. Note: If equal to 0, the final circuit behaves as an ordinary array multiplier. Defaults to 0.
    +        prefix (str, optional): Prefix name of signed truncated multiplier. Defaults to "".
    +        name (str, optional): Name of signed truncated multiplier. Defaults to "s_tm".
    +    """
    +    def __init__(self, a: Bus, b: Bus, truncation_cut: int = 0, prefix: str = "", name: str = "s_tm", **kwargs):
    +        # NOTE: If truncation_cut is specified as 0 the final circuit is a simple array multiplier
    +        self.truncation_cut = truncation_cut
    +        
    +        self.N = max(a.N, b.N)
    +        # 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, signed=True, **kwargs)
    +        self.c_data_type = "int64_t"
    +        
    +        # 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)
    +
    +        # Gradual generation of partial products
    +        for b_multiplier_index in range(self.truncation_cut, self.N):
    +            for a_multiplicand_index in range(self.truncation_cut, self.N):
    +                # AND and NAND gates generation for calculation of partial products and sign extension
    +                if (b_multiplier_index == self.N-1 and a_multiplicand_index != self.N-1) or (b_multiplier_index != self.N-1 and a_multiplicand_index == self.N-1):
    +                    obj_nand = NandGate(self.a.get_wire(a_multiplicand_index), self.b.get_wire(b_multiplier_index), prefix=self.prefix+"_nand"+str(a_multiplicand_index)+"_"+str(b_multiplier_index), parent_component=self)
    +                    self.add_component(obj_nand)
    +                else:
    +                    obj_and = AndGate(self.a.get_wire(a_multiplicand_index), self.b.get_wire(b_multiplier_index), prefix=self.prefix+"_and"+str(a_multiplicand_index)+"_"+str(b_multiplier_index), parent_component=self)
    +                    self.add_component(obj_and)
    +
    +                if b_multiplier_index != self.truncation_cut:
    +                    previous_product = self.components[a_multiplicand_index + b_multiplier_index - 2*self.truncation_cut].out if b_multiplier_index == self.truncation_cut + 1 else self.get_previous_partial_product(a_index=a_multiplicand_index, b_index=b_multiplier_index, mult_type="tm")
    +                    # HA generation for first 1-bit adder in each row starting from the second one
    +                    if a_multiplicand_index == self.truncation_cut:
    +                        obj_adder = HalfAdder(self.get_previous_component().out, previous_product, prefix=self.prefix+"_ha"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +                        # Product generation
    +                        self.out.connect(b_multiplier_index + self.truncation_cut, obj_adder.get_sum_wire())
    +
    +                    # FA generation
    +                    else:
    +                        # Constant wire with value 1 used at the last FA in second row (as one of its inputs) for signed multiplication (based on Baugh Wooley algorithm)
    +                        if a_multiplicand_index == self.N-1 and b_multiplier_index == self.truncation_cut+1:
    +                            previous_product = ConstantWireValue1()
    +
    +                        obj_adder = FullAdder(self.get_previous_component().out, previous_product, self.get_previous_component(number=2).get_carry_wire(), prefix=self.prefix+"_fa"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +
    +                # PRODUCT GENERATION
    +                if (a_multiplicand_index == self.truncation_cut and b_multiplier_index == self.truncation_cut) or (self.truncation_cut == self.N-1):
    +                    self.out.connect(a_multiplicand_index + b_multiplier_index, obj_and.out)
    +
    +                    # 1 bit multiplier case
    +                    if a_multiplicand_index == self.N-1 and b_multiplier_index == self.N-1:
    +                        obj_nor = NorGate(ConstantWireValue1(), self.get_previous_component().out, prefix=self.prefix+"_nor_zero_extend", parent_component=self)
    +                        self.add_component(obj_nor)
    +
    +                        self.out.connect(a_multiplicand_index+1, obj_nor.out)
    +
    +                elif b_multiplier_index == self.N-1 and self.truncation_cut != self.N-1:
    +                    self.out.connect(b_multiplier_index + a_multiplicand_index, obj_adder.get_sum_wire())
    +
    +                    if a_multiplicand_index == self.N-1:
    +                        obj_xor = XorGate(self.get_previous_component().get_carry_wire(), ConstantWireValue1(), prefix=self.prefix+"_xor"+str(a_multiplicand_index+1)+"_"+str(b_multiplier_index), parent_component=self)
    +                        self.add_component(obj_xor)
    +
    +                        self.out.connect(self.out.N-1, obj_xor.out)
    +        
    +        # Connecting the output bits generated from ommited cells to ground
    +        for grounded_out_index in range(0, self.truncation_cut*2):
    +            self.out.connect(grounded_out_index, ConstantWireValue0())
    +
    +

    Ancestors

    + +

    Inherited members

    + +
    +
    +class UnsignedTruncatedMultiplier +(a: Bus, b: Bus, truncation_cut: int = 0, prefix: str = '', name: str = 'u_tm', **kwargs) +
    +
    +

    Class representing unsigned truncated multiplier.

    +

    It represents an approximative version of unsigned array multiplier with simpler structure. +It is created by modifying an ordinary N-bit unsigned array multiplier by ignoring +(truncating) some of the partial products.

    +

    The design promises better area and power parameters in exchange for the loss of computation precision. +

    +
                                                           CUT=2
    +                                       A3B0    A2B0      │   A1B0    A0B0
    +                                      ┌───┐   ┌───┐         ┌───┐   ┌───┐
    +                                      │AND│   │AND│      │  │AND│   │AND│
    +                                      └───┘   └───┘         └───┘   └───┘
    +                                                 ┌ ─ ─ ─ ┘
    +                                 A3B1       A2B1       A1B1       A0B1
    +                                ┌───┐      ┌───┐ │    ┌───┐      ┌───┐
    +                                │AND│      │AND│      │AND│      │AND│
    +                                └───┘      └───┘ │    └───┘      └───┘
    +                             ┌────┐     ┌────┐     ┌────┐     ┌────┐
    +                             │    │     │    │   │ │    │     │    │
    +                             │ HA │     │ FA │     │ FA │     │ HA │
    +                             │    │     │    │   │ │    │     │    │
    +                             └────┘     └────┘     └────┘     └────┘         
    +          ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┬ ─ ─ ─ ─ ┴─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ CUT=2
    +                   A3B2         A2B2         A1B2       A0B2
    +                  ┌▼─▼┐        ┌▼─▼┐   │    ┌───┐      ┌───┐
    +                  │AND│        │AND│        │AND│      │AND│
    +                  └┬──┘        └┬──┘   │    └───┘      └───┘
    +                   │            │        ┌────┐     ┌────┐
    +                   │            │      │ │    │     │    │
    +                   │        ┌ ─ ┼─ ─ ─ ┘ │ FA │     │ HA │
    +                   │            │        │    │     │    │
    +                   │        │   │        └────┘     └────┘
    +           A3B3    │  A2B3      │  A1B3      A0B3
    +          ┌◄─►┐    │ ┌◄─►┐  │   │ ┌───┐     ┌───┐
    +          │AND│    │ │AND│      │ │AND│     │AND│
    +          └┬──┘    │ └┬──┘  │   │ └───┘     └───┘
    +       ┌───▼┐     ┌▼──▼┐       ┌┼───┐    ┌────┐
    +       │    │     │    │    │  ││   │    │    │
    +┌──────┤ HA │◄────┤ HA │       ││FA │    │ HA │
    +│      │    │     │    │    │  ││   │    │    │
    +│      └──┬─┘     └──┬─┘       └┼───┘    └────┘
    +│         │          │      │   │
    +▼         ▼          ▼          ▼           ▼          ▼          ▼          ▼
    +P7        P6         P5     │   P4          P3=0       P2=0       P1=0       P0=0
    +
    +

    Description of the init method.

    +

    Args

    +
    +
    a : Bus
    +
    First input bus.
    +
    b : Bus
    +
    Second input bus.
    +
    truncation_cut : int, optional
    +
    Specifies truncation cut level used in the truncated multiplier circuit creation. Note: If equal to 0, the final circuit behaves as an ordinary array multiplier. Defaults to 0.
    +
    prefix : str, optional
    +
    Prefix name of unsigned truncated multiplier. Defaults to "".
    +
    name : str, optional
    +
    Name of unsigned truncated multiplier. Defaults to "u_tm".
    +
    +
    + +Expand source code + +
    class UnsignedTruncatedMultiplier(MultiplierCircuit):
    +    """Class representing unsigned truncated multiplier.
    +
    +    It represents an approximative version of unsigned array multiplier with simpler structure.
    +    It is created by modifying an ordinary N-bit unsigned array multiplier by ignoring
    +    (truncating) some of the partial products.
    +
    +    The design promises better area and power parameters in exchange for the loss of computation precision.        
    +    ```
    +                                                           CUT=2
    +                                           A3B0    A2B0      │   A1B0    A0B0
    +                                          ┌───┐   ┌───┐         ┌───┐   ┌───┐
    +                                          │AND│   │AND│      │  │AND│   │AND│
    +                                          └───┘   └───┘         └───┘   └───┘
    +                                                     ┌ ─ ─ ─ ┘
    +                                     A3B1       A2B1       A1B1       A0B1
    +                                    ┌───┐      ┌───┐ │    ┌───┐      ┌───┐
    +                                    │AND│      │AND│      │AND│      │AND│
    +                                    └───┘      └───┘ │    └───┘      └───┘
    +                                 ┌────┐     ┌────┐     ┌────┐     ┌────┐
    +                                 │    │     │    │   │ │    │     │    │
    +                                 │ HA │     │ FA │     │ FA │     │ HA │
    +                                 │    │     │    │   │ │    │     │    │
    +                                 └────┘     └────┘     └────┘     └────┘         
    +              ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┬ ─ ─ ─ ─ ┴─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ CUT=2
    +                       A3B2         A2B2         A1B2       A0B2
    +                      ┌▼─▼┐        ┌▼─▼┐   │    ┌───┐      ┌───┐
    +                      │AND│        │AND│        │AND│      │AND│
    +                      └┬──┘        └┬──┘   │    └───┘      └───┘
    +                       │            │        ┌────┐     ┌────┐
    +                       │            │      │ │    │     │    │
    +                       │        ┌ ─ ┼─ ─ ─ ┘ │ FA │     │ HA │
    +                       │            │        │    │     │    │
    +                       │        │   │        └────┘     └────┘
    +               A3B3    │  A2B3      │  A1B3      A0B3
    +              ┌◄─►┐    │ ┌◄─►┐  │   │ ┌───┐     ┌───┐
    +              │AND│    │ │AND│      │ │AND│     │AND│
    +              └┬──┘    │ └┬──┘  │   │ └───┘     └───┘
    +           ┌───▼┐     ┌▼──▼┐       ┌┼───┐    ┌────┐
    +           │    │     │    │    │  ││   │    │    │
    +    ┌──────┤ HA │◄────┤ HA │       ││FA │    │ HA │
    +    │      │    │     │    │    │  ││   │    │    │
    +    │      └──┬─┘     └──┬─┘       └┼───┘    └────┘
    +    │         │          │      │   │
    +    ▼         ▼          ▼          ▼           ▼          ▼          ▼          ▼
    +    P7        P6         P5     │   P4          P3=0       P2=0       P1=0       P0=0
    +    ```
    +    Description of the __init__ method.
    +
    +    Args:
    +        a (Bus): First input bus.
    +        b (Bus): Second input bus.
    +        truncation_cut (int, optional): Specifies truncation cut level used in the truncated multiplier circuit creation. Note: If equal to 0, the final circuit behaves as an ordinary array multiplier. Defaults to 0.
    +        prefix (str, optional): Prefix name of unsigned truncated multiplier. Defaults to "".
    +        name (str, optional): Name of unsigned truncated multiplier. Defaults to "u_tm".
    +    """
    +    def __init__(self, a: Bus, b: Bus, truncation_cut: int = 0, prefix: str = "", name: str = "u_tm", **kwargs):
    +        # NOTE: If truncation_cut is specified as 0 the final circuit is a simple array multiplier
    +        self.truncation_cut = truncation_cut
    +        
    +        self.N = max(a.N, b.N)
    +        # 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)
    +
    +        # 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)
    +
    +        # Gradual generation of partial products
    +        for b_multiplier_index in range(self.truncation_cut, self.N):
    +            for a_multiplicand_index in range(self.truncation_cut, self.N):
    +                # AND gates generation for calculation of partial products
    +                obj_and = AndGate(self.a.get_wire(a_multiplicand_index), self.b.get_wire(b_multiplier_index), prefix=self.prefix+"_and"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                self.add_component(obj_and)
    +
    +                if b_multiplier_index != self.truncation_cut:
    +                    previous_product = self.components[a_multiplicand_index + b_multiplier_index - 2*self.truncation_cut].out if b_multiplier_index == self.truncation_cut + 1 else self.get_previous_partial_product(a_index=a_multiplicand_index, b_index=b_multiplier_index, mult_type="tm")
    +
    +                    # HA generation for first 1-bit adder in each row starting from the second one
    +                    if a_multiplicand_index == self.truncation_cut:
    +                        obj_adder = HalfAdder(self.get_previous_component().out, previous_product, prefix=self.prefix+"_ha"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +                        # Product generation
    +                        self.out.connect(b_multiplier_index + self.truncation_cut, obj_adder.get_sum_wire())
    +
    +                    # HA generation, last 1-bit adder in second row
    +                    elif a_multiplicand_index == self.N-1 and b_multiplier_index == self.truncation_cut+1:
    +                        obj_adder = HalfAdder(self.get_previous_component().out, self.get_previous_component(number=2).get_carry_wire(), prefix=self.prefix+"_ha"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +
    +                    # FA generation
    +                    else:
    +                        obj_adder = FullAdder(self.get_previous_component().out, previous_product, self.get_previous_component(number=2).get_carry_wire(), prefix=self.prefix+"_fa"+str(a_multiplicand_index)+"_"+str(b_multiplier_index))
    +                        self.add_component(obj_adder)
    +
    +               # PRODUCT GENERATION
    +                if (a_multiplicand_index == self.truncation_cut and b_multiplier_index == self.truncation_cut) or (self.truncation_cut == self.N-1):
    +                    self.out.connect(a_multiplicand_index + b_multiplier_index, obj_and.out)
    +                    
    +                    # 1 bit multiplier case
    +                    if a_multiplicand_index == self.N-1 and b_multiplier_index == self.N-1:
    +                        self.out.connect(a_multiplicand_index+b_multiplier_index+1, ConstantWireValue0())
    +
    +                elif b_multiplier_index == self.N-1 and self.truncation_cut != self.N-1:
    +                    self.out.connect(b_multiplier_index + a_multiplicand_index, obj_adder.get_sum_wire())
    +
    +                    if a_multiplicand_index == self.N-1:
    +                        self.out.connect(self.out.N-1, obj_adder.get_carry_wire())
    +
    +        # Connecting the output bits generated from ommited cells to ground
    +        for grounded_out_index in range(0, self.truncation_cut*2):
    +            self.out.connect(grounded_out_index, ConstantWireValue0())
    +
    +

    Ancestors

    + +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/multi_bit_circuits/index.html b/multi_bit_circuits/index.html index 06c22f9..f58e3c2 100644 --- a/multi_bit_circuits/index.html +++ b/multi_bit_circuits/index.html @@ -30,6 +30,10 @@
    +
    ariths_gen.multi_bit_circuits.approximate_multipliers
    +
    +
    +
    ariths_gen.multi_bit_circuits.dividers
    @@ -61,6 +65,7 @@
  • Sub-modules

    diff --git a/multi_bit_circuits/multipliers/array_multiplier.html b/multi_bit_circuits/multipliers/array_multiplier.html index 284aa53..230a0cc 100644 --- a/multi_bit_circuits/multipliers/array_multiplier.html +++ b/multi_bit_circuits/multipliers/array_multiplier.html @@ -221,7 +221,7 @@ class SignedArrayMultiplier(MultiplierCircuit): 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) self.c_data_type = "int64_t" - + # 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) @@ -412,7 +412,7 @@ gradually sum them.

    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) self.c_data_type = "int64_t" - + # 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) diff --git a/one_bit_circuits/one_bit_components/three_input_one_bit_components.html b/one_bit_circuits/one_bit_components/three_input_one_bit_components.html index df44331..d2c1c61 100644 --- a/one_bit_circuits/one_bit_components/three_input_one_bit_components.html +++ b/one_bit_circuits/one_bit_components/three_input_one_bit_components.html @@ -51,6 +51,8 @@ class FullAdder(ThreeInputOneBitCircuit): c (Wire, optional): Carry input wire. Defaults to Wire(name="cin"). prefix (str, optional): Prefix name of full adder. Defaults to "fa". """ + use_verilog_instance = False + def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), c: Wire = Wire(name="cin"), prefix: str = "fa"): super().__init__(a, b, c, prefix) # 2 wires for component's bus output (sum, cout) @@ -78,6 +80,40 @@ class FullAdder(ThreeInputOneBitCircuit): self.out.connect(1, obj_or.out) + def get_init_v_flat(self): + """ support of custom PDK """ + if not self.use_verilog_instance: + return super().get_init_v_flat() + + return " " + self.use_verilog_instance.format( + **{ + "unit": self.prefix, + "wirea": self.a.prefix, + "wireb": self.b.prefix, + "wirec": self.c.prefix, + "wireys": self.get_sum_wire().prefix, + "wireyc": self.get_carry_wire().prefix, + } + ) + ";\n" + + + def get_self_init_v_hier(self): + """ support of custom PDK """ + if not self.use_verilog_instance: + return super().get_self_init_v_hier() + + unique_out_wires = [] + for o in self.out.bus: + unique_out_wires.append(o.name+"_outid"+str(self.out.bus.index(o))) if o.is_const() or o.name in [self.a.name, self.b.name] else unique_out_wires.append(o.name) + + return " " + self.use_verilog_instance.format(**{ + "unit": self.prefix, + "wirea": self.a.name, + "wireb": self.b.name, + "wirec": self.c.name, + "wireys": unique_out_wires[0], + "wireyc": unique_out_wires[1], + }) + ";\n" class FullAdderPG(ThreeInputOneBitCircuit): """Class representing modified three input one bit full adder with propagate/generate logic. @@ -308,6 +344,8 @@ class FullSubtractor(ThreeInputOneBitCircuit): c (Wire, optional): Carry input wire. Defaults to Wire(name="cin"). prefix (str, optional): Prefix name of full adder. Defaults to "fa". """ + use_verilog_instance = False + def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), c: Wire = Wire(name="cin"), prefix: str = "fa"): super().__init__(a, b, c, prefix) # 2 wires for component's bus output (sum, cout) @@ -333,7 +371,42 @@ class FullSubtractor(ThreeInputOneBitCircuit): obj_or = OrGate(generate_and.out, obj_and.out, prefix=self.prefix+"_or"+str(self.get_instance_num(cls=OrGate)), outid=1, parent_component=self) self.add_component(obj_or) - self.out.connect(1, obj_or.out) + self.out.connect(1, obj_or.out) + + def get_init_v_flat(self): + """ support of custom PDK """ + if not self.use_verilog_instance: + return super().get_init_v_flat() + + return " " + self.use_verilog_instance.format( + **{ + "unit": self.prefix, + "wirea": self.a.prefix, + "wireb": self.b.prefix, + "wirec": self.c.prefix, + "wireys": self.get_sum_wire().prefix, + "wireyc": self.get_carry_wire().prefix, + } + ) + ";\n" + + + def get_self_init_v_hier(self): + """ support of custom PDK """ + if not self.use_verilog_instance: + return super().get_self_init_v_hier() + + unique_out_wires = [] + for o in self.out.bus: + unique_out_wires.append(o.name+"_outid"+str(self.out.bus.index(o))) if o.is_const() or o.name in [self.a.name, self.b.name] else unique_out_wires.append(o.name) + + return " " + self.use_verilog_instance.format(**{ + "unit": self.prefix, + "wirea": self.a.name, + "wireb": self.b.name, + "wirec": self.c.name, + "wireys": unique_out_wires[0], + "wireyc": unique_out_wires[1], + }) + ";\n"

    Ancestors

    +

    Class variables

    +
    +
    var use_verilog_instance
    +
    +
    +
    +
    +

    Methods

    +
    +
    +def get_init_v_flat(self) +
    +
    +

    support of custom PDK

    +
    + +Expand source code + +
    def get_init_v_flat(self):
    +    """ support of custom PDK """
    +    if not self.use_verilog_instance:
    +        return super().get_init_v_flat()
    +
    +    return "  " + self.use_verilog_instance.format(
    +        **{
    +            "unit": self.prefix,
    +            "wirea": self.a.prefix,
    +            "wireb": self.b.prefix,
    +            "wirec": self.c.prefix,
    +            "wireys": self.get_sum_wire().prefix,
    +            "wireyc": self.get_carry_wire().prefix,
    +        }
    +    ) + ";\n"
    +
    +
    +
    +def get_self_init_v_hier(self) +
    +
    +

    support of custom PDK

    +
    + +Expand source code + +
    def get_self_init_v_hier(self):
    +    """ support of custom PDK """
    +    if not self.use_verilog_instance:
    +        return super().get_self_init_v_hier()
    +
    +    unique_out_wires = []
    +    for o in self.out.bus:
    +        unique_out_wires.append(o.name+"_outid"+str(self.out.bus.index(o))) if o.is_const() or o.name in [self.a.name, self.b.name] else unique_out_wires.append(o.name) 
    +
    +    return "  " + self.use_verilog_instance.format(**{
    +            "unit": self.prefix,
    +            "wirea": self.a.name,
    +            "wireb": self.b.name,
    +            "wirec": self.c.name,
    +            "wireys": unique_out_wires[0],
    +            "wireyc": unique_out_wires[1],
    +        }) + ";\n"
    +
    +
    +

    Inherited members

    • ThreeInputOneBitCircuit: @@ -385,7 +522,6 @@ class FullSubtractor(ThreeInputOneBitCircuit):
    • get_init_c_flat
    • get_init_c_hier
    • get_init_python_flat
    • -
    • get_init_v_flat
    • get_init_v_hier
    • get_instance_num
    • get_invocation_blif_hier
    • @@ -404,7 +540,6 @@ class FullSubtractor(ThreeInputOneBitCircuit):
    • get_prototype_v_hier
    • get_python_code_flat
    • get_self_init_v_flat
    • -
    • get_self_init_v_hier
    • get_sum_wire
    • get_triplets_cgp
    • get_unique_types
    • @@ -1026,6 +1161,11 @@ Sel ────┘
      • FullAdder

        +
      • FullAdderPG

        diff --git a/one_bit_circuits/one_bit_components/two_input_one_bit_components.html b/one_bit_circuits/one_bit_components/two_input_one_bit_components.html index eb894ef..0fccdf1 100644 --- a/one_bit_circuits/one_bit_components/two_input_one_bit_components.html +++ b/one_bit_circuits/one_bit_components/two_input_one_bit_components.html @@ -49,6 +49,8 @@ class HalfAdder(TwoInputOneBitCircuit): b (Wire, optional): Second input wire. Defaults to Wire(name="b"). prefix (str, optional): Prefix name of half adder. Defaults to "ha". """ + use_verilog_instance = False + def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), prefix: str = "ha"): super().__init__(a, b, prefix) # 2 wires for component's bus output (sum, cout) @@ -66,6 +68,38 @@ class HalfAdder(TwoInputOneBitCircuit): self.add_component(obj_and) self.out.connect(1, obj_and.out) + def get_init_v_flat(self): + """ support of custom PDK """ + if not self.use_verilog_instance: + return super().get_init_v_flat() + + return " " + self.use_verilog_instance.format( + **{ + "unit": self.prefix, + "wirea": self.a.prefix, + "wireb": self.b.prefix, + "wireys": self.get_sum_wire().prefix, + "wireyc": self.get_carry_wire().prefix, + } + ) + ";\n" + + + def get_self_init_v_hier(self): + """ support of custom PDK """ + if not self.use_verilog_instance: + return super().get_self_init_v_hier() + + unique_out_wires = [] + for o in self.out.bus: + unique_out_wires.append(o.name+"_outid"+str(self.out.bus.index(o))) if o.is_const() or o.name in [self.a.name, self.b.name] else unique_out_wires.append(o.name) + + return " " + self.use_verilog_instance.format(**{ + "unit": self.prefix, + "wirea": self.a.name, + "wireb": self.b.name, + "wireys": unique_out_wires[0], + "wireyc": unique_out_wires[1], + }) + ";\n" class PGLogicBlock(TwoInputOneBitCircuit): """Class representing two input one bit propagate/generate logic block. @@ -235,6 +269,8 @@ class HalfSubtractor(TwoInputOneBitCircuit): b (Wire, optional): Second input wire. Defaults to Wire(name="b"). prefix (str, optional): Prefix name of half adder. Defaults to "ha". """ + use_verilog_instance = False + def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), prefix: str = "ha"): super().__init__(a, b, prefix) # 2 wires for component's bus output (sum, cout) @@ -250,7 +286,40 @@ class HalfSubtractor(TwoInputOneBitCircuit): # AND gate for calculation of 1-bit cout obj_and = AndGate(a, b, prefix=self.prefix+"_and"+str(self.get_instance_num(cls=AndGate)), outid=1, parent_component=self) self.add_component(obj_and) - self.out.connect(1, obj_and.out) + self.out.connect(1, obj_and.out) + + def get_init_v_flat(self): + """ support of custom PDK """ + if not self.use_verilog_instance: + return super().get_init_v_flat() + + return " " + self.use_verilog_instance.format( + **{ + "unit": self.prefix, + "wirea": self.a.prefix, + "wireb": self.b.prefix, + "wireys": self.get_sum_wire().prefix, + "wireyc": self.get_carry_wire().prefix, + } + ) + ";\n" + + + def get_self_init_v_hier(self): + """ support of custom PDK """ + if not self.use_verilog_instance: + return super().get_self_init_v_hier() + + unique_out_wires = [] + for o in self.out.bus: + unique_out_wires.append(o.name+"_outid"+str(self.out.bus.index(o))) if o.is_const() or o.name in [self.a.name, self.b.name] else unique_out_wires.append(o.name) + + return " " + self.use_verilog_instance.format(**{ + "unit": self.prefix, + "wirea": self.a.name, + "wireb": self.b.name, + "wireys": unique_out_wires[0], + "wireyc": unique_out_wires[1], + }) + ";\n"

        Ancestors

        +

        Class variables

        +
        +
        var use_verilog_instance
        +
        +
        +
        +
        +

        Methods

        +
        +
        +def get_init_v_flat(self) +
        +
        +

        support of custom PDK

        +
        + +Expand source code + +
        def get_init_v_flat(self):
        +    """ support of custom PDK """
        +    if not self.use_verilog_instance:
        +        return super().get_init_v_flat()
        +
        +    return "  " + self.use_verilog_instance.format(
        +        **{
        +            "unit": self.prefix,
        +            "wirea": self.a.prefix,
        +            "wireb": self.b.prefix,
        +            "wireys": self.get_sum_wire().prefix,
        +            "wireyc": self.get_carry_wire().prefix,
        +        }
        +    ) + ";\n"
        +
        +
        +
        +def get_self_init_v_hier(self) +
        +
        +

        support of custom PDK

        +
        + +Expand source code + +
        def get_self_init_v_hier(self):
        +    """ support of custom PDK """
        +    if not self.use_verilog_instance:
        +        return super().get_self_init_v_hier()
        +
        +    unique_out_wires = []
        +    for o in self.out.bus:
        +        unique_out_wires.append(o.name+"_outid"+str(self.out.bus.index(o))) if o.is_const() or o.name in [self.a.name, self.b.name] else unique_out_wires.append(o.name) 
        +
        +    return "  " + self.use_verilog_instance.format(**{
        +            "unit": self.prefix,
        +            "wirea": self.a.name,
        +            "wireb": self.b.name,
        +            "wireys": unique_out_wires[0],
        +            "wireyc": unique_out_wires[1],
        +        }) + ";\n"
        +
        +
        +

        Inherited members

        • TwoInputOneBitCircuit: @@ -301,7 +432,6 @@ class HalfSubtractor(TwoInputOneBitCircuit):
        • get_init_c_flat
        • get_init_c_hier
        • get_init_python_flat
        • -
        • get_init_v_flat
        • get_init_v_hier
        • get_instance_num
        • get_invocation_blif_hier
        • @@ -320,7 +450,6 @@ class HalfSubtractor(TwoInputOneBitCircuit):
        • get_prototype_v_hier
        • get_python_code_flat
        • get_self_init_v_flat
        • -
        • get_self_init_v_hier
        • get_sum_wire
        • get_triplets_cgp
        • get_unique_types
        • @@ -770,6 +899,11 @@ class HalfSubtractor(TwoInputOneBitCircuit):
          • HalfAdder

            +
          • HalfSubtractor

            diff --git a/pdk.html b/pdk.html new file mode 100644 index 0000000..348e88a --- /dev/null +++ b/pdk.html @@ -0,0 +1,103 @@ + + + + + + +ariths_gen.pdk API documentation + + + + + + + + + + + +
            +
            +
            +

            Module ariths_gen.pdk

            +
            +
            +

            Support of custom PDK

            +

            This file defines functions for generating of full and half adders +directly on the level of CMOS modules.

            +

            You may add your own modules as in example in set_pdk45_library()

            +

            Please call this function before calling get_verilog_code_XXX()

            +
            + +Expand source code + +
            """
            +Support of custom PDK
            +
            +This file defines functions for generating of full and half adders
            +directly on the level of CMOS modules. 
            +
            +You may add your own modules as in example in set_pdk45_library()
            +
            +Please call this function before calling get_verilog_code_XXX()
            +"""
            +from .one_bit_circuits import (
            +    one_bit_components
            +)
            +
            +
            +def set_pdk45_library():
            +    one_bit_components.FullAdder.use_verilog_instance = "FAX1 {unit} (.A({wirea}), .B({wireb}), .C({wirec}), .YS({wireys}), .YC({wireyc}))"
            +    one_bit_components.HalfAdder.use_verilog_instance = "HAX1 {unit} (.A({wirea}), .B({wireb}), .YS({wireys}), .YC({wireyc}))"
            +
            +
            +
            +
            +
            +
            +
            +

            Functions

            +
            +
            +def set_pdk45_library() +
            +
            +
            +
            + +Expand source code + +
            def set_pdk45_library():
            +    one_bit_components.FullAdder.use_verilog_instance = "FAX1 {unit} (.A({wirea}), .B({wireb}), .C({wirec}), .YS({wireys}), .YC({wireyc}))"
            +    one_bit_components.HalfAdder.use_verilog_instance = "HAX1 {unit} (.A({wirea}), .B({wireb}), .YS({wireys}), .YC({wireyc}))"
            +
            +
            +
            +
            +
            +
            +
            + +
            + + + \ No newline at end of file diff --git a/wire_components/buses.html b/wire_components/buses.html index c4770e6..d1da59e 100644 --- a/wire_components/buses.html +++ b/wire_components/buses.html @@ -37,7 +37,7 @@ class Bus(): Args: prefix (str, optional): Prefix name of the bus. Defaults to "bus". N (int, optional): Number of wires in the bus. Defaults to 1. - wires_list (list, optional): List of Wire objects used to clone one bus to another. Defaults to 0. + wires_list (list, optional): List of Wire objects used to clone one bus to another. Defaults to None. out_bus (bool, optional): Specifies whether this Bus is an output bus of some previous component. Defaults to False. signed (bool, optional): Specifies whether this Bus should consider signed numbers or not (used for C code generation). Defaults to False. """ @@ -76,18 +76,23 @@ class Bus(): """ return self.out_bus - def bus_extend(self, N: int, prefix: str = "bus"): + def bus_extend(self, N: int, prefix: str = "bus", last_wire_extend: bool = True): """Provides bus extension to contain more wires. Args: N (int): Number of wires in the bus. Defaults to 1. prefix (str, optional): Prefix name of the bus. Defaults to "bus". + last_wire_extend (bool, optional): Specifies whether the last wire of the bus should be extended (connected) to all the extending wires. Defaults to True. """ # Checks if any extension is neccesarry and if so, proceeds to wire extend the bus if self.N < N: # Adding wires into current bus's wires list (wire names are concatenated from bus prefix and their index position inside the bus in square brackets) self.bus += [Wire(name=prefix+f"[{i}]", prefix=prefix, index=i, parent_bus=self) for i in range(self.N, N)] + if last_wire_extend is True: + for w_index in range(self.N, N): + self.connect(bus_wire_index=w_index, inner_component_out_wire=self.get_wire(self.N - 1)) self.N = N + def get_wire(self, wire_index: int = 0): """Retrieves a wire from the bus by a given index. @@ -288,7 +293,7 @@ class Bus():
            N : int, optional
            Number of wires in the bus. Defaults to 1.
            wires_list : list, optional
            -
            List of Wire objects used to clone one bus to another. Defaults to 0.
            +
            List of Wire objects used to clone one bus to another. Defaults to None.
            out_bus : bool, optional
            Specifies whether this Bus is an output bus of some previous component. Defaults to False.
            signed : bool, optional
            @@ -306,7 +311,7 @@ class Bus(): Args: prefix (str, optional): Prefix name of the bus. Defaults to "bus". N (int, optional): Number of wires in the bus. Defaults to 1. - wires_list (list, optional): List of Wire objects used to clone one bus to another. Defaults to 0. + wires_list (list, optional): List of Wire objects used to clone one bus to another. Defaults to None. out_bus (bool, optional): Specifies whether this Bus is an output bus of some previous component. Defaults to False. signed (bool, optional): Specifies whether this Bus should consider signed numbers or not (used for C code generation). Defaults to False. """ @@ -345,18 +350,23 @@ class Bus(): """ return self.out_bus - def bus_extend(self, N: int, prefix: str = "bus"): + def bus_extend(self, N: int, prefix: str = "bus", last_wire_extend: bool = True): """Provides bus extension to contain more wires. Args: N (int): Number of wires in the bus. Defaults to 1. prefix (str, optional): Prefix name of the bus. Defaults to "bus". + last_wire_extend (bool, optional): Specifies whether the last wire of the bus should be extended (connected) to all the extending wires. Defaults to True. """ # Checks if any extension is neccesarry and if so, proceeds to wire extend the bus if self.N < N: # Adding wires into current bus's wires list (wire names are concatenated from bus prefix and their index position inside the bus in square brackets) self.bus += [Wire(name=prefix+f"[{i}]", prefix=prefix, index=i, parent_bus=self) for i in range(self.N, N)] + if last_wire_extend is True: + for w_index in range(self.N, N): + self.connect(bus_wire_index=w_index, inner_component_out_wire=self.get_wire(self.N - 1)) self.N = N + def get_wire(self, wire_index: int = 0): """Retrieves a wire from the bus by a given index. @@ -536,7 +546,7 @@ class Bus():

            Methods

            -def bus_extend(self, N: int, prefix: str = 'bus') +def bus_extend(self, N: int, prefix: str = 'bus', last_wire_extend: bool = True)

            Provides bus extension to contain more wires.

            @@ -546,22 +556,28 @@ class Bus():
            Number of wires in the bus. Defaults to 1.
            prefix : str, optional
            Prefix name of the bus. Defaults to "bus".
            +
            last_wire_extend : bool, optional
            +
            Specifies whether the last wire of the bus should be extended (connected) to all the extending wires. Defaults to True.
            Expand source code -
            def bus_extend(self, N: int, prefix: str = "bus"):
            +
            def bus_extend(self, N: int, prefix: str = "bus", last_wire_extend: bool = True):
                 """Provides bus extension to contain more wires.
             
                 Args:
                     N (int): Number of wires in the bus. Defaults to 1.
                     prefix (str, optional): Prefix name of the bus. Defaults to "bus".
            +        last_wire_extend (bool, optional): Specifies whether the last wire of the bus should be extended (connected) to all the extending wires. Defaults to True.
                 """
                 # Checks if any extension is neccesarry and if so, proceeds to wire extend the bus
                 if self.N < N:
                     # Adding wires into current bus's wires list (wire names are concatenated from bus prefix and their index position inside the bus in square brackets)
                     self.bus += [Wire(name=prefix+f"[{i}]", prefix=prefix, index=i, parent_bus=self) for i in range(self.N, N)]
            +        if last_wire_extend is True:
            +            for w_index in range(self.N, N):
            +                self.connect(bus_wire_index=w_index, inner_component_out_wire=self.get_wire(self.N - 1))
                     self.N = N