mirror of
https://github.com/ehw-fit/ariths-gen.git
synced 2025-04-10 17:22:11 +01:00
Devel (#2)
* CGP format * CGP format minor * General MAC circuit * Modified definition of MAC class to allow proper generation of output representations. * auto test MAC * test all * Made some minor changes and updated creation of MAC circuit. * Updated logic behind generating export representations, mainly focused around circuit and its buses and subcomponents namings. * Made some minor changes concerning proper exportation of multiplier circuits. Co-authored-by: honzastor <jan.klhufek@gmail.com>
This commit is contained in:
parent
87a7f2b8bb
commit
bee2086705
7
.github/workflows/generate.yml
vendored
7
.github/workflows/generate.yml
vendored
@ -30,6 +30,8 @@ jobs:
|
||||
run: python -c "import sys; print(sys.version)"
|
||||
- name: Run generating
|
||||
run: python generate_test.py
|
||||
- name: Run generating
|
||||
run: python generate_mac.py
|
||||
- name: Upload results
|
||||
uses: actions/upload-artifact@v1.0.0
|
||||
with:
|
||||
@ -62,6 +64,11 @@ jobs:
|
||||
cd tests
|
||||
bash test_circuits_cgp.sh
|
||||
cd ..
|
||||
- name: Run MAC testing
|
||||
run: |
|
||||
cd tests
|
||||
bash test_mac.sh
|
||||
cd ..
|
||||
|
||||
# Only on main thread
|
||||
documentation:
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,5 +8,6 @@ dist/
|
||||
test_circuits/
|
||||
tests/tmp.exe
|
||||
tests/tmp.c
|
||||
html/
|
||||
|
||||
*.egg-info
|
6
.testall.sh
Normal file
6
.testall.sh
Normal file
@ -0,0 +1,6 @@
|
||||
python generate_test.py
|
||||
python generate_mac.py
|
||||
cd tests
|
||||
bash test_mac.sh
|
||||
bash test_circuits.sh
|
||||
bash test_circuits_cgp.sh
|
@ -2,6 +2,8 @@ from .arithmetic_circuit import (
|
||||
ArithmeticCircuit
|
||||
)
|
||||
|
||||
from .general_circuit import (GeneralCircuit )
|
||||
|
||||
from .multiplier_circuit import (
|
||||
MultiplierCircuit
|
||||
)
|
||||
|
@ -14,12 +14,34 @@ class ArithmeticCircuit():
|
||||
The __init__ method fills some mandatory attributes concerning arithmetic circuit
|
||||
that are later used for generation into various representations.
|
||||
"""
|
||||
def __init__(self):
|
||||
|
||||
def __init__(self, a, b, prefix: str, name: str, out_N: int, inner_component: bool = False, one_bit_circuit: bool = False):
|
||||
if one_bit_circuit is False:
|
||||
if prefix == "":
|
||||
self.prefix = name
|
||||
else:
|
||||
self.prefix = prefix + "_" + name
|
||||
|
||||
self.inner_component = inner_component
|
||||
if self.inner_component is True:
|
||||
self.a = Bus(prefix=f"{self.prefix}_{a.prefix}", wires_list=a.bus)
|
||||
self.b = Bus(prefix=f"{self.prefix}_{b.prefix}", wires_list=b.bus)
|
||||
|
||||
if a.is_output_bus():
|
||||
self.a.connect_bus(connecting_bus=a)
|
||||
if b.is_output_bus():
|
||||
self.b.connect_bus(connecting_bus=b)
|
||||
else:
|
||||
self.a = Bus(prefix=f"{a.prefix}", wires_list=a.bus)
|
||||
self.b = Bus(prefix=f"{b.prefix}", wires_list=b.bus)
|
||||
|
||||
# N output wires for given circuit
|
||||
self.out = Bus(self.prefix+"_out", out_N, out_bus=True)
|
||||
|
||||
self.components = []
|
||||
self.circuit_wires = []
|
||||
self.circuit_gates = []
|
||||
self.c_data_type = "uint64_t"
|
||||
self.N = 1
|
||||
|
||||
def add_component(self, component):
|
||||
"""Adds a component into list of circuit's inner subcomponents.
|
||||
@ -123,8 +145,10 @@ class ArithmeticCircuit():
|
||||
list: List of unique component types describing the circuit.
|
||||
"""
|
||||
gate_comps = self.get_unique_types(components=self.get_circuit_gates())
|
||||
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())
|
||||
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())
|
||||
|
||||
all_components = gate_comps + one_bit_comps + multi_bit_comps
|
||||
return all_components
|
||||
@ -172,23 +196,31 @@ class ArithmeticCircuit():
|
||||
"""
|
||||
self.circuit_wires = []
|
||||
if isinstance(self.a, Bus):
|
||||
[self.circuit_wires.append((w, f"{w.name}", self.save_wire_id(wire=w))) for w in self.a.bus]
|
||||
[self.circuit_wires.append((w, f"{w.name}", self.save_wire_id(wire=w))) for w in self.b.bus]
|
||||
[self.circuit_wires.append(
|
||||
(w, f"{w.name}", self.save_wire_id(wire=w))) for w in self.a.bus]
|
||||
[self.circuit_wires.append(
|
||||
(w, f"{w.name}", self.save_wire_id(wire=w))) for w in self.b.bus]
|
||||
else:
|
||||
self.circuit_wires.append((self.a, f"{self.a.name}", self.save_wire_id(wire=self.a)))
|
||||
self.circuit_wires.append((self.b, f"{self.b.name}", self.save_wire_id(wire=self.b)))
|
||||
self.circuit_wires.append(
|
||||
(self.a, f"{self.a.name}", self.save_wire_id(wire=self.a)))
|
||||
self.circuit_wires.append(
|
||||
(self.b, f"{self.b.name}", self.save_wire_id(wire=self.b)))
|
||||
if hasattr(self, 'c'):
|
||||
self.circuit_wires.append((self.c, f"{self.c.name}", self.save_wire_id(wire=self.c)))
|
||||
self.circuit_wires.append(
|
||||
(self.c, f"{self.c.name}", self.save_wire_id(wire=self.c)))
|
||||
|
||||
for gate in self.circuit_gates:
|
||||
if not [item for item in self.circuit_wires if gate.a.name == item[1]]:
|
||||
self.circuit_wires.append((gate.a, gate.a.name, self.save_wire_id(wire=gate.a)))
|
||||
self.circuit_wires.append(
|
||||
(gate.a, gate.a.name, self.save_wire_id(wire=gate.a)))
|
||||
|
||||
if hasattr(gate, 'b') and not [item for item in self.circuit_wires if gate.b.name == item[1]]:
|
||||
self.circuit_wires.append((gate.b, gate.b.name, self.save_wire_id(wire=gate.b)))
|
||||
self.circuit_wires.append(
|
||||
(gate.b, gate.b.name, self.save_wire_id(wire=gate.b)))
|
||||
|
||||
if not [item for item in self.circuit_wires if gate.out.name == item[1]]:
|
||||
self.circuit_wires.append((gate.out, gate.out.name, self.save_wire_id(wire=gate.out)))
|
||||
self.circuit_wires.append(
|
||||
(gate.out, gate.out.name, self.save_wire_id(wire=gate.out)))
|
||||
|
||||
def get_circuit_wire_index(self, wire: Wire):
|
||||
"""Searches for circuit's wire unique index position within the circuit. Used for cgp chromosome generation.
|
||||
@ -283,8 +315,10 @@ class ArithmeticCircuit():
|
||||
str: Hierarchical C code of multi-bit arithmetic circuit's function block description.
|
||||
"""
|
||||
# Obtain proper circuit name with its bit width
|
||||
circuit_prefix = self.__class__(a=Bus("a"), b=Bus("b")).prefix + str(self.N)
|
||||
circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(N=self.N, prefix="b"), prefix=circuit_prefix)
|
||||
circuit_prefix = 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)
|
||||
return f"{circuit_block.get_circuit_c()}\n\n"
|
||||
|
||||
def get_declarations_c_hier(self):
|
||||
@ -369,6 +403,7 @@ class ArithmeticCircuit():
|
||||
|
||||
""" VERILOG CODE GENERATION """
|
||||
# FLAT VERILOG #
|
||||
|
||||
def get_prototype_v(self):
|
||||
"""Generates Verilog code module header to describe corresponding arithmetic circuit's interface in Verilog code.
|
||||
|
||||
@ -433,8 +468,10 @@ class ArithmeticCircuit():
|
||||
str: Hierarchical Verilog code of multi-bit arithmetic circuit's function block description.
|
||||
"""
|
||||
# Obtain proper circuit name with its bit width
|
||||
circuit_prefix = self.__class__(a=Bus("a"), b=Bus("b")).prefix + str(self.N)
|
||||
circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(N=self.N, prefix="b"), prefix=circuit_prefix)
|
||||
circuit_prefix = 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)
|
||||
return f"{circuit_block.get_circuit_v()}\n\n"
|
||||
|
||||
def get_declarations_v_hier(self):
|
||||
@ -483,8 +520,10 @@ class ArithmeticCircuit():
|
||||
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_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(N=self.N, prefix="b"), prefix=circuit_prefix)
|
||||
circuit_prefix = 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)
|
||||
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"
|
||||
|
||||
@ -521,6 +560,7 @@ class ArithmeticCircuit():
|
||||
|
||||
""" BLIF CODE GENERATION """
|
||||
# FLAT BLIF #
|
||||
|
||||
def get_prototype_blif(self):
|
||||
"""Generates Blif code model name of described arithmetic circuit.
|
||||
|
||||
@ -603,7 +643,8 @@ class ArithmeticCircuit():
|
||||
f".subckt {circuit_type}" + \
|
||||
"".join([f" a[{self.a.bus.index(w)}]={self.a.prefix}[{self.a.bus.index(w)}]" for w in self.a.bus]) + \
|
||||
"".join([f" b[{self.b.bus.index(w)}]={self.b.prefix}[{self.b.bus.index(w)}]" for w in self.b.bus]) + \
|
||||
"".join([f" {circuit_type}_out[{self.out.bus.index(o)}]={o.name}" for o in self.out.bus]) + "\n"
|
||||
"".join(
|
||||
[f" {circuit_type}_out[{self.out.bus.index(o)}]={o.name}" for o in self.out.bus]) + "\n"
|
||||
|
||||
def get_circuit_blif(self):
|
||||
"""Generates hierarchical Blif code subcomponent's function block.
|
||||
@ -635,8 +676,8 @@ class ArithmeticCircuit():
|
||||
str: Hierarchical Blif code of multi-bit arithmetic circuit's function block description.
|
||||
"""
|
||||
# Obtain proper circuit name with its bit width
|
||||
circuit_prefix = self.__class__(a=Bus("a"), b=Bus("b")).prefix + str(self.N)
|
||||
circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(N=self.N, prefix="b"), prefix=circuit_prefix)
|
||||
circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(
|
||||
N=self.N, prefix="b"))
|
||||
return f"{circuit_block.get_circuit_blif()}"
|
||||
|
||||
# Generating hierarchical BLIF code representation of circuit
|
||||
@ -652,6 +693,7 @@ class ArithmeticCircuit():
|
||||
|
||||
""" CGP CODE GENERATION """
|
||||
# FLAT CGP #
|
||||
|
||||
def get_parameters_cgp(self):
|
||||
"""Generates CGP chromosome parameters of corresponding arithmetic circuit.
|
||||
|
||||
@ -678,8 +720,8 @@ class ArithmeticCircuit():
|
||||
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()
|
||||
return "".join([g.get_triplet_cgp(a_id=self.get_circuit_wire_index(g.a)) 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)) for g in self.circuit_gates])
|
||||
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])
|
||||
|
||||
def get_outputs_cgp(self):
|
||||
"""Generates list of output wires indexes of described arithmetic circuit from MSB to LSB.
|
||||
|
733
ariths_gen/core/arithmetic_circuits/general_circuit.py
Normal file
733
ariths_gen/core/arithmetic_circuits/general_circuit.py
Normal file
@ -0,0 +1,733 @@
|
||||
from ariths_gen.core.logic_gate_circuits.logic_gate_circuit import OneInputLogicGate, TwoInputLogicGate
|
||||
|
||||
from ariths_gen.wire_components import (
|
||||
Wire,
|
||||
ConstantWireValue0,
|
||||
ConstantWireValue1,
|
||||
Bus
|
||||
)
|
||||
|
||||
|
||||
class GeneralCircuit():
|
||||
"""Class represents a general arithmetic circuit and ensures their generation to various representations.
|
||||
|
||||
The __init__ method fills some mandatory attributes concerning arithmetic circuit
|
||||
that are later used for generation into various representations.
|
||||
"""
|
||||
|
||||
def __init__(self, prefix: str, name: str, out_N: int, inner_component: bool = False, inputs: list=[]):
|
||||
if prefix == "":
|
||||
self.prefix = name
|
||||
else:
|
||||
self.prefix = prefix + "_" + name
|
||||
self.inner_component = inner_component
|
||||
self.inputs = inputs
|
||||
self.out = Bus(self.prefix+"_out", out_N, out_bus=True)
|
||||
|
||||
self.components = []
|
||||
self.circuit_wires = []
|
||||
self.circuit_gates = []
|
||||
self.c_data_type = "uint64_t"
|
||||
|
||||
def add_component(self, component):
|
||||
"""Adds a component into list of circuit's inner subcomponents.
|
||||
|
||||
Args:
|
||||
component: Subcomponent to be added into list of components composing described circuit.
|
||||
"""
|
||||
self.components.append(component)
|
||||
return component
|
||||
|
||||
def get_previous_component(self, number: int = 1):
|
||||
"""Retrieves previously added composite subcomponent from circuit's list of components.
|
||||
|
||||
Args:
|
||||
number (int, optional): Offset indicating which lastly added component will be retrieved. Defaults to 1.
|
||||
|
||||
Returns:
|
||||
component: Desired previously added composite component.
|
||||
"""
|
||||
return self.components[-number]
|
||||
|
||||
def get_instance_num(self, cls, count_disabled_gates: bool = True):
|
||||
"""Informs how many instances of the same type are already present inside circuit's components list.
|
||||
|
||||
Args:
|
||||
cls (type): Class type for which to count the number of instances in the components list.
|
||||
count_disabled_gates (bool, optional): Indicates whether logic gates that aren't generated should be also counted. Defaults to True.
|
||||
Returns:
|
||||
int: Number of instances of the same class type.
|
||||
"""
|
||||
if issubclass(cls, TwoInputLogicGate) and count_disabled_gates is False:
|
||||
return sum(isinstance(c, cls) for c in self.components if isinstance(c, cls) and c.disable_generation is False)
|
||||
else:
|
||||
return sum(isinstance(c, cls) for c in self.components)
|
||||
|
||||
def get_circuit_gates(self):
|
||||
"""Gets a list of all the logic gates in circuit that should be generated.
|
||||
|
||||
Returns:
|
||||
list: List of composite logic gates.
|
||||
"""
|
||||
gates = []
|
||||
for c in self.components:
|
||||
if isinstance(c, TwoInputLogicGate):
|
||||
if c.disable_generation is False:
|
||||
gates.append(c)
|
||||
else:
|
||||
gates.extend((c.get_circuit_gates()))
|
||||
return gates
|
||||
|
||||
def get_one_bit_components(self):
|
||||
"""Retrieves a list of all the one bit circuits (besides logic gates) present as subcomponents inside the circuit.
|
||||
|
||||
Returns:
|
||||
list: List of composite one bit circuits.
|
||||
"""
|
||||
one_bit_comps = []
|
||||
for c in self.components:
|
||||
if isinstance(c, TwoInputLogicGate):
|
||||
continue
|
||||
elif isinstance(getattr(c, 'a'), Wire):
|
||||
one_bit_comps.append(c)
|
||||
else:
|
||||
one_bit_comps.extend(c.get_one_bit_components())
|
||||
|
||||
return one_bit_comps
|
||||
|
||||
def get_multi_bit_components(self):
|
||||
"""Retrieves a list of all the multi bit circuits present as subcomponents inside the circuit.
|
||||
|
||||
Returns:
|
||||
list: List of composite multi bit circuits.
|
||||
"""
|
||||
multi_bit_comps = []
|
||||
for c in self.components:
|
||||
if isinstance(c, TwoInputLogicGate):
|
||||
continue
|
||||
elif isinstance(getattr(c, 'a'), Wire):
|
||||
continue
|
||||
else:
|
||||
multi_bit_comps.append(c)
|
||||
return multi_bit_comps
|
||||
|
||||
@staticmethod
|
||||
def get_unique_types(components: list):
|
||||
"""Retrieves just the unique representatives of class types present inside the provided components list.
|
||||
|
||||
Args:
|
||||
components (list): List of components to be filtered.
|
||||
|
||||
Returns:
|
||||
list: List of unique composite class types.
|
||||
"""
|
||||
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.
|
||||
|
||||
Returning list consists of only the unique types of logic gates, one bit circuits and multi bit circuits.
|
||||
|
||||
Returns:
|
||||
list: List of unique component types describing the circuit.
|
||||
"""
|
||||
gate_comps = self.get_unique_types(components=self.get_circuit_gates())
|
||||
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())
|
||||
|
||||
all_components = gate_comps + one_bit_comps + multi_bit_comps
|
||||
return all_components
|
||||
|
||||
def get_sum_wire(self):
|
||||
"""Get output wire carrying sum value.
|
||||
|
||||
Returns:
|
||||
Wire: Return sum wire.
|
||||
"""
|
||||
return self.out.get_wire(0)
|
||||
|
||||
def get_carry_wire(self):
|
||||
"""Get output wire carrying carry out value.
|
||||
|
||||
Returns:
|
||||
Wire: Return carry out wire.
|
||||
"""
|
||||
return self.out.get_wire(1)
|
||||
|
||||
def save_wire_id(self, wire: Wire):
|
||||
"""Returns appropriate wire index position within the circuit.
|
||||
|
||||
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.
|
||||
|
||||
Args:
|
||||
wire (Wire): Wire that will be stored at this circuit index position.
|
||||
|
||||
Returns:
|
||||
int: Wire's index position within circuit.
|
||||
"""
|
||||
if wire.is_const():
|
||||
return wire.cgp_const
|
||||
else:
|
||||
return len([w[0] for w in self.circuit_wires if w[0].is_const() is False]) + 2
|
||||
|
||||
def get_cgp_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 = []
|
||||
if isinstance(self.a, Bus):
|
||||
[self.circuit_wires.append(
|
||||
(w, f"{w.name}", self.save_wire_id(wire=w))) for w in self.a.bus]
|
||||
[self.circuit_wires.append(
|
||||
(w, f"{w.name}", self.save_wire_id(wire=w))) for w in self.b.bus]
|
||||
else:
|
||||
self.circuit_wires.append(
|
||||
(self.a, f"{self.a.name}", self.save_wire_id(wire=self.a)))
|
||||
self.circuit_wires.append(
|
||||
(self.b, f"{self.b.name}", self.save_wire_id(wire=self.b)))
|
||||
if hasattr(self, 'c'):
|
||||
self.circuit_wires.append(
|
||||
(self.c, f"{self.c.name}", self.save_wire_id(wire=self.c)))
|
||||
|
||||
for gate in self.circuit_gates:
|
||||
if not [item for item in self.circuit_wires if gate.a.name == item[1]]:
|
||||
self.circuit_wires.append(
|
||||
(gate.a, gate.a.name, self.save_wire_id(wire=gate.a)))
|
||||
|
||||
if hasattr(gate, 'b') and not [item for item in self.circuit_wires if gate.b.name == item[1]]:
|
||||
self.circuit_wires.append(
|
||||
(gate.b, gate.b.name, self.save_wire_id(wire=gate.b)))
|
||||
|
||||
if not [item for item in self.circuit_wires if gate.out.name == item[1]]:
|
||||
self.circuit_wires.append(
|
||||
(gate.out, gate.out.name, self.save_wire_id(wire=gate.out)))
|
||||
|
||||
def get_circuit_wire_index(self, wire: Wire):
|
||||
"""Searches for circuit's wire unique index position within the circuit. Used for cgp chromosome generation.
|
||||
|
||||
Args:
|
||||
wire (Wire): Wire to retrieve index position of.
|
||||
|
||||
Returns:
|
||||
int: Wire's index position number within the circuit.
|
||||
"""
|
||||
if wire.is_const():
|
||||
return wire.cgp_const
|
||||
else:
|
||||
for w in self.circuit_wires:
|
||||
if wire.name == w[1]:
|
||||
return w[2]
|
||||
|
||||
""" C CODE GENERATION """
|
||||
# FLAT C #
|
||||
@staticmethod
|
||||
def get_includes_c():
|
||||
"""Generates necessary C library includes for output representation.
|
||||
|
||||
Returns:
|
||||
str: C code library includes.
|
||||
"""
|
||||
return f"#include <stdio.h>\n#include <stdint.h>\n\n"
|
||||
|
||||
def get_prototype_c(self):
|
||||
"""Generates C code function header to describe corresponding arithmetic circuit's interface in C code.
|
||||
|
||||
Returns:
|
||||
str: Function's name and parameters in C code.
|
||||
"""
|
||||
return f"{self.c_data_type} {self.prefix}(" + ",".join([f"{self.c_data_type} {x.prefix}" for x in self.inputs]) + ")" + "{" + "\n"
|
||||
|
||||
def get_declaration_c_flat(self):
|
||||
"""Generates flat C code declaration of input/output circuit wires.
|
||||
|
||||
Returns:
|
||||
str: Flat C code arithmetic circuit's wires declaration.
|
||||
"""
|
||||
return f"".join([c.get_declaration_c_flat() for c in self.components])
|
||||
|
||||
def get_init_c_flat(self):
|
||||
"""Generates flat C code initialization and assignment of corresponding arithmetic circuit's input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Flat C code initialization of arithmetic circuit wires.
|
||||
"""
|
||||
return "".join([c.get_assign_c_flat() if isinstance(c, TwoInputLogicGate) else c.get_init_c_flat() for c in self.components])
|
||||
|
||||
def get_function_out_c_flat(self):
|
||||
"""Generates flat C code assignment of corresponding arithmetic circuit's output bus wires.
|
||||
|
||||
Returns:
|
||||
str: Flat C code containing output bus wires assignment.
|
||||
"""
|
||||
return self.out.return_bus_wires_values_c_flat()
|
||||
|
||||
# Generating flat C code representation of circuit
|
||||
def get_c_code_flat(self, file_object):
|
||||
"""Generates flat C code representation of corresponding arithmetic circuit.
|
||||
|
||||
Args:
|
||||
file_object (TextIOWrapper): Destination file object where circuit's representation will be written to.
|
||||
"""
|
||||
file_object.write(self.get_includes_c())
|
||||
file_object.write(self.get_prototype_c())
|
||||
file_object.write(self.out.get_declaration_c())
|
||||
file_object.write(self.get_declaration_c_flat()+"\n")
|
||||
file_object.write(self.get_init_c_flat()+"\n")
|
||||
file_object.write(self.get_function_out_c_flat())
|
||||
file_object.write(f" return {self.out.prefix}"+";\n}")
|
||||
file_object.close()
|
||||
|
||||
# HIERARCHICAL C #
|
||||
def get_function_blocks_c(self):
|
||||
"""Generates hierarchical C code representation of all subcomponents function blocks present in corresponding arithmetic circuit.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code of all subcomponents function blocks description.
|
||||
"""
|
||||
# Retrieve all unique component types composing this circuit
|
||||
self.component_types = self.get_component_types()
|
||||
return "".join([c.get_function_block_c() for c in self.component_types])
|
||||
|
||||
def get_function_block_c(self):
|
||||
"""Generates hierarchical C code representation of corresponding multi-bit arithmetic circuit used as function block in hierarchical circuit description.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code of multi-bit arithmetic circuit's function block description.
|
||||
"""
|
||||
# Obtain proper circuit name with its bit width
|
||||
circuit_prefix = self.__class__(
|
||||
a=Bus("a"), b=Bus("b")).prefix + str(self.N)
|
||||
circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(
|
||||
N=self.N, prefix="b"), prefix=circuit_prefix)
|
||||
return f"{circuit_block.get_circuit_c()}\n\n"
|
||||
|
||||
def get_declarations_c_hier(self):
|
||||
"""Generates hierarchical C code declaration of input/output circuit wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code containing unique declaration of arithmetic circuit wires.
|
||||
"""
|
||||
return "".join([c.get_declaration_c_hier() for c in self.components])
|
||||
|
||||
def get_declaration_c_hier(self):
|
||||
"""Generates hierarchical C code declaration of corresponding subcomponent input/output wires inside the upper component.
|
||||
|
||||
Generates wires used to connect input/output values to/from invocation of the corresponding function block into inner wires present
|
||||
inside the upper component from which function block has been invoked.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code of subcomponent arithmetic circuit's wires declaration.
|
||||
"""
|
||||
return f" {self.c_data_type} {self.a.prefix} = 0;\n" + \
|
||||
f" {self.c_data_type} {self.b.prefix} = 0;\n" + \
|
||||
f" {self.c_data_type} {self.out.prefix} = 0;\n"
|
||||
|
||||
def get_init_c_hier(self):
|
||||
"""Generates hierarchical C code initialization and assignment of corresponding arithmetic circuit's input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code initialization of arithmetic circuit wires.
|
||||
"""
|
||||
return "".join([c.get_gate_invocation_c() if isinstance(c, TwoInputLogicGate) else c.get_out_invocation_c(circuit_prefix=self.prefix) for c in self.components])
|
||||
|
||||
def get_out_invocation_c(self, circuit_prefix: str):
|
||||
"""Generates hierarchical C code invocation of corresponding arithmetic circuit's generated function block.
|
||||
|
||||
Assigns input values from other subcomponents into multi-bit input buses used as inputs for function block invocation.
|
||||
Assigns output values from invocation of the corresponding function block into inner wires present inside
|
||||
the upper component from which function block has been invoked.
|
||||
|
||||
Args:
|
||||
circuit_prefix (str): Prefix name of the upper component from which function block is being invoked.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code of subcomponent's C function invocation and output assignment.
|
||||
"""
|
||||
# Getting name of circuit type for proper C code generation without affecting actual generated composition
|
||||
circuit_type = self.prefix.replace(circuit_prefix+"_", "")
|
||||
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"
|
||||
|
||||
def get_function_out_c_hier(self):
|
||||
"""Generates hierarchical C code assignment of corresponding arithmetic circuit's output bus wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code containing output bus wires assignment.
|
||||
"""
|
||||
return self.out.return_bus_wires_values_c_hier()
|
||||
|
||||
def get_circuit_c(self):
|
||||
"""Generates hierarchical C code subcomponent's function block.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code of subcomponent's function block.
|
||||
"""
|
||||
return f"{self.get_prototype_c()}" + \
|
||||
f"{self.out.get_declaration_c()}" + \
|
||||
f"{self.get_declarations_c_hier()}\n" + \
|
||||
f"{self.get_init_c_hier()}\n" + \
|
||||
f"{self.get_function_out_c_hier()}" + \
|
||||
f" return {self.out.prefix}"+";\n}"
|
||||
|
||||
# Generating hierarchical C code representation of circuit
|
||||
def get_c_code_hier(self, file_object):
|
||||
"""Generates hierarchical C code representation of corresponding arithmetic circuit.
|
||||
|
||||
Args:
|
||||
file_object (TextIOWrapper): Destination file object where circuit's representation will be written to.
|
||||
"""
|
||||
file_object.write(self.get_includes_c())
|
||||
file_object.write(self.get_function_blocks_c())
|
||||
file_object.write(self.get_circuit_c())
|
||||
file_object.close()
|
||||
|
||||
""" VERILOG CODE GENERATION """
|
||||
# FLAT VERILOG #
|
||||
|
||||
def get_prototype_v(self):
|
||||
"""Generates Verilog code module header to describe corresponding arithmetic circuit's interface in Verilog code.
|
||||
|
||||
Returns:
|
||||
str: Module's name and parameters in Verilog code.
|
||||
"""
|
||||
return f"module {self.prefix}(" + ",".join(f"input [{x.N-1}:0] {x.prefix}" for x in self.inputs) + f", output [{self.out.N-1}:0] {self.out.prefix});\n"
|
||||
|
||||
def get_declaration_v_flat(self):
|
||||
"""Generates flat Verilog code declaration of input/output circuit wires.
|
||||
|
||||
Returns:
|
||||
str: Flat Verilog code arithmetic circuit's wires declaration.
|
||||
"""
|
||||
return f"".join([c.get_declaration_v_flat() for c in self.components])
|
||||
|
||||
def get_init_v_flat(self):
|
||||
"""Generates flat Verilog code initialization and assignment of corresponding arithmetic circuit's input/output buses wires.
|
||||
|
||||
Returns:
|
||||
str: Flat Verilog code initialization of arithmetic circuit wires.
|
||||
"""
|
||||
return "".join([c.get_assign_v_flat() if isinstance(c, TwoInputLogicGate) else c.get_init_v_flat() for c in self.components])
|
||||
|
||||
def get_function_out_v_flat(self):
|
||||
"""Generates flat Verilog code assignment of corresponding arithmetic circuit's output bus wires.
|
||||
|
||||
Returns:
|
||||
str: Flat Verilog code containing output bus wires assignment.
|
||||
"""
|
||||
return self.out.return_bus_wires_values_v_flat()
|
||||
|
||||
# Generating flat Verilog code representation of circuit
|
||||
def get_v_code_flat(self, file_object):
|
||||
"""Generates flat Verilog code representation of corresponding arithmetic circuit.
|
||||
|
||||
Args:
|
||||
file_object (TextIOWrapper): Destination file object where circuit's representation will be written to.
|
||||
"""
|
||||
file_object.write(self.get_prototype_v())
|
||||
file_object.write(self.get_declaration_v_flat()+"\n")
|
||||
file_object.write(self.get_init_v_flat() + "\n")
|
||||
file_object.write(self.get_function_out_v_flat())
|
||||
file_object.write(f"endmodule")
|
||||
file_object.close()
|
||||
|
||||
# HIERARCHICAL VERILOG #
|
||||
def get_function_blocks_v(self):
|
||||
"""Generates hierarchical Verilog code representation of all subcomponents function blocks present in corresponding arithmetic circuit.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code of all subcomponents function blocks description.
|
||||
"""
|
||||
# Retrieve all unique component types composing this circuit
|
||||
self.component_types = self.get_component_types()
|
||||
return "".join([c.get_function_block_v() for c in self.component_types])
|
||||
|
||||
def get_function_block_v(self):
|
||||
"""Generates hierarchical Verilog code representation of corresponding multi-bit arithmetic circuit used as function block in hierarchical circuit description.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code of multi-bit arithmetic circuit's function block description.
|
||||
"""
|
||||
# Obtain proper circuit name with its bit width
|
||||
circuit_prefix = self.__class__(
|
||||
a=Bus("a"), b=Bus("b")).prefix + str(self.N)
|
||||
circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(
|
||||
N=self.N, prefix="b"), prefix=circuit_prefix)
|
||||
return f"{circuit_block.get_circuit_v()}\n\n"
|
||||
|
||||
def get_declarations_v_hier(self):
|
||||
"""Generates hierarchical Verilog code declaration of input/output circuit wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code containing unique declaration of arithmetic circuit wires.
|
||||
"""
|
||||
return "".join([c.get_declaration_v_hier() for c in self.components])
|
||||
|
||||
def get_declaration_v_hier(self):
|
||||
"""Generates hierarchical Verilog code declaration of corresponding subcomponent input/output wires inside the upper component.
|
||||
|
||||
Generates wires used to connect input/output values to/from invocation of the corresponding function block into inner wires present
|
||||
inside the upper component from which function block has been invoked.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code of subcomponent arithmetic circuit's wires declaration.
|
||||
"""
|
||||
return f" wire [{self.a.N-1}:0] {self.a.prefix};\n" + \
|
||||
f" wire [{self.b.N-1}:0] {self.b.prefix};\n" + \
|
||||
f" wire [{self.out.N-1}:0] {self.out.prefix};\n"
|
||||
|
||||
def get_init_v_hier(self):
|
||||
"""Generates hierarchical Verilog code initialization and assignment of corresponding arithmetic circuit's input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code initialization of arithmetic circuit wires.
|
||||
"""
|
||||
return "".join([c.get_gate_invocation_v() if isinstance(c, TwoInputLogicGate) else c.get_out_invocation_v(circuit_prefix=self.prefix) for c in self.components])
|
||||
|
||||
def get_out_invocation_v(self, circuit_prefix: str):
|
||||
"""Generates hierarchical Verilog code invocation of corresponding arithmetic circuit's generated function block.
|
||||
|
||||
Assigns input values from other subcomponents into multi-bit input buses used as inputs for function block invocation.
|
||||
Assigns output values from invocation of the corresponding function block into inner wires present inside
|
||||
the upper component from which function block has been invoked.
|
||||
|
||||
Args:
|
||||
circuit_prefix (str): Prefix name of the upper component from which function block is being invoked.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code of subcomponent's module invocation and output assignment.
|
||||
"""
|
||||
# Getting name of circuit type and insitu copying out bus for proper Verilog code generation without affecting actual generated composition
|
||||
circuit_type = self.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_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(
|
||||
N=self.N, prefix="b"), prefix=circuit_prefix)
|
||||
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"
|
||||
|
||||
def get_function_out_v_hier(self):
|
||||
"""Generates hierarchical Verilog code assignment of corresponding arithmetic circuit's output bus wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code containing output bus wires assignment.
|
||||
"""
|
||||
return self.out.return_bus_wires_values_v_hier()
|
||||
|
||||
def get_circuit_v(self):
|
||||
"""Generates hierarchical Verilog code subcomponent's function block.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code of subcomponent's function block.
|
||||
"""
|
||||
return f"{self.get_prototype_v()}" + \
|
||||
f"{self.get_declarations_v_hier()}\n" + \
|
||||
f"{self.get_init_v_hier()}\n" + \
|
||||
f"{self.get_function_out_v_hier()}" + \
|
||||
f"endmodule"
|
||||
|
||||
# Generating hierarchical Verilog code representation of circuit
|
||||
def get_v_code_hier(self, file_object):
|
||||
"""Generates hierarchical Verilog code representation of corresponding arithmetic circuit.
|
||||
|
||||
Args:
|
||||
file_object (TextIOWrapper): Destination file object where circuit's representation will be written to.
|
||||
"""
|
||||
file_object.write(self.get_function_blocks_v())
|
||||
file_object.write(self.get_circuit_v())
|
||||
file_object.close()
|
||||
|
||||
""" BLIF CODE GENERATION """
|
||||
# FLAT BLIF #
|
||||
|
||||
def get_prototype_blif(self):
|
||||
"""Generates Blif code model name of described arithmetic circuit.
|
||||
|
||||
Returns:
|
||||
str: Model's name in Blif code.
|
||||
"""
|
||||
return f".model {self.prefix}\n"
|
||||
|
||||
def get_declaration_blif(self):
|
||||
"""Generates flat Blif code declaration of input/output circuit wires.
|
||||
|
||||
Returns:
|
||||
str: Flat Blif code containing declaration of circuit's wires.
|
||||
"""
|
||||
if self.N == 1:
|
||||
return f".inputs {self.a.prefix} {self.b.prefix}\n" + \
|
||||
f".outputs{self.out.get_wire_declaration_blif()}\n" + \
|
||||
f".names vdd\n1\n" + \
|
||||
f".names gnd\n0\n"
|
||||
else:
|
||||
return f".inputs{self.a.get_wire_declaration_blif()}{self.b.get_wire_declaration_blif()}\n" + \
|
||||
f".outputs{self.out.get_wire_declaration_blif()}\n" + \
|
||||
f".names vdd\n1\n" + \
|
||||
f".names gnd\n0\n"
|
||||
|
||||
def get_function_blif_flat(self):
|
||||
"""Generates flat Blif code with invocation of subcomponents logic gates functions via their corresponding truth tables.
|
||||
|
||||
Returns:
|
||||
str: Flat Blif code containing invocation of inner subcomponents logic gates Boolean functions.
|
||||
"""
|
||||
return "".join(c.get_function_blif_flat() for c in self.components)
|
||||
|
||||
def get_function_out_blif(self):
|
||||
"""Generates flat Blif code assignment of corresponding arithmetic circuit's output bus wires.
|
||||
|
||||
Returns:
|
||||
str: Flat Blif code containing output bus wires assignment.
|
||||
"""
|
||||
return f"{self.out.get_wire_assign_blif(output=True)}"
|
||||
|
||||
# Generating flat BLIF code representation of circuit
|
||||
def get_blif_code_flat(self, file_object):
|
||||
"""Generates flat Blif code representation of corresponding arithmetic circuit.
|
||||
|
||||
Args:
|
||||
file_object (TextIOWrapper): Destination file object where circuit's representation will be written to.
|
||||
"""
|
||||
file_object.write(self.get_prototype_blif())
|
||||
file_object.write(self.get_declaration_blif())
|
||||
file_object.write(self.get_function_blif_flat())
|
||||
file_object.write(self.get_function_out_blif())
|
||||
file_object.write(f".end\n")
|
||||
file_object.close()
|
||||
|
||||
# HIERARCHICAL BLIF #
|
||||
def get_invocations_blif_hier(self):
|
||||
"""Generates hierarchical Blif code with invocations of subcomponents function blocks.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Blif code containing invocations of inner subcomponents function blocks.
|
||||
"""
|
||||
return "".join(c.get_invocation_blif_hier(circuit_prefix=self.prefix) for c in self.components)
|
||||
|
||||
def get_invocation_blif_hier(self, circuit_prefix: str):
|
||||
"""Generates hierarchical Blif code invocation of corresponding arithmetic circuit's generated function block.
|
||||
|
||||
Used for multi-bit subcomponent's modul invocation.
|
||||
|
||||
Args:
|
||||
circuit_prefix (str): Prefix name of the upper component from which function block is being invoked.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Blif code of subcomponent's model invocation and output assignment.
|
||||
"""
|
||||
# Getting name of circuit type for proper Blif code generation without affecting actual generated composition
|
||||
circuit_type = self.prefix.replace(circuit_prefix+"_", "")
|
||||
return f"{self.a.get_wire_assign_blif(output=True)}" + \
|
||||
f"{self.b.get_wire_assign_blif(output=True)}" + \
|
||||
f".subckt {circuit_type}" + \
|
||||
"".join([f" a[{self.a.bus.index(w)}]={self.a.prefix}[{self.a.bus.index(w)}]" for w in self.a.bus]) + \
|
||||
"".join([f" b[{self.b.bus.index(w)}]={self.b.prefix}[{self.b.bus.index(w)}]" for w in self.b.bus]) + \
|
||||
"".join(
|
||||
[f" {circuit_type}_out[{self.out.bus.index(o)}]={o.name}" for o in self.out.bus]) + "\n"
|
||||
|
||||
def get_circuit_blif(self):
|
||||
"""Generates hierarchical Blif code subcomponent's function block.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Blif code of subcomponent's function block.
|
||||
"""
|
||||
return f"{self.get_prototype_blif()}" + \
|
||||
f"{self.get_declaration_blif()}" + \
|
||||
f"{self.get_invocations_blif_hier()}" + \
|
||||
f"{self.get_function_out_blif()}" + \
|
||||
f".end\n"
|
||||
|
||||
def get_function_blocks_blif(self):
|
||||
"""Generates hierarchical Blif code representation of all subcomponents function blocks present in corresponding arithmetic circuit.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Blif code of all subcomponents function blocks description.
|
||||
"""
|
||||
# Retrieve all unique component types composing this circuit
|
||||
# (iterating backwards as opposed to other representations so the top modul is always above its subcomponents)
|
||||
self.component_types = self.get_component_types()
|
||||
return "\n".join([c.get_function_block_blif() for c in self.component_types[::-1]])
|
||||
|
||||
def get_function_block_blif(self):
|
||||
"""Generates hierarchical Blif code representation of corresponding multi-bit arithmetic circuit used as function block in hierarchical circuit description.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Blif code of multi-bit arithmetic circuit's function block description.
|
||||
"""
|
||||
# Obtain proper circuit name with its bit width
|
||||
circuit_prefix = self.__class__(
|
||||
a=Bus("a"), b=Bus("b")).prefix + str(self.N)
|
||||
circuit_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(
|
||||
N=self.N, prefix="b"), prefix=circuit_prefix)
|
||||
return f"{circuit_block.get_circuit_blif()}"
|
||||
|
||||
# Generating hierarchical BLIF code representation of circuit
|
||||
def get_blif_code_hier(self, file_object):
|
||||
"""Generates hierarchical Blif code representation of corresponding arithmetic circuit.
|
||||
|
||||
Args:
|
||||
file_object (TextIOWrapper): Destination file object where circuit's representation will be written to.
|
||||
"""
|
||||
file_object.write(self.get_circuit_blif()+"\n")
|
||||
file_object.write(self.get_function_blocks_blif())
|
||||
file_object.close()
|
||||
|
||||
""" CGP CODE GENERATION """
|
||||
# FLAT CGP #
|
||||
|
||||
def get_parameters_cgp(self):
|
||||
"""Generates CGP chromosome parameters of corresponding arithmetic circuit.
|
||||
|
||||
In total seven parameters represent: total inputs, total outputs, number of rows, number of columns (gates),
|
||||
number of each gate's inputs, number of each gate's outputs, quality constant value.
|
||||
|
||||
Returns:
|
||||
str: CGP chromosome parameters of described arithmetic circuit.
|
||||
"""
|
||||
self.circuit_gates = self.get_circuit_gates()
|
||||
return f"{{{self.a.N+self.a.N},{self.out.N},1,{len(self.circuit_gates)},2,1,0}}"
|
||||
|
||||
def get_triplets_cgp(self):
|
||||
"""Generates list of logic gate triplets (first input wire, second input wire, logic gate function) using wires unique position indexes within the described circuit.
|
||||
|
||||
Each triplet represents unique logic gate within the described arithmetic circuit. Besides the contained input wires indexes and gate's inner logic function, an output wire
|
||||
with incremented index position is also created and remembered to be appropriately driven as an input to another logic gate or as the circuit's output.
|
||||
|
||||
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.
|
||||
|
||||
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()
|
||||
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])
|
||||
|
||||
def get_outputs_cgp(self):
|
||||
"""Generates list of output wires indexes of described arithmetic circuit from MSB to LSB.
|
||||
|
||||
Returns:
|
||||
str: List of arithmetic circuit's output wire indexes.
|
||||
"""
|
||||
return "(" + ",".join([str(self.get_circuit_wire_index(o)) for o in self.out.bus]) + ")"
|
||||
|
||||
# Generating flat CGP chromosome representation of circuit
|
||||
def get_cgp_code_flat(self, file_object):
|
||||
"""Generates flat CGP chromosome representation of corresponding arithmetic circuit.
|
||||
|
||||
Args:
|
||||
file_object (TextIOWrapper): Destination file object where circuit's representation will be written to.
|
||||
"""
|
||||
file_object.write(self.get_parameters_cgp())
|
||||
file_object.write(self.get_triplets_cgp())
|
||||
file_object.write(self.get_outputs_cgp())
|
||||
file_object.close()
|
@ -29,8 +29,8 @@ class MultiplierCircuit(ArithmeticCircuit):
|
||||
that are later used for generation into various representations.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, a, b, prefix, name, out_N, **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):
|
||||
|
@ -416,7 +416,7 @@ class TwoInputLogicGate():
|
||||
"""
|
||||
return "{2,1,1,1,2,1,0}"
|
||||
|
||||
def get_triplet_cgp(self, a_id: int, b_id: int):
|
||||
def get_triplet_cgp(self, a_id: int, b_id: int, out_id: int):
|
||||
"""Generates logic gate triplet (first input wire, second input wire, logic gate function) using wires unique position indexes within the described circuit.
|
||||
|
||||
Each triplet represents unique logic gate within the described circuit. Besides the contained input wires indexes and gate's inner logic function, an output wire
|
||||
@ -429,11 +429,12 @@ class TwoInputLogicGate():
|
||||
Args:
|
||||
a_id (int): First input wire index position.
|
||||
b_id (int): Second input wire index position.
|
||||
out_id (int): The output wire index position
|
||||
|
||||
Returns:
|
||||
str: Triplet describing function of corresponding two input logic gate.
|
||||
"""
|
||||
return f"({a_id},{b_id},{self.cgp_function})"
|
||||
return f"([{out_id}]{a_id},{b_id},{self.cgp_function})"
|
||||
|
||||
@staticmethod
|
||||
def get_output_cgp(out_id: int):
|
||||
@ -470,7 +471,7 @@ class TwoInputLogicGate():
|
||||
out_id = self.out.cgp_const
|
||||
else:
|
||||
out_id = a_id+1 if a_id > b_id else b_id+1
|
||||
return self.get_triplet_cgp(a_id=a_id, b_id=b_id) + self.get_output_cgp(out_id=out_id)
|
||||
return self.get_triplet_cgp(a_id=a_id, b_id=b_id, out_id=out_id) + self.get_output_cgp(out_id=out_id)
|
||||
|
||||
def get_cgp_code(self, file_object):
|
||||
"""Generates flat CGP chromosome representation of corresponding logic gate itself.
|
||||
@ -706,7 +707,7 @@ class OneInputLogicGate(TwoInputLogicGate):
|
||||
|
||||
""" CGP CODE GENERATION """
|
||||
# FLAT CGP #
|
||||
def get_triplet_cgp(self, a_id: int):
|
||||
def get_triplet_cgp(self, a_id: int, out_id: int):
|
||||
"""Generates logic gate triplet (first input wire, second input wire, logic gate function) using wires unique position indexes within the described circuit.
|
||||
|
||||
Each triplet represents unique logic gate within the described circuit. In this case of one input logic gate, the same input wire index is driven to both inputs.
|
||||
@ -719,11 +720,12 @@ class OneInputLogicGate(TwoInputLogicGate):
|
||||
|
||||
Args:
|
||||
a_id (int): First (used also as the second) input wire index position.
|
||||
out_id (int): Outpu wire index position
|
||||
|
||||
Returns:
|
||||
str: Triplet describing function of corresponding one input logic gate.
|
||||
"""
|
||||
return f"({a_id},{a_id},{self.cgp_function})"
|
||||
return f"([{out_id}]{a_id},{a_id},{self.cgp_function})"
|
||||
|
||||
@staticmethod
|
||||
def get_output_cgp(out_id: int):
|
||||
@ -752,4 +754,4 @@ class OneInputLogicGate(TwoInputLogicGate):
|
||||
out_id = self.out.cgp_const
|
||||
else:
|
||||
out_id = a_id+1 if a_id == 2 else 2
|
||||
return self.get_triplet_cgp(a_id=a_id) + self.get_output_cgp(out_id=out_id)
|
||||
return self.get_triplet_cgp(a_id=a_id, out_id=out_id) + self.get_output_cgp(out_id=out_id)
|
||||
|
@ -16,7 +16,7 @@ class TwoInputOneBitCircuit(ArithmeticCircuit):
|
||||
prefix (str, optional): Prefix name of circuit. Defaults to "two_input_one_bit_circuit".
|
||||
"""
|
||||
def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), prefix: str = "two_input_one_bit_circuit"):
|
||||
super().__init__()
|
||||
super().__init__(a=a, b=b, prefix=prefix, name="", out_N=1, one_bit_circuit = True)
|
||||
self.c_data_type = "uint8_t"
|
||||
self.prefix = prefix
|
||||
self.a = a
|
||||
|
@ -62,22 +62,17 @@ class UnsignedCarryLookaheadAdder(ArithmeticCircuit):
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
cla_block_size (int, optional): Size of each composite cla adder block size. Defaults to 4.
|
||||
prefix (str, optional): Prefix name of unsigned cla. Defaults to "u_cla".
|
||||
prefix (str, optional): Prefix name of unsigned cla. Defaults to "".
|
||||
name (str, optional): Name of unsigned cla. Defaults to "u_cla".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, cla_block_size: int = 4, prefix: str = "u_cla"):
|
||||
super().__init__()
|
||||
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)
|
||||
self.prefix = prefix
|
||||
self.a = Bus(prefix=a.prefix, wires_list=a.bus)
|
||||
self.b = Bus(prefix=b.prefix, wires_list=b.bus)
|
||||
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)
|
||||
|
||||
# Output wires for N sum bits and additional cout bit
|
||||
self.out = Bus(self.prefix+"_out", self.N+1)
|
||||
|
||||
# To signify current number of blocks and number of bits that remain to be added into function blocks
|
||||
N_blocks = 0
|
||||
N_wires = self.N
|
||||
@ -185,10 +180,11 @@ class SignedCarryLookaheadAdder(UnsignedCarryLookaheadAdder, ArithmeticCircuit):
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
cla_block_size (int, optional): Size of each composite cla adder block size. Defaults to 4.
|
||||
prefix (str, optional): Prefix name of signed cla. Defaults to "s_cla".
|
||||
prefix (str, optional): Prefix name of signed cla. Defaults to "".
|
||||
name (str, optional): Name of signed cla. Defaults to "s_cla".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, cla_block_size: int = 4, prefix: str = "s_cla"):
|
||||
super().__init__(a=a, b=b, cla_block_size=cla_block_size, prefix=prefix)
|
||||
def __init__(self, a: Bus, b: Bus, cla_block_size: int = 4, prefix: str = "", name: str = "s_cla", **kwargs):
|
||||
super().__init__(a=a, b=b, cla_block_size=cla_block_size, prefix=prefix, name=name, **kwargs)
|
||||
self.c_data_type = "int64_t"
|
||||
|
||||
# Additional XOR gates to ensure correct sign extension in case of sign addition
|
||||
|
@ -69,22 +69,17 @@ class UnsignedCarrySkipAdder(ArithmeticCircuit):
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
bypass_block_size (int, optional): Size of each composite bypass adder block size. Defaults to 4.
|
||||
prefix (str, optional): Prefix name of unsigned cska. Defaults to "u_cska".
|
||||
prefix (str, optional): Prefix name of unsigned cska. Defaults to "".
|
||||
name (str, optional): Name of unsigned cska. Defaults to "u_cska".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, bypass_block_size: int = 4, prefix: str = "u_cska"):
|
||||
super().__init__()
|
||||
def __init__(self, a: Bus, b: Bus, bypass_block_size: int = 4, prefix: str = "", name: str = "u_cska", **kwargs):
|
||||
self.N = max(a.N, b.N)
|
||||
self.prefix = prefix
|
||||
self.a = Bus(prefix=a.prefix, wires_list=a.bus)
|
||||
self.b = Bus(prefix=b.prefix, wires_list=b.bus)
|
||||
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)
|
||||
|
||||
# Output wires for N sum bits and additional cout bit
|
||||
self.out = Bus(self.prefix+"_out", self.N+1)
|
||||
|
||||
# To signify current number of blocks and number of bits that remain to be added into function blocks
|
||||
N_blocks = 0
|
||||
N_wires = self.N
|
||||
@ -168,10 +163,11 @@ class SignedCarrySkipAdder(UnsignedCarrySkipAdder, ArithmeticCircuit):
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
bypass_block_size (int, optional): Size of each composite bypass adder block size. Defaults to 4.
|
||||
prefix (str, optional): Prefix name of signed cska. Defaults to "s_cska".
|
||||
prefix (str, optional): Prefix name of signed cska. Defaults to "".
|
||||
name (str, optional): Name of signed cska. Defaults to "s_cska".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, bypass_block_size: int = 4, prefix: str = "s_cska"):
|
||||
super().__init__(a=a, b=b, bypass_block_size=bypass_block_size, prefix=prefix)
|
||||
def __init__(self, a: Bus, b: Bus, bypass_block_size: int = 4, prefix: str = "", name: str = "s_cska", **kwargs):
|
||||
super().__init__(a=a, b=b, bypass_block_size=bypass_block_size, prefix=prefix, name=name, **kwargs)
|
||||
self.c_data_type = "int64_t"
|
||||
|
||||
# Additional XOR gates to ensure correct sign extension in case of sign addition
|
||||
|
@ -59,22 +59,17 @@ class UnsignedPGRippleCarryAdder(ArithmeticCircuit):
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of unsigned P/G rca. Defaults to "u_pg_rca".
|
||||
prefix (str, optional): Prefix name of unsigned P/G rca. Defaults to "".
|
||||
name (str, optional): Name of unsigned P/G rca. Defaults to "u_pg_rca".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "u_pg_rca"):
|
||||
super().__init__()
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_pg_rca", **kwargs):
|
||||
self.N = max(a.N, b.N)
|
||||
self.prefix = prefix
|
||||
self.a = Bus(prefix=a.prefix, wires_list=a.bus)
|
||||
self.b = Bus(prefix=b.prefix, wires_list=b.bus)
|
||||
|
||||
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)
|
||||
|
||||
# Output wires for N sum bits and additional cout bit
|
||||
self.out = Bus(self.prefix+"_out", self.N+1)
|
||||
|
||||
# Gradual addition of 1-bit adder components
|
||||
for input_index in range(self.N):
|
||||
if input_index == 0:
|
||||
@ -131,10 +126,11 @@ class SignedPGRippleCarryAdder(UnsignedPGRippleCarryAdder, ArithmeticCircuit):
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of signed P/G rca. Defaults to "s_pg_rca".
|
||||
prefix (str, optional): Prefix name of signed P/G rca. Defaults to "".
|
||||
name (str, optional): Name of signed P/G rca. Defaults to "s_pg_rca".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "s_pg_rca"):
|
||||
super().__init__(a=a, b=b, prefix=prefix)
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_pg_rca", **kwargs):
|
||||
super().__init__(a=a, b=b, prefix=prefix, name=name, **kwargs)
|
||||
self.c_data_type = "int64_t"
|
||||
|
||||
# Additional XOR gates to ensure correct sign extension in case of sign addition
|
||||
|
@ -50,22 +50,17 @@ class UnsignedRippleCarryAdder(ArithmeticCircuit):
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of unsigned rca. Defaults to "u_rca".
|
||||
prefix (str, optional): Prefix name of unsigned rca. Defaults to "".
|
||||
name (str, optional): Name of unsigned rca. Defaults to "u_rca".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "u_rca"):
|
||||
super().__init__()
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_rca", **kwargs):
|
||||
self.N = max(a.N, b.N)
|
||||
self.prefix = prefix
|
||||
self.a = Bus(prefix=a.prefix, wires_list=a.bus)
|
||||
self.b = Bus(prefix=b.prefix, wires_list=b.bus)
|
||||
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)
|
||||
|
||||
# Output wires for N sum bits and additional cout bit
|
||||
self.out = Bus(self.prefix+"_out", self.N+1)
|
||||
|
||||
# Gradual addition of 1-bit adder components
|
||||
for input_index in range(self.N):
|
||||
# First adder is a half adder
|
||||
@ -107,10 +102,11 @@ class SignedRippleCarryAdder(UnsignedRippleCarryAdder, ArithmeticCircuit):
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of signed rca. Defaults to "s_rca".
|
||||
prefix (str, optional): Prefix name of signed rca. Defaults to "".
|
||||
name (str, optional): Name of signed rca. Defaults to "s_rca".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "s_rca"):
|
||||
super().__init__(a=a, b=b, prefix=prefix)
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_rca", **kwargs):
|
||||
super().__init__(a=a, b=b, prefix=prefix, name=name, **kwargs)
|
||||
self.c_data_type = "int64_t"
|
||||
|
||||
# Additional XOR gates to ensure correct sign extension in case of sign addition
|
||||
|
@ -92,22 +92,17 @@ class ArrayDivider(ArithmeticCircuit):
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of array divider. Defaults to "arrdiv".
|
||||
prefix (str, optional): Prefix name of array divider. Defaults to "".
|
||||
name (str, optional): Name of array divider. Defaults to "arrdiv".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "arrdiv"):
|
||||
super().__init__()
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "arrdiv", **kwargs):
|
||||
self.N = max(a.N, b.N)
|
||||
self.prefix = prefix
|
||||
self.a = Bus(prefix=a.prefix, wires_list=a.bus)
|
||||
self.b = Bus(prefix=b.prefix, wires_list=b.bus)
|
||||
super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N, **kwargs)
|
||||
|
||||
# Bus sign extension in case buses have different lengths
|
||||
self.a.bus_extend(N=self.N, prefix=a.prefix)
|
||||
self.b.bus_extend(N=self.N, prefix=b.prefix)
|
||||
|
||||
# Output wires for quotient result
|
||||
self.out = Bus(self.prefix+"_out", self.N)
|
||||
|
||||
# Performing series of iterative subtractions
|
||||
# Gradually shifting the divisor
|
||||
for a_index in reversed(range(self.N)):
|
||||
|
@ -79,22 +79,17 @@ class UnsignedArrayMultiplier(MultiplierCircuit):
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of unsigned array multiplier. Defaults to "u_arrmul".
|
||||
prefix (str, optional): Prefix name of unsigned array multiplier. Defaults to "".
|
||||
name (str, optional): Name of unsigned array multiplier. Defaults to "u_arrmul".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "u_arrmul"):
|
||||
super().__init__()
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_arrmul", **kwargs):
|
||||
self.N = max(a.N, b.N)
|
||||
self.prefix = prefix
|
||||
self.a = Bus(prefix=a.prefix, wires_list=a.bus)
|
||||
self.b = Bus(prefix=b.prefix, wires_list=b.bus)
|
||||
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)
|
||||
|
||||
# Output wires for multiplication product
|
||||
self.out = Bus(self.prefix+"_out", self.N*2)
|
||||
|
||||
# Gradual generation of partial products
|
||||
for b_multiplier_index in range(self.N):
|
||||
for a_multiplicand_index in range(self.N):
|
||||
@ -127,7 +122,7 @@ class UnsignedArrayMultiplier(MultiplierCircuit):
|
||||
|
||||
# 1 bit multiplier case
|
||||
if a_multiplicand_index == self.N-1:
|
||||
self.out.connect(a_multiplicand_index+1, ConstantWireValue0)
|
||||
self.out.connect(a_multiplicand_index+1, ConstantWireValue0())
|
||||
|
||||
elif b_multiplier_index == self.N-1:
|
||||
self.out.connect(b_multiplier_index + a_multiplicand_index, obj_adder.get_sum_wire())
|
||||
@ -191,23 +186,18 @@ class SignedArrayMultiplier(MultiplierCircuit):
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of signed array multiplier. Defaults to "s_arrmul".
|
||||
prefix (str, optional): Prefix name of signed array multiplier. Defaults to "".
|
||||
name (str, optional): Name of signed array multiplier. Defaults to "s_arrmul".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "s_arrmul"):
|
||||
super().__init__()
|
||||
self.c_data_type = "int64_t"
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_arrmul", **kwargs):
|
||||
self.N = max(a.N, b.N)
|
||||
self.prefix = prefix
|
||||
self.a = Bus(prefix=a.prefix, wires_list=a.bus)
|
||||
self.b = Bus(prefix=b.prefix, wires_list=b.bus)
|
||||
super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **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)
|
||||
|
||||
# Output wires for multiplication product
|
||||
self.out = Bus(self.prefix+"_out", self.N*2)
|
||||
|
||||
# Gradual generation of partial products
|
||||
for b_multiplier_index in range(self.N):
|
||||
for a_multiplicand_index in range(self.N):
|
||||
|
@ -45,23 +45,18 @@ class UnsignedDaddaMultiplier(MultiplierCircuit):
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of unsigned dadda multiplier. Defaults to "u_dadda_cla".
|
||||
prefix (str, optional): Prefix name of unsigned dadda multiplier. Defaults to "".
|
||||
name (str, optional): Name of unsigned dadda multiplier. Defaults to "u_dadda_cla".
|
||||
unsigned_adder_class_name (str, optional): Unsigned multi bit adder used to obtain final sums of products. Defaults to UnsignedCarryLookaheadAdder.
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "u_dadda_cla", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder):
|
||||
super().__init__()
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_dadda_cla", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs):
|
||||
self.N = max(a.N, b.N)
|
||||
self.prefix = prefix
|
||||
self.a = Bus(prefix=a.prefix, wires_list=a.bus)
|
||||
self.b = Bus(prefix=b.prefix, wires_list=b.bus)
|
||||
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)
|
||||
|
||||
# Output wires for multiplication product
|
||||
self.out = Bus(self.prefix+"_out", self.N*2)
|
||||
|
||||
# Get starting stage and maximum possible column height
|
||||
self.stage, self.d = self.get_maximum_height(initial_value=min(self.a.N, self.b.N))
|
||||
# Initialize all columns partial products forming AND gates matrix
|
||||
@ -123,11 +118,10 @@ class UnsignedDaddaMultiplier(MultiplierCircuit):
|
||||
# Final addition of remaining bits using chosen unsigned multi bit adder
|
||||
else:
|
||||
# Obtain proper adder name with its bit width (columns bit pairs minus the first alone bit)
|
||||
adder_prefix = self.prefix + "_" + unsigned_adder_class_name(a=a, b=b).prefix + str(len(self.columns)-1)
|
||||
|
||||
adder_a = Bus(prefix=f"{adder_prefix}_a", wires_list=[self.add_column_wire(column=col, bit=0) for col in range(1, len(self.columns))])
|
||||
adder_b = Bus(prefix=f"{adder_prefix}_b", wires_list=[self.add_column_wire(column=col, bit=1) for col in range(1, len(self.columns))])
|
||||
final_adder = unsigned_adder_class_name(a=adder_a, b=adder_b, prefix=adder_prefix)
|
||||
adder_name = unsigned_adder_class_name(a=a, b=b).prefix + str(len(self.columns)-1)
|
||||
adder_a = Bus(prefix=f"a", wires_list=[self.add_column_wire(column=col, bit=0) for col in range(1, len(self.columns))])
|
||||
adder_b = Bus(prefix=f"b", wires_list=[self.add_column_wire(column=col, bit=1) for col in range(1, len(self.columns))])
|
||||
final_adder = unsigned_adder_class_name(a=adder_a, b=adder_b, prefix=self.prefix, name=adder_name, inner_component=True)
|
||||
self.add_component(final_adder)
|
||||
|
||||
[self.out.connect(o, final_adder.out.get_wire(o-1), inserted_wire_desired_index=o-1) for o in range(1, len(self.out.bus))]
|
||||
@ -155,24 +149,19 @@ class SignedDaddaMultiplier(MultiplierCircuit):
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of signed dadda multiplier. Defaults to "s_dadda_cla".
|
||||
prefix (str, optional): Prefix name of signed dadda multiplier. Defaults to "".
|
||||
name (str, optional): Name of signed dadda multiplier. Defaults to "s_dadda_cla".
|
||||
unsigned_adder_class_name (str, optional): Unsigned multi bit adder used to obtain final sums of products. Defaults to UnsignedCarryLookaheadAdder.
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "s_dadda_cla", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder):
|
||||
super().__init__()
|
||||
self.c_data_type = "int64_t"
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_dadda_cla", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs):
|
||||
self.N = max(a.N, b.N)
|
||||
self.prefix = prefix
|
||||
self.a = Bus(prefix=a.prefix, wires_list=a.bus)
|
||||
self.b = Bus(prefix=b.prefix, wires_list=b.bus)
|
||||
super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **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)
|
||||
|
||||
# Output wires for multiplication product
|
||||
self.out = Bus(self.prefix+"_out", self.N*2)
|
||||
|
||||
# Get starting stage and maximum possible column height
|
||||
self.stage, self.d = self.get_maximum_height(initial_value=min(self.a.N, self.b.N))
|
||||
# Initialize all columns partial products forming AND/NAND gates matrix based on Baugh-Wooley multiplication
|
||||
@ -241,11 +230,10 @@ class SignedDaddaMultiplier(MultiplierCircuit):
|
||||
# Final addition of remaining bits using chosen unsigned multi bit adder
|
||||
else:
|
||||
# Obtain proper adder name with its bit width (columns bit pairs minus the first alone bit)
|
||||
adder_prefix = self.prefix + "_" + unsigned_adder_class_name(a=a, b=b).prefix + str(len(self.columns)-1)
|
||||
|
||||
adder_a = Bus(prefix=f"{adder_prefix}_a", wires_list=[self.add_column_wire(column=col, bit=0) for col in range(1, len(self.columns))])
|
||||
adder_b = Bus(prefix=f"{adder_prefix}_b", wires_list=[self.add_column_wire(column=col, bit=1) for col in range(1, len(self.columns))])
|
||||
final_adder = unsigned_adder_class_name(a=adder_a, b=adder_b, prefix=adder_prefix)
|
||||
adder_name = unsigned_adder_class_name(a=a, b=b).prefix + str(len(self.columns)-1)
|
||||
adder_a = Bus(prefix=f"a", wires_list=[self.add_column_wire(column=col, bit=0) for col in range(1, len(self.columns))])
|
||||
adder_b = Bus(prefix=f"b", wires_list=[self.add_column_wire(column=col, bit=1) for col in range(1, len(self.columns))])
|
||||
final_adder = unsigned_adder_class_name(a=adder_a, b=adder_b, prefix=self.prefix, name=adder_name, inner_component=True)
|
||||
self.add_component(final_adder)
|
||||
|
||||
[self.out.connect(o, final_adder.out.get_wire(o-1), inserted_wire_desired_index=o-1) for o in range(1, len(self.out.bus))]
|
||||
|
@ -44,23 +44,18 @@ class UnsignedWallaceMultiplier(MultiplierCircuit):
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of unsigned wallace multiplier. Defaults to "u_wallace_cla".
|
||||
prefix (str, optional): Prefix name of unsigned wallace multiplier. Defaults to "".
|
||||
name (str, optional): Name of unsigned wallace multiplier. Defaults to "u_wallace_cla".
|
||||
unsigned_adder_class_name (str, optional): Unsigned multi bit adder used to obtain final sums of products. Defaults to UnsignedCarryLookaheadAdder.
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "u_wallace_cla", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder):
|
||||
super().__init__()
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_wallace_cla", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs):
|
||||
self.N = max(a.N, b.N)
|
||||
self.prefix = prefix
|
||||
self.a = Bus(prefix=a.prefix, wires_list=a.bus)
|
||||
self.b = Bus(prefix=b.prefix, wires_list=b.bus)
|
||||
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)
|
||||
|
||||
# Output wires for multiplication product
|
||||
self.out = Bus(self.prefix+"_out", self.N*2)
|
||||
|
||||
# Initialize all columns partial products forming AND gates matrix
|
||||
self.columns = self.init_column_heights()
|
||||
|
||||
@ -117,11 +112,10 @@ class UnsignedWallaceMultiplier(MultiplierCircuit):
|
||||
# Final addition of remaining bits using chosen unsigned multi bit adder
|
||||
else:
|
||||
# Obtain proper adder name with its bit width (columns bit pairs minus the first alone bit)
|
||||
adder_prefix = self.prefix + "_" + unsigned_adder_class_name(a=a, b=b).prefix + str(len(self.columns)-1)
|
||||
|
||||
adder_a = Bus(prefix=f"{adder_prefix}_a", wires_list=[self.add_column_wire(column=col, bit=0) for col in range(1, len(self.columns))])
|
||||
adder_b = Bus(prefix=f"{adder_prefix}_b", wires_list=[self.add_column_wire(column=col, bit=1) for col in range(1, len(self.columns))])
|
||||
final_adder = unsigned_adder_class_name(a=adder_a, b=adder_b, prefix=adder_prefix)
|
||||
adder_name = unsigned_adder_class_name(a=a, b=b).prefix + str(len(self.columns)-1)
|
||||
adder_a = Bus(prefix=f"a", wires_list=[self.add_column_wire(column=col, bit=0) for col in range(1, len(self.columns))])
|
||||
adder_b = Bus(prefix=f"b", wires_list=[self.add_column_wire(column=col, bit=1) for col in range(1, len(self.columns))])
|
||||
final_adder = unsigned_adder_class_name(a=adder_a, b=adder_b, prefix=self.prefix, name=adder_name, inner_component=True)
|
||||
self.add_component(final_adder)
|
||||
|
||||
[self.out.connect(o, final_adder.out.get_wire(o-1), inserted_wire_desired_index=o-1) for o in range(1, len(self.out.bus))]
|
||||
@ -148,24 +142,19 @@ class SignedWallaceMultiplier(MultiplierCircuit):
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of signed wallace multiplier. Defaults to "s_wallace_cla".
|
||||
prefix (str, optional): Prefix name of signed wallace multiplier. Defaults to "".
|
||||
name (str, optional): Name of signed wallace multiplier. Defaults to "s_wallace_cla".
|
||||
unsigned_adder_class_name (str, optional): Unsigned multi bit adder used to obtain final sums of products. Defaults to UnsignedCarryLookaheadAdder.
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "s_wallace_cla", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder):
|
||||
super().__init__()
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_wallace_cla", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs):
|
||||
self.N = max(a.N, b.N)
|
||||
self.prefix = prefix
|
||||
super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs)
|
||||
self.c_data_type = "int64_t"
|
||||
self.a = Bus(prefix=a.prefix, wires_list=a.bus)
|
||||
self.b = Bus(prefix=b.prefix, wires_list=b.bus)
|
||||
|
||||
# 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)
|
||||
|
||||
# Output wires for multiplication product
|
||||
self.out = Bus(self.prefix+"_out", self.N*2)
|
||||
|
||||
# Initialize all columns partial products forming AND/NAND gates matrix based on Baugh-Wooley multiplication
|
||||
self.columns = self.init_column_heights(signed=True)
|
||||
|
||||
@ -231,11 +220,10 @@ class SignedWallaceMultiplier(MultiplierCircuit):
|
||||
# Final addition of remaining bits using chosen unsigned multi bit adder
|
||||
else:
|
||||
# Obtain proper adder name with its bit width (columns bit pairs minus the first alone bit)
|
||||
adder_prefix = self.prefix + "_" + unsigned_adder_class_name(a=a, b=b).prefix + str(len(self.columns)-1)
|
||||
|
||||
adder_a = Bus(prefix=f"{adder_prefix}_a", wires_list=[self.add_column_wire(column=col, bit=0) for col in range(1, len(self.columns))])
|
||||
adder_b = Bus(prefix=f"{adder_prefix}_b", wires_list=[self.add_column_wire(column=col, bit=1) for col in range(1, len(self.columns))])
|
||||
final_adder = unsigned_adder_class_name(a=adder_a, b=adder_b, prefix=adder_prefix)
|
||||
adder_name = unsigned_adder_class_name(a=a, b=b).prefix + str(len(self.columns)-1)
|
||||
adder_a = Bus(prefix=f"a", wires_list=[self.add_column_wire(column=col, bit=0) for col in range(1, len(self.columns))])
|
||||
adder_b = Bus(prefix=f"b", wires_list=[self.add_column_wire(column=col, bit=1) for col in range(1, len(self.columns))])
|
||||
final_adder = unsigned_adder_class_name(a=adder_a, b=adder_b, prefix=self.prefix, name=adder_name, inner_component=True)
|
||||
self.add_component(final_adder)
|
||||
|
||||
[self.out.connect(o, final_adder.out.get_wire(o-1), inserted_wire_desired_index=o-1) for o in range(1, len(self.out.bus))]
|
||||
|
@ -10,8 +10,10 @@ class Bus():
|
||||
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.
|
||||
out_bus (bool, optional): Specifies whether this Bus is an output bus of some previous component. Defaults to False.
|
||||
"""
|
||||
def __init__(self, prefix: str = "bus", N: int = 1, wires_list: list = None):
|
||||
def __init__(self, prefix: str = "bus", N: int = 1, wires_list: list = None, out_bus: bool = False):
|
||||
self.out_bus = out_bus
|
||||
if wires_list is None:
|
||||
self.prefix = prefix
|
||||
# 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)
|
||||
@ -22,6 +24,14 @@ class Bus():
|
||||
self.bus = wires_list
|
||||
self.N = len(self.bus)
|
||||
|
||||
def is_output_bus(self):
|
||||
"""Tells whether this Bus is an output bus.
|
||||
|
||||
Returns:
|
||||
bool: Returns True if it is an output bus of some component.
|
||||
"""
|
||||
return self.out_bus
|
||||
|
||||
def bus_extend(self, N: int, prefix: str = "bus"):
|
||||
"""Provides bus extension to contain more wires.
|
||||
|
||||
@ -69,6 +79,14 @@ class Bus():
|
||||
elif inserted_wire_desired_index != -1:
|
||||
self.bus[bus_wire_index] = Wire(name=inner_component_out_wire.name, prefix=inner_component_out_wire.parent_bus.prefix, index=inserted_wire_index, value=inner_component_out_wire.value, parent_bus=self)
|
||||
|
||||
# TODO
|
||||
def connect_bus(self, connecting_bus, start_connection_pos: int = 0, end_connection_pos: int = -1):
|
||||
if end_connection_pos == -1:
|
||||
end_connection_pos = self.N
|
||||
|
||||
# Nakonec je potřeba napojit výstup adderu na výstup mac
|
||||
[self.connect(o, connecting_bus.get_wire(o), inserted_wire_desired_index=o) for o in range(start_connection_pos, end_connection_pos)]
|
||||
|
||||
""" C CODE GENERATION """
|
||||
def get_declaration_c(self):
|
||||
"""Bus declaration in C code.
|
||||
|
7
chr2c.py
7
chr2c.py
@ -10,7 +10,7 @@ import argparse
|
||||
|
||||
# Parse all nodes present in input CGP
|
||||
def parse_node(n):
|
||||
return list(map(int, re.match(r"(\d+),(\d+),(\d+)", n).groups()))
|
||||
return list(map(int, re.match(r"\[(\d+)\](\d+),(\d+),(\d+)", n).groups()))
|
||||
|
||||
|
||||
# Recursively detect wires required to get the result wire with id 'id' and activate them (will be generated)
|
||||
@ -56,10 +56,7 @@ def parse_chromosome(chromosome, signed=False, function=None):
|
||||
cdata_dict = [None for i in range(0, c_cols * c_rows)]
|
||||
|
||||
for id, chromosome in enumerate(cdata):
|
||||
a = chromosome[0]
|
||||
b = chromosome[1]
|
||||
f = chromosome[2]
|
||||
|
||||
cid, a, b, f = chromosome
|
||||
cdata_dict[id] = (id + 2 + c_in, a, b, f)
|
||||
|
||||
# Reserve position for all wires present in the genotype
|
||||
|
24
generate_mac.py
Normal file
24
generate_mac.py
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
from ariths_gen.core.arithmetic_circuits.arithmetic_circuit import ArithmeticCircuit
|
||||
from ariths_gen.core.arithmetic_circuits import GeneralCircuit
|
||||
from ariths_gen.wire_components import Bus, Wire
|
||||
from ariths_gen.multi_bit_circuits.adders import UnsignedRippleCarryAdder
|
||||
from ariths_gen.multi_bit_circuits.multipliers import UnsignedArrayMultiplier, UnsignedDaddaMultiplier
|
||||
import os
|
||||
|
||||
class MAC(GeneralCircuit):
|
||||
def __init__(self, a: Bus, b: Bus, r: Bus, prefix: str = "", name: str = "mac", **kwargs):
|
||||
super().__init__(prefix=prefix, name=name, out_N=2*a.N+1, inputs=[a, b, r], **kwargs)
|
||||
assert a.N == b.N
|
||||
assert r.N == 2 * a.N
|
||||
|
||||
self.mul = self.add_component(UnsignedArrayMultiplier(a=a, b=b, prefix=self.prefix, name=f"u_arrmul{a.N}", inner_component=True))
|
||||
self.add = self.add_component(UnsignedRippleCarryAdder(a=r, b=self.mul.out, prefix=self.prefix, name=f"u_rca{r.N}", inner_component=True))
|
||||
self.out.connect_bus(connecting_bus=self.add.out)
|
||||
|
||||
# usage
|
||||
os.makedirs("test_circuits/mac", exist_ok=True)
|
||||
mymac = MAC(Bus("a", 8), Bus("b", 8), Bus("acc", 16))
|
||||
mymac.get_v_code_hier(open("test_circuits/mac/mac_hier.v", "w"))
|
||||
mymac.get_c_code_hier(open("test_circuits/mac/mac_hier.c", "w"))
|
||||
mymac.get_c_code_flat(open("test_circuits/mac/mac_flat.c", "w"))
|
@ -80,116 +80,116 @@ if __name__ == "__main__":
|
||||
|
||||
# RCA
|
||||
name = f"u_rca{N}"
|
||||
circuit = UnsignedRippleCarryAdder(a, b, prefix=name)
|
||||
circuit = UnsignedRippleCarryAdder(a, b, name=name)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_rca{N}"
|
||||
circuit = SignedRippleCarryAdder(a, b, prefix=name)
|
||||
circuit = SignedRippleCarryAdder(a, b, name=name)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
# RCA with PG
|
||||
name = f"u_pg_rca{N}"
|
||||
circuit = UnsignedPGRippleCarryAdder(a, b, prefix=name)
|
||||
circuit = UnsignedPGRippleCarryAdder(a, b, name=name)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_pg_rca{N}"
|
||||
circuit = SignedPGRippleCarryAdder(a, b, prefix=name)
|
||||
circuit = SignedPGRippleCarryAdder(a, b, name=name)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
# CSKA with 4 bit CSKA blocks (default)
|
||||
name = f"u_cska{N}"
|
||||
circuit = UnsignedCarrySkipAdder(a, b, prefix=name)
|
||||
circuit = UnsignedCarrySkipAdder(a, b, name=name)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_cska{N}"
|
||||
circuit = SignedCarrySkipAdder(a, b, prefix=name)
|
||||
circuit = SignedCarrySkipAdder(a, b, name=name)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
# CLA with 4 bit CLA blocks (default)
|
||||
name = f"u_cla{N}"
|
||||
circuit = UnsignedCarryLookaheadAdder(a, b, prefix=name)
|
||||
circuit = UnsignedCarryLookaheadAdder(a, b, name=name)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_cla{N}"
|
||||
circuit = SignedCarryLookaheadAdder(a, b, prefix=name)
|
||||
circuit = SignedCarryLookaheadAdder(a, b, name=name)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
# Arrmul
|
||||
name = f"u_arrmul{N}"
|
||||
circuit = UnsignedArrayMultiplier(a, b, prefix=name)
|
||||
circuit = UnsignedArrayMultiplier(a, b, name=name)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_arrmul{N}"
|
||||
circuit = SignedArrayMultiplier(a, b, prefix=name)
|
||||
circuit = SignedArrayMultiplier(a, b, name=name)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
# Wallace
|
||||
name = f"u_wallace_cla{N}"
|
||||
circuit = UnsignedWallaceMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedCarryLookaheadAdder)
|
||||
circuit = UnsignedWallaceMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedCarryLookaheadAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_wallace_cla{N}"
|
||||
circuit = SignedWallaceMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedCarryLookaheadAdder)
|
||||
circuit = SignedWallaceMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedCarryLookaheadAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"u_wallace_rca{N}"
|
||||
circuit = UnsignedWallaceMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedRippleCarryAdder)
|
||||
circuit = UnsignedWallaceMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedRippleCarryAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_wallace_rca{N}"
|
||||
circuit = SignedWallaceMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedRippleCarryAdder)
|
||||
circuit = SignedWallaceMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedRippleCarryAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"u_wallace_pg_rca{N}"
|
||||
circuit = UnsignedWallaceMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedPGRippleCarryAdder)
|
||||
circuit = UnsignedWallaceMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedPGRippleCarryAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_wallace_pg_rca{N}"
|
||||
circuit = SignedWallaceMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedPGRippleCarryAdder)
|
||||
circuit = SignedWallaceMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedPGRippleCarryAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"u_wallace_cska{N}"
|
||||
circuit = UnsignedWallaceMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedCarrySkipAdder)
|
||||
circuit = UnsignedWallaceMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedCarrySkipAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_wallace_cska{N}"
|
||||
circuit = SignedWallaceMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedCarrySkipAdder)
|
||||
circuit = SignedWallaceMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedCarrySkipAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
# Dadda
|
||||
name = f"u_dadda_cla{N}"
|
||||
circuit = UnsignedDaddaMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedCarryLookaheadAdder)
|
||||
circuit = UnsignedDaddaMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedCarryLookaheadAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_dadda_cla{N}"
|
||||
circuit = SignedDaddaMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedCarryLookaheadAdder)
|
||||
circuit = SignedDaddaMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedCarryLookaheadAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"u_dadda_rca{N}"
|
||||
circuit = UnsignedDaddaMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedRippleCarryAdder)
|
||||
circuit = UnsignedDaddaMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedRippleCarryAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_dadda_rca{N}"
|
||||
circuit = SignedDaddaMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedRippleCarryAdder)
|
||||
circuit = SignedDaddaMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedRippleCarryAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"u_dadda_pg_rca{N}"
|
||||
circuit = UnsignedDaddaMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedPGRippleCarryAdder)
|
||||
circuit = UnsignedDaddaMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedPGRippleCarryAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_dadda_pg_rca{N}"
|
||||
circuit = SignedDaddaMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedPGRippleCarryAdder)
|
||||
circuit = SignedDaddaMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedPGRippleCarryAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"u_dadda_cska{N}"
|
||||
circuit = UnsignedDaddaMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedCarrySkipAdder)
|
||||
circuit = UnsignedDaddaMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedCarrySkipAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
name = f"s_dadda_cska{N}"
|
||||
circuit = SignedDaddaMultiplier(a, b, prefix=name, unsigned_adder_class_name=UnsignedCarrySkipAdder)
|
||||
circuit = SignedDaddaMultiplier(a, b, name=name, unsigned_adder_class_name=UnsignedCarrySkipAdder)
|
||||
export_circuit(circuit, name)
|
||||
|
||||
# Arrdiv
|
||||
name = f"arrdiv{N}"
|
||||
circuit = ArrayDivider(a, b, prefix=name)
|
||||
circuit = ArrayDivider(a, b, name=name)
|
||||
export_circuit(circuit, name)
|
||||
|
23
tests/mac.c
Normal file
23
tests/mac.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
uint64_t mac(uint64_t a,uint64_t b,uint64_t acc);
|
||||
|
||||
|
||||
int main() {
|
||||
int result = 0;
|
||||
|
||||
srand(42);
|
||||
for(int i = 0; i < 10000; i++) {
|
||||
uint64_t a, b, acc;
|
||||
a = rand() % 256;
|
||||
b = rand() % 256;
|
||||
acc = rand() % 65536;
|
||||
result = (a * b) + acc;
|
||||
|
||||
assert(result == mac(a, b, acc));
|
||||
}
|
||||
return 0;
|
||||
}
|
35
tests/test_mac.sh
Normal file
35
tests/test_mac.sh
Normal file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
valid=1
|
||||
|
||||
test_circuit_mac () {
|
||||
local type=$1
|
||||
|
||||
|
||||
|
||||
for mode in "flat" "hier"; do
|
||||
echo -e "===== Testing \e[33mMAC\e[0m ($mode) ======"
|
||||
|
||||
g++ -std=c++11 -pedantic -g -std=c++11 -pedantic -DCNAME="$circuit" $type.c ../test_circuits/mac/mac_$mode.c -o tmp.exe
|
||||
if ./tmp.exe ; then
|
||||
echo -e "[\e[32mok\e[0m]"
|
||||
else
|
||||
echo -e "[\e[31mfail\e[0m]"
|
||||
valid=0
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
|
||||
test_circuit_mac "mac"
|
||||
|
||||
|
||||
|
||||
if [ $valid -eq 1 ]; then
|
||||
echo "all tests passed"
|
||||
exit 0
|
||||
else
|
||||
echo "some of tests failed"
|
||||
exit 1
|
||||
fi
|
Loading…
x
Reference in New Issue
Block a user