mirror of
https://github.com/ehw-fit/ariths-gen.git
synced 2025-04-10 17:22:11 +01:00
Added documentation to Recursive multiplier and hopefully fixed some issues with popcount output generation.
This commit is contained in:
parent
4e331f0525
commit
739d5fafce
@ -54,8 +54,9 @@ class GeneralCircuit():
|
||||
self.out = Bus(outname, out_N, out_bus=True, signed=signed)
|
||||
|
||||
self.components = []
|
||||
self.circuit_wires = []
|
||||
self._prefixes = [] # TODO rename to fullname and add distinct attr for prefix, name, suffix
|
||||
self.circuit_gates = []
|
||||
self.circuit_wires = []
|
||||
self.signed = signed
|
||||
self.c_data_type = "int64_t" if self.signed is True else "uint64_t"
|
||||
self.pyc = None # Python compiled function
|
||||
@ -88,11 +89,25 @@ class GeneralCircuit():
|
||||
def add_component(self, component):
|
||||
"""Adds a component into list of circuit's inner subcomponents.
|
||||
|
||||
Additionally it adds all the gates of the component to the circuit's list of gates and all
|
||||
sbcomponents prefixes to check for naming duplicates which could cause issues in the circuit generation.
|
||||
|
||||
Args:
|
||||
component: Subcomponent to be added into list of components composing described circuit.
|
||||
"""
|
||||
prefixes = [c.prefix for c in self.components]
|
||||
assert component.prefix not in prefixes, f"Component with prefix {component.prefix} already exists in the circuit."
|
||||
# TODO will be redone in ArithsGen rework
|
||||
# We should probably check also wire names for especially hierarchical generation
|
||||
if isinstance(component, TwoInputLogicGate):
|
||||
if component.disable_generation is False:
|
||||
self.circuit_gates.append(component)
|
||||
else:
|
||||
self.circuit_gates.extend(component.get_circuit_gates())
|
||||
for prefix in component._prefixes:
|
||||
assert prefix not in self._prefixes, f"Component with prefix {prefix} already exists in the circuit."
|
||||
self._prefixes.extend(component._prefixes)
|
||||
|
||||
assert component.prefix not in self._prefixes, f"Component with prefix {component.prefix} already exists in the circuit."
|
||||
self._prefixes.append(component.prefix)
|
||||
self.components.append(component)
|
||||
return component
|
||||
|
||||
@ -227,14 +242,13 @@ class GeneralCircuit():
|
||||
else:
|
||||
return len(self.circuit_wires)+2
|
||||
|
||||
def get_cgp_wires(self):
|
||||
def get_circuit_wires(self):
|
||||
"""Gets a list of all wires in circuit along with their index position for cgp chromosome generation and stores them inside `self.circuit_wires` list.
|
||||
|
||||
Constant wire with value 0 has constant index of 0.
|
||||
Constant wire with value 1 has constant index of 1.
|
||||
Other wires indexes start counting from 2 and up.
|
||||
"""
|
||||
self.circuit_wires = []
|
||||
circuit_wires_names = []
|
||||
|
||||
for input in self.inputs:
|
||||
@ -263,6 +277,7 @@ class GeneralCircuit():
|
||||
(gate.out, gate.out.name, self.save_wire_id(wire=gate.out)))
|
||||
circuit_wires_names.append(gate.out.name)
|
||||
|
||||
|
||||
def get_circuit_wire_index(self, wire: Wire):
|
||||
"""Searches for circuit's wire unique index position within the circuit. Used for cgp chromosome generation.
|
||||
|
||||
@ -773,7 +788,7 @@ class GeneralCircuit():
|
||||
Returns:
|
||||
str: CGP chromosome parameters of described arithmetic circuit.
|
||||
"""
|
||||
self.circuit_gates = self.get_circuit_gates()
|
||||
# self.circuit_gates = self.get_circuit_gates() TODO delete
|
||||
return f"{{{sum(input_bus.N for input_bus in self.inputs)},{self.out.N},1,{len(self.circuit_gates)},2,1,0}}"
|
||||
|
||||
def get_triplets_cgp(self):
|
||||
@ -789,7 +804,7 @@ class GeneralCircuit():
|
||||
Returns:
|
||||
str: List of triplets each describing logic function of corresponding two input logic gate and as a whole describe the arithmetic circuit.
|
||||
"""
|
||||
self.get_cgp_wires()
|
||||
self.get_circuit_wires()
|
||||
return "".join([g.get_triplet_cgp(a_id=self.get_circuit_wire_index(g.a), out_id=self.get_circuit_wire_index(g.out)) if isinstance(g, OneInputLogicGate) else
|
||||
g.get_triplet_cgp(a_id=self.get_circuit_wire_index(g.a), b_id=self.get_circuit_wire_index(g.b), out_id=self.get_circuit_wire_index(g.out)) for g in self.circuit_gates])
|
||||
|
||||
|
@ -22,6 +22,28 @@ import math
|
||||
class UnsignedAccurateTwoBitMultiplier(MultiplierCircuit):
|
||||
"""Class representing unsigned two-bit accurate multiplier.
|
||||
|
||||
```
|
||||
A1B1 A1B0 A0B1 A0B0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐
|
||||
│AND│ │AND│ │AND│ │AND│
|
||||
└─┬─┘ └─┬─┘ └─┬─┘ └─┬─┘
|
||||
│ └──┬──┐└┬─┐ │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ ┌▼─▼┐│ │
|
||||
│ │ │AND││ │
|
||||
│ │ └─┬─┘│ │
|
||||
└─────┐ ┌─┼───┘┌─┘ │
|
||||
│ │ └──┐ │ │
|
||||
┌◄─►┐ ┌▼─▼┐ ┌▼─▼┐ │
|
||||
│AND│ │XOR│ │XOR│ │
|
||||
└─┬─┘ └─┬─┘ └─┬─┘ │
|
||||
│ │ │ │
|
||||
▼ ▼ ▼ ▼
|
||||
O3 O2 O1 O0
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
@ -77,6 +99,22 @@ class UnsignedApproximateTwoBitMultiplierM1(MultiplierCircuit):
|
||||
|
||||
M1 ax variant defined here: https://ieeexplore.ieee.org/document/8727537
|
||||
|
||||
```
|
||||
A1B1 A1B0 A0B1 A0B0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐
|
||||
│AND│ │AND│ │AND│ │AND│
|
||||
└─┬─┘ └─┬─┘ └─┬─┘ └─┬─┘
|
||||
│ │ └┐ │
|
||||
│ └─────┐ │ │
|
||||
└──────┐ ┌▼─▼┐ │
|
||||
│ │ OR│ │
|
||||
│ └─┬─┘ │
|
||||
│ │ │
|
||||
▼ ▼ ▼ ▼
|
||||
O3=0 O2 O1 O0
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
@ -128,6 +166,29 @@ class UnsignedApproximateTwoBitMultiplierM2(MultiplierCircuit):
|
||||
|
||||
M2 ax variant defined here: https://ieeexplore.ieee.org/document/8727537
|
||||
|
||||
```
|
||||
A1B1 A1B0 A0B1
|
||||
│ │ │ │ │ │
|
||||
┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐
|
||||
│AND│ │AND│ │AND│
|
||||
└─┬─┘ └─┬─┘ └─┬─┘
|
||||
│ │┌─────┴┐
|
||||
│ ┌┴┼────┐ │
|
||||
│ │ │ │ │
|
||||
│ ┌▼─▼┐ ┌▼─▼┐
|
||||
│ │XOR│ │AND│
|
||||
│ └─┬─┘ └─┬─┘
|
||||
└─────┐ ┌─────┼──────┤
|
||||
│ │ │ │
|
||||
┌▼─▼┐ │ │
|
||||
│XOR│ │ │
|
||||
└─┬─┘ │ │
|
||||
┌──────┼──────┼──────┤
|
||||
│ │ │ │
|
||||
▼ ▼ ▼ ▼
|
||||
O3 O2 O1 O0
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
@ -181,6 +242,33 @@ class UnsignedApproximateTwoBitMultiplierM3(MultiplierCircuit):
|
||||
|
||||
M3 ax variant defined here: https://ieeexplore.ieee.org/document/8727537
|
||||
|
||||
```
|
||||
A1B1 A1B0 A0B1 A0B0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐
|
||||
│AND│ │AND│ │AND│ │AND│
|
||||
└─┬─┘ └─┬─┘ └─┬─┘ └─┬─┘
|
||||
│ │ └┐ │
|
||||
│ │ │ │
|
||||
│ └─────┐ │ │
|
||||
│ ┌▼─▼┐ │
|
||||
│ │ OR│ │
|
||||
│ └─┬─┘ │
|
||||
│┌─────┬──────┼──────┤
|
||||
││ │ │ │
|
||||
││ ┌─▼─┐ │ │
|
||||
││ │NOT│ │ │
|
||||
││ └─┬─┘ │ │
|
||||
┌┴┼────┐└┐ │ │
|
||||
│ │ │ │ │ │
|
||||
┌▼─▼┐ ┌▼─▼┐ │ │
|
||||
│AND│ │AND│ │ │
|
||||
└─┬─┘ └─┬─┘ │ │
|
||||
│ │ │ │
|
||||
▼ ▼ ▼ ▼
|
||||
O3 O2 O1 O0
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
@ -236,6 +324,22 @@ class UnsignedApproximateTwoBitMultiplierM4(MultiplierCircuit):
|
||||
|
||||
M4 ax variant defined here: https://ieeexplore.ieee.org/document/8727537
|
||||
|
||||
```
|
||||
A1B1 A1B0 A0B1 A0B0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐ ┌▼─▼┐
|
||||
│AND│ │AND│ │AND│ │AND│
|
||||
└─┬─┘ └─┬─┘ └─┬─┘ └─┬─┘
|
||||
│ │ └┐ │
|
||||
│ └─────┐ │ │
|
||||
└──────┐ ┌▼─▼┐ │
|
||||
│ │XOR│ │
|
||||
│ └─┬─┘ │
|
||||
│ │ │
|
||||
▼ ▼ ▼ ▼
|
||||
O3=0 O2 O1 O0
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
@ -285,7 +389,13 @@ class SignedApproximateTwoBitMultiplierM4(MultiplierCircuit):
|
||||
class UnsignedRecursiveMultiplier(MultiplierCircuit):
|
||||
"""Class representing unsigned recursive multiplier.
|
||||
|
||||
TODO
|
||||
Input bit-vector length N can be any power of two greater than 1 (e.g. 2, 4, 8, ...).
|
||||
|
||||
The internal structure of the recursive multiplier is composed of subsequent two-bit submultipliers provided in the input `submultipliers` list.
|
||||
The `submultipliers` list should contain the classes of the two-bit submultipliers that will be used for instantiation. If None are provided, accurate two-bit submultipliers are assumed.
|
||||
|
||||
The number of submultipliers required is equal to (N/2)² for N > 2. For N = 2, only one two-bit submultiplier is required.
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
|
@ -4,11 +4,18 @@ from ariths_gen.multi_bit_circuits.others.popcount import (
|
||||
)
|
||||
|
||||
from ariths_gen.multi_bit_circuits.others.bit_reduce import (
|
||||
BitReduce, AndReduce, OrReduce
|
||||
BitReduce,
|
||||
AndReduce,
|
||||
OrReduce
|
||||
)
|
||||
|
||||
from ariths_gen.multi_bit_circuits.others.compare import (
|
||||
UnsignedCompareLT, UnsignedCompareLTE, UnsignedCompareGT, UnsignedCompareGTE
|
||||
UnsignedCompareLT,
|
||||
UnsignedCompareLTE,
|
||||
UnsignedCompareGT,
|
||||
UnsignedCompareGTE
|
||||
)
|
||||
|
||||
from ariths_gen.multi_bit_circuits.others.popcount_compare import PopCountCompare
|
||||
from ariths_gen.multi_bit_circuits.others.popcount_compare import (
|
||||
PopCountCompare
|
||||
)
|
||||
|
@ -80,10 +80,10 @@ class BitReduce(GeneralCircuit):
|
||||
|
||||
|
||||
class OrReduce(BitReduce):
|
||||
def __init__(self, a: Bus, prefix : str = "", name : str = "orreduce", **kwargs):
|
||||
def __init__(self, a: Bus, prefix: str = "", name: str = "orreduce", **kwargs):
|
||||
super().__init__(a=a, gate=OrGate, prefix=prefix, name=name, **kwargs)
|
||||
|
||||
|
||||
class AndReduce(BitReduce):
|
||||
def __init__(self, a: Bus, prefix : str = "", name : str = "orreduce", **kwargs):
|
||||
def __init__(self, a: Bus, prefix: str = "", name: str = "andreduce", **kwargs):
|
||||
super().__init__(a=a, gate=AndGate, prefix=prefix, name=name, **kwargs)
|
@ -83,7 +83,7 @@ class UnsignedCompareLTE(GeneralCircuit):
|
||||
Returns true if a <= b
|
||||
"""
|
||||
|
||||
def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_lt", **kwargs):
|
||||
def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_lte", **kwargs):
|
||||
self.a = a
|
||||
self.b = b
|
||||
self.N = max(a.N, b.N)
|
||||
|
@ -68,8 +68,8 @@ class UnsignedPopCount(GeneralCircuit):
|
||||
return a
|
||||
else:
|
||||
half = a.N // 2
|
||||
b_in = Bus(N=half, prefix=f"b_inn{depth}A")
|
||||
c_in = Bus(N=a.N - half, prefix=f"b_inn{depth}B")
|
||||
b_in = Bus(N=half, prefix=f"b_inn_{branch}_{depth}A")
|
||||
c_in = Bus(N=a.N - half, prefix=f"b_inn_{branch}_{depth}B")
|
||||
#print(a, half, a.N)
|
||||
|
||||
|
||||
@ -87,4 +87,4 @@ class UnsignedPopCount(GeneralCircuit):
|
||||
|
||||
sumbus = create_tree(self.a,0, "X")
|
||||
#print(sumbus)
|
||||
self.out.connect_bus(sumbus )
|
||||
self.out.connect_bus(sumbus)
|
||||
|
@ -59,7 +59,7 @@ class PopCountCompare(GeneralCircuit):
|
||||
▼
|
||||
"""
|
||||
|
||||
def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_lt", **kwargs):
|
||||
def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "popcnt_cmp", **kwargs):
|
||||
self.a = a
|
||||
self.b = b
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
import os
|
||||
import sys
|
||||
# Add the parent directory to the system path
|
||||
DIR_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(0, os.path.join(DIR_PATH, '..'))
|
||||
|
||||
from io import StringIO
|
||||
from ariths_gen.core.cgp_circuit import UnsignedCGPCircuit
|
||||
from ariths_gen.wire_components import (
|
||||
|
@ -1,3 +1,9 @@
|
||||
import os
|
||||
import sys
|
||||
# Add the parent directory to the system path
|
||||
DIR_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(0, os.path.join(DIR_PATH, '..'))
|
||||
|
||||
from ariths_gen.wire_components import (
|
||||
Wire,
|
||||
ConstantWireValue0,
|
||||
|
Loading…
x
Reference in New Issue
Block a user