Added documentation of classes methods.
This commit is contained in:
parent
a328e91996
commit
068def0226
@ -20,7 +20,7 @@ python3 ariths_gen.py
|
||||
## Documentation
|
||||
Code documentation is provided using **pdoc** documentation generator tool. Source: https://pdoc3.github.io/pdoc/.
|
||||
|
||||
### Instalation
|
||||
### Installation
|
||||
```bash
|
||||
pip3 install pdoc3
|
||||
```
|
||||
|
@ -27,15 +27,41 @@ class ArithmeticCircuit():
|
||||
self.N = 1
|
||||
|
||||
def add_component(self, component):
|
||||
"""Adds component into a list of circuit's inner subcomponents.
|
||||
|
||||
Args:
|
||||
component: Subcomponent to be added into list of components composing described circuit.
|
||||
"""
|
||||
self.components.append(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):
|
||||
"""Informs how many instances of the same type are already present inside circuit's components list.
|
||||
|
||||
Args:
|
||||
cls (type): Class type of which to search for instances.
|
||||
|
||||
Returns:
|
||||
int: Number of instances of the same class type.
|
||||
"""
|
||||
return sum(isinstance(c, cls) for c in self.components)
|
||||
|
||||
def get_unique_one_bit_components(self):
|
||||
def get_one_bit_components(self):
|
||||
"""Retrieves list of all 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, LogicGate):
|
||||
@ -43,11 +69,16 @@ class ArithmeticCircuit():
|
||||
elif type(getattr(c, 'a')) == Wire:
|
||||
one_bit_comps.append(c)
|
||||
else:
|
||||
one_bit_comps.extend(c.get_unique_one_bit_components())
|
||||
one_bit_comps.extend(c.get_one_bit_components())
|
||||
|
||||
return one_bit_comps
|
||||
|
||||
def get_unique_multi_bit_components(self):
|
||||
def get_multi_bit_components(self):
|
||||
"""Retrieves list of all 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, LogicGate):
|
||||
@ -60,23 +91,51 @@ class ArithmeticCircuit():
|
||||
|
||||
@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 list of all unique types of subcomponents composing the circuit.
|
||||
|
||||
Returning list consists of 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_unique_one_bit_components())
|
||||
multi_bit_comps = self.get_unique_types(components=self.get_unique_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
|
||||
|
||||
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 get_circuit_wires(self):
|
||||
"""Retrieves all the unique wires used for interconnecting subcomponents inside the circuit and stores them inside `self.circuit_wires` list.
|
||||
Additionally stores all unique names of just the inner input wires inside `self.inputs` list.
|
||||
"""
|
||||
self.circuit_wires = []
|
||||
for component in self.components:
|
||||
if not [item for item in self.circuit_wires if item[1] == component.a.name]:
|
||||
@ -91,14 +150,25 @@ class ArithmeticCircuit():
|
||||
# Get unique names of all inner input circuits (mainly used in one bit circuits)
|
||||
self.inputs = [i[0] for i in self.circuit_wires if i[0] not in [o.out for o in self.components]]
|
||||
|
||||
# Search for circuit's wire unique index for cgp chromosome generation
|
||||
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.
|
||||
"""
|
||||
for w in self.circuit_wires:
|
||||
if wire.name.endswith(w[1]):
|
||||
return w[2]
|
||||
|
||||
# Get list of all gates present in circuit
|
||||
def get_circuit_gates(self):
|
||||
"""Gets list of all logic gates present in circuit.
|
||||
|
||||
Returns:
|
||||
list: List of composite logic gates.
|
||||
"""
|
||||
gates = []
|
||||
for c in self.components:
|
||||
if isinstance(c, LogicGate):
|
||||
@ -107,8 +177,9 @@ class ArithmeticCircuit():
|
||||
gates.extend((c.get_circuit_gates()))
|
||||
return gates
|
||||
|
||||
# Get list of all wires in circuit along with their index position for cgp chromosome generation
|
||||
def get_cgp_wires(self):
|
||||
"""Gets list of all wires in circuit along with their index position for cgp chromosome generation and stores them inside `self.circuit_wires` list.
|
||||
"""
|
||||
self.circuit_wires = []
|
||||
if isinstance(self.a, Bus):
|
||||
[self.circuit_wires.append((w, f"_{w.name}", len(self.circuit_wires))) for w in self.a.bus]
|
||||
@ -133,34 +204,74 @@ class ArithmeticCircuit():
|
||||
# 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}({self.c_data_type} {self.a.prefix}, {self.c_data_type} {self.b.prefix})" + "{" + "\n"
|
||||
|
||||
def get_declarations_c_flat(self):
|
||||
"""Generates flat C code declaration of input/output buses wires.
|
||||
|
||||
Returns:
|
||||
str: Flattened C code arithmetic circuit's wires declaration.
|
||||
"""
|
||||
return f"{self.a.get_wire_declaration_c()}" + \
|
||||
f"{self.b.get_wire_declaration_c()}" + \
|
||||
f"".join([c.get_declaration_c_flat() for c in self.components])
|
||||
|
||||
# For multi-bit circuit wires declaration
|
||||
def get_declaration_c_flat(self):
|
||||
"""Generates flat C code declaration of input/output buses wires of multi-bit arithmetic circuit present as subcomponent in the circuit.
|
||||
|
||||
Returns:
|
||||
str: Flattened C code multi-bit arithmetic circuit subcomponent wires declaration.
|
||||
"""
|
||||
return f"".join([c.get_declaration_c_flat() for c in self.components])
|
||||
|
||||
def get_inits_c_flat(self):
|
||||
"""Generates flat C code initialization and assignment of corresponding arithmetic circuit's input/output buses wires.
|
||||
|
||||
Returns:
|
||||
str: Flattened C code initialization of arithmetic circuit wires.
|
||||
"""
|
||||
return f"{self.a.get_wire_assign_c()}" + \
|
||||
f"{self.b.get_wire_assign_c()}" + \
|
||||
"".join([c.get_assign_c_flat() if isinstance(c, LogicGate) else c.get_init_c_flat() for c in self.components])
|
||||
|
||||
# For multi-bit circuit wires initialization
|
||||
def get_init_c_flat(self):
|
||||
"""Generates flat C code initialization and assignment of input/output buses wires of multi-bit arithmetic circuit present as subcomponent in the circuit.
|
||||
|
||||
Returns:
|
||||
str: Flattened C code multi-bit arithmetic circuit subcomponent wires initialization.
|
||||
"""
|
||||
return "".join([c.get_assign_c_flat() if isinstance(c, LogicGate) 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: Flattened C code containing output bus wires assignment.
|
||||
"""
|
||||
return "".join([f" {self.out.prefix} |= {o.return_wire_value_c(offset=self.out.bus.index(o))};\n" for o in self.out.bus])
|
||||
|
||||
# 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())
|
||||
@ -172,33 +283,71 @@ class ArithmeticCircuit():
|
||||
|
||||
# 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.
|
||||
"""
|
||||
# Add 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 adder name with its bit width
|
||||
adder_prefix = self.__class__(a=Bus("a"), b=Bus("b")).prefix + str(self.N)
|
||||
adder_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(N=self.N, prefix="b"), prefix=adder_prefix)
|
||||
return f"{adder_block.get_circuit_c()}\n\n"
|
||||
|
||||
def get_declaration_c_hier(self):
|
||||
"""Generates hierarchical C code declaration of input/output buses wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code containing unique declaration of arithmetic circuit wires.
|
||||
"""
|
||||
return "".join(self.a.get_wire_declaration_c()) + \
|
||||
"".join(self.b.get_wire_declaration_c()) + \
|
||||
"".join([c.out.get_declaration_c() if isinstance(c, LogicGate) else c.get_wire_declaration_c_hier() for c in self.components])
|
||||
|
||||
def get_wire_declaration_c_hier(self):
|
||||
"""Generates hierarchical C code declaration of corresponding subcomponent input/output buses wires inside the upper component.
|
||||
|
||||
Generates wires used to connect input/output values to/from invocation of the correspoding 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.prefix}_{self.a.prefix} = 0;\n" + \
|
||||
f" {self.c_data_type} {self.prefix}_{self.b.prefix} = 0;\n" + \
|
||||
f" {self.c_data_type} {self.prefix}_{self.out.prefix} = 0;\n" + \
|
||||
f"{self.out.get_wire_declaration_c()}"
|
||||
|
||||
def get_init_c_hier(self):
|
||||
"""Generates hierarchical C code initialization and assignment of corresponding arithmetic circuit's input/output buses wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code initialization of arithmetic circuit wires.
|
||||
"""
|
||||
return f"{self.a.get_wire_assign_c()}" + \
|
||||
f"{self.b.get_wire_assign_c()}" + \
|
||||
"".join([f" {c.out.name} = {c.get_gate_invocation_c()}" if isinstance(c, LogicGate) 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 correspoding 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 and insitu copying out bus for proper C code generation without affecting actual generated composition
|
||||
circuit_type = self.prefix.replace(circuit_prefix+"_", "")
|
||||
out = Bus(prefix=self.prefix+"_"+self.out.prefix, wires_list=self.out.bus)
|
||||
@ -208,9 +357,19 @@ class ArithmeticCircuit():
|
||||
f"{out.get_wire_assign_c()}"
|
||||
|
||||
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 "".join([f" {self.out.prefix} |= {o.return_wire_value_c(offset=self.out.bus.index(o))};\n" for o in self.out.bus])
|
||||
|
||||
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_declaration_c_hier()}\n" + \
|
||||
@ -220,6 +379,11 @@ class ArithmeticCircuit():
|
||||
|
||||
# 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())
|
||||
@ -228,29 +392,66 @@ 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.
|
||||
|
||||
Returns:
|
||||
str: Module's name and parameters in Verilog code.
|
||||
"""
|
||||
return f"module {self.prefix}(input [{self.N-1}:0] {self.a.prefix}, input [{self.N-1}:0] {self.b.prefix}, output [{self.out.N-1}:0] {self.out.prefix});\n"
|
||||
|
||||
def get_declarations_v_flat(self):
|
||||
"""Generates flat Verilog code declaration of input/output buses wires.
|
||||
|
||||
Returns:
|
||||
str: Flattened Verilog code arithmetic circuit's wires declaration.
|
||||
"""
|
||||
return f"{self.a.get_wire_declaration_v()}" + \
|
||||
f"{self.b.get_wire_declaration_v()}" + \
|
||||
f"".join([c.get_declaration_v_flat() for c in self.components])
|
||||
|
||||
# For multi-bit circuit wires declaration
|
||||
def get_declaration_v_flat(self):
|
||||
"""Generates flat Verilog code declaration of input/output buses wires of multi-bit arithmetic circuit present as subcomponent in the circuit.
|
||||
|
||||
Returns:
|
||||
str: Flattened Verilog code multi-bit arithmetic circuit subcomponent wires declaration.
|
||||
"""
|
||||
return f"".join([c.get_declaration_v_flat() for c in self.components])
|
||||
|
||||
def get_inits_v_flat(self):
|
||||
"""Generates flat Verilog code initialization and assignment of corresponding arithmetic circuit's input/output buses wires.
|
||||
|
||||
Returns:
|
||||
str: Flattened Verilog code initialization of arithmetic circuit wires.
|
||||
"""
|
||||
return f"{self.a.get_wire_assign_v()}" + \
|
||||
f"{self.b.get_wire_assign_v()}" + \
|
||||
"".join([c.get_assign_v_flat() if isinstance(c, LogicGate) else c.get_init_v_flat() for c in self.components])
|
||||
|
||||
# For multi-bit circuit wires initialization
|
||||
def get_init_v_flat(self):
|
||||
"""Generates flat Verilog code initialization and assignment of input/output buses wires of multi-bit arithmetic circuit present as subcomponent in the circuit.
|
||||
|
||||
Returns:
|
||||
str: Flattened Verilog code multi-bit arithmetic circuit subcomponent wires initialization.
|
||||
"""
|
||||
return "".join([c.get_assign_v_flat() if isinstance(c, LogicGate) 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: Flattened Verilog code containing output bus wires assignment.
|
||||
"""
|
||||
return "".join([f" assign {self.out.prefix}[{self.out.bus.index(o)}] = {o.prefix};\n" for o in self.out.bus])
|
||||
|
||||
# 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_declarations_v_flat()+"\n")
|
||||
file_object.write(self.get_inits_v_flat() + "\n")
|
||||
@ -260,33 +461,71 @@ class ArithmeticCircuit():
|
||||
|
||||
# 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.
|
||||
"""
|
||||
# Add 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 adder name with its bit width
|
||||
adder_prefix = self.__class__(a=Bus("a"), b=Bus("b")).prefix + str(self.N)
|
||||
adder_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(N=self.N, prefix="b"), prefix=adder_prefix)
|
||||
return f"{adder_block.get_circuit_v()}\n\n"
|
||||
|
||||
def get_declaration_v_hier(self):
|
||||
"""Generates hierarchical Verilog code declaration of input/output buses wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code containing unique declaration of arithmetic circuit wires.
|
||||
"""
|
||||
return "".join(self.a.get_wire_declaration_v()) + \
|
||||
"".join(self.b.get_wire_declaration_v()) + \
|
||||
"".join([c.out.get_declaration_v() if isinstance(c, LogicGate) else c.get_wire_declaration_v_hier() for c in self.components])
|
||||
|
||||
def get_wire_declaration_v_hier(self):
|
||||
"""Generates hierarchical Verilog code declaration of corresponding subcomponent input/output buses wires inside the upper component.
|
||||
|
||||
Generates wires used to connect input/output values to/from invocation of the correspoding 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.prefix}_{self.a.prefix};\n" + \
|
||||
f" wire [{self.b.N-1}:0] {self.prefix}_{self.b.prefix};\n" + \
|
||||
f" wire [{self.out.N-1}:0] {self.prefix}_{self.out.prefix};\n" + \
|
||||
f"{self.out.get_wire_declaration_v()}"
|
||||
|
||||
def get_init_v_hier(self):
|
||||
"""Generates hierarchical Verilog code initialization and assignment of corresponding arithmetic circuit's input/output buses wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code initialization of arithmetic circuit wires.
|
||||
"""
|
||||
return f"{self.a.get_wire_assign_v()}" + \
|
||||
f"{self.b.get_wire_assign_v()}" + \
|
||||
"".join([c.get_gate_invocation_v() if isinstance(c, LogicGate) else c.get_invocation_v(circuit_prefix=self.prefix) for c in self.components])
|
||||
|
||||
def get_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 correspoding 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+"_", "")
|
||||
out = Bus(prefix=self.prefix+"_"+self.out.prefix, wires_list=self.out.bus)
|
||||
@ -296,9 +535,19 @@ class ArithmeticCircuit():
|
||||
f"{out.get_wire_assign_v()}"
|
||||
|
||||
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 "".join([f" assign {self.out.prefix}[{self.out.bus.index(o)}] = {o.name};\n" for o in self.out.bus])
|
||||
|
||||
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_declaration_v_hier()}\n" + \
|
||||
f"{self.get_init_v_hier()}\n" + \
|
||||
@ -307,6 +556,11 @@ class ArithmeticCircuit():
|
||||
|
||||
# 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()
|
||||
@ -314,9 +568,19 @@ class ArithmeticCircuit():
|
||||
""" 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 arithmetic circuit's input/output buses wires.
|
||||
|
||||
Returns:
|
||||
str: Flattened Blif code containing declaration of circuit's interface wires.
|
||||
"""
|
||||
if self.N == 1:
|
||||
return f".inputs {self.a.prefix} {self.b.prefix}\n" + \
|
||||
f".outputs{self.out.get_wire_declaration_blif()}\n" + \
|
||||
@ -329,13 +593,28 @@ class ArithmeticCircuit():
|
||||
f"{self.b.get_wire_assign_blif()}"
|
||||
|
||||
def get_function_blif_flat(self):
|
||||
"""Generates flat Blif code with unique input wire mapping and invocation of subcomponents functions via their corresponding truth tables.
|
||||
|
||||
Returns:
|
||||
str: Flattened Blif code containing input wires mapping and inner subcomponents Boolean functions invocation.
|
||||
"""
|
||||
return "".join(c.get_init_function_blif_flat() if isinstance(c, LogicGate) else c.get_function_blif_flat() for c in self.components)
|
||||
|
||||
def get_function_out_blif(self):
|
||||
"""Generates flat Blif code mapping of corresponding arithmetic circuit's output bus wires.
|
||||
|
||||
Returns:
|
||||
str: Flattened Blif code containing output bus wires assignment mapping.
|
||||
"""
|
||||
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())
|
||||
@ -345,9 +624,25 @@ class ArithmeticCircuit():
|
||||
|
||||
# HIERARCHICAL BLIF #
|
||||
def get_function_blif_hier(self):
|
||||
"""Generates hierarchical Blif code with unique input wire mapping and invocation of subcomponents function blocks.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Blif code containing input wires mapping and inner subcomponents function blocks invocation.
|
||||
"""
|
||||
return "".join(c.get_invocation_blif_hier(init=True) if isinstance(c, LogicGate) else 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.
|
||||
|
||||
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 correspoding 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 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 "".join([w.get_assign_blif(name=self.prefix+'_'+self.a.prefix+f'[{self.a.bus.index(w)}]', output=True)for w in self.a.bus]) + \
|
||||
@ -358,6 +653,11 @@ class ArithmeticCircuit():
|
||||
"".join([f" 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_function_blif_hier()}" + \
|
||||
@ -365,11 +665,21 @@ class ArithmeticCircuit():
|
||||
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.
|
||||
"""
|
||||
# Add unique component types composing this circuit
|
||||
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 adder name with its bit width
|
||||
adder_prefix = self.__class__(a=Bus("a"), b=Bus("b")).prefix + str(self.N)
|
||||
adder_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(N=self.N, prefix="b"), prefix=adder_prefix)
|
||||
@ -377,6 +687,11 @@ class ArithmeticCircuit():
|
||||
|
||||
# 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()
|
||||
@ -384,18 +699,42 @@ class ArithmeticCircuit():
|
||||
""" 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_triplet_cgp(self):
|
||||
"""Generates list of logic gate triplets (2 input wires, 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.
|
||||
|
||||
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_index=self.get_circuit_wire_index(g.a), b_index=self.get_circuit_wire_index(g.b)) for g in self.circuit_gates])
|
||||
|
||||
def get_output_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[::-1]]) + ")"
|
||||
|
||||
# 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_triplet_cgp())
|
||||
file_object.write(self.get_output_cgp())
|
||||
|
@ -29,9 +29,17 @@ class MultiplierCircuit(ArithmeticCircuit):
|
||||
super().__init__()
|
||||
|
||||
""" Array multipliers """
|
||||
# Used in array multipliers to get previous row's component output wires
|
||||
# for further connection to another component's input
|
||||
def get_previous_partial_product(self, a_index: int, b_index: int, offset: int = 0):
|
||||
"""Used in array multipliers to get previous row's component output wires for further connection to another component's input.
|
||||
|
||||
Args:
|
||||
a_index (int): First input wire index.
|
||||
b_index (int): Second input wire index.
|
||||
offset (int, optional): Offset to properly retrieve previous partial product. Defaults to 0.
|
||||
|
||||
Returns:
|
||||
Wire: Previous row's component wire of corresponding pp.
|
||||
"""
|
||||
# To get the index of previous row's connecting adder and its generated pp
|
||||
index = ((b_index-2) * (self.N*2)) + ((self.N-1)+2*(a_index+2)) + offset
|
||||
|
||||
@ -44,9 +52,21 @@ class MultiplierCircuit(ArithmeticCircuit):
|
||||
return self.components[index].get_sum_wire()
|
||||
|
||||
""" Dadda multiplier """
|
||||
# Used in dadda multipliers to get multiplier's maximum height
|
||||
@staticmethod
|
||||
def get_maximum_height(initial_value: int):
|
||||
"""Used in dadda multipliers to get multiplier's maximum height.
|
||||
|
||||
Maximum height sequence as defined here: https://en.wikipedia.org/wiki/Dadda_multiplier
|
||||
d(j=1) = 2; d(j+1) = floor(1.5*d)
|
||||
|
||||
`j` stands for initial stage value
|
||||
`d` stands for maximum height for current initial stage value
|
||||
Args:
|
||||
initial_value (int): Initial algorithms stage value.
|
||||
|
||||
Returns:
|
||||
int, int: Current algorithms stage and maximum bits (height) allowed in a column for current stage.
|
||||
"""
|
||||
stage = 0
|
||||
d = 2
|
||||
while True:
|
||||
@ -58,12 +78,26 @@ class MultiplierCircuit(ArithmeticCircuit):
|
||||
if d >= initial_value:
|
||||
return stage, max_height
|
||||
|
||||
def init_column_heights(self, signed=False):
|
||||
def init_column_heights(self):
|
||||
"""Creates appropriate number of partial product columns along with filling them with corresponding number of bit pairs.
|
||||
|
||||
Returns:
|
||||
list: List of partial product columns with their bit pairs.
|
||||
"""
|
||||
columns = [[num] if num <= self.N else [num - (num - self.N)*2] for num in range(1, self.out.N)]
|
||||
columns = [self.add_column_wires(column=col, column_index=columns.index(col)) for col in columns]
|
||||
return columns
|
||||
|
||||
def add_column_wires(self, column: list, column_index: int):
|
||||
"""Fills circuit's partial product column with corresponding bit pairs.
|
||||
|
||||
Args:
|
||||
column (list): List representing column of partial product bits.
|
||||
column_index (int): Index of partial products column.
|
||||
|
||||
Returns:
|
||||
list: Updated column list containing corresponding number of input bit pairs to form proper pp column.
|
||||
"""
|
||||
[column.append([]) for _ in range(column[0])]
|
||||
if column_index <= self.N-1:
|
||||
[column[column[0]-index].append(self.a.get_wire(index)) for index in range(0, column[0])]
|
||||
@ -72,7 +106,6 @@ class MultiplierCircuit(ArithmeticCircuit):
|
||||
[column[self.a.N-index].append(self.a.get_wire(index)) for index in range(self.a.N-1, self.a.N-column[0]-1, -1)]
|
||||
[column[index-(self.a.N-1-column[0])].append(self.b.get_wire(index)) for index in range(self.a.N-column[0], self.a.N)]
|
||||
|
||||
# TODO check and refactor
|
||||
# Filling unsigned pp matrix with AND gates
|
||||
if self.__class__.__name__ == "unsigned_dadda_multiplier" or self.__class__.__name__ == "unsigned_wallace_multiplier":
|
||||
column[1:] = [AndGate(a=column[i][0], b=column[i][1], prefix=self.prefix+'_and_'+str(column[i][0].index)+'_'+str(column[i][1].index)) for i in range(1, len(column))]
|
||||
@ -91,14 +124,45 @@ class MultiplierCircuit(ArithmeticCircuit):
|
||||
return column
|
||||
|
||||
def get_column_height(self, column_num: int):
|
||||
"""Retrieves the current height of desired partial products column.
|
||||
|
||||
Args:
|
||||
column_num (int): Index of pp column.
|
||||
|
||||
Returns:
|
||||
int: Height of the current bit column.
|
||||
"""
|
||||
return self.columns[column_num][0]
|
||||
|
||||
def update_column_heights(self, curr_column: int, curr_height_change: int, next_column: int = 0, next_height_change: int = 0):
|
||||
"""Updates height of desired column and optionally also its subsequent column.
|
||||
|
||||
Used within dadda and wallace multipliers to perform gradual reduction of partial product columns through the stages.
|
||||
Allows to choose the height change to take effect on the chosen column index and optionally also the same for the following
|
||||
column if it should also be affected.
|
||||
|
||||
Args:
|
||||
curr_column (int): Current pp column index.
|
||||
curr_height_change (int): Height change for the chosen current pp column.
|
||||
next_column (int, optional): Subsequent pp column index. Defaults to 0.
|
||||
next_height_change (int, optional): Height change for the chosen subsequent pp column. Defaults to 0.
|
||||
"""
|
||||
self.columns[curr_column][0] = self.get_column_height(curr_column)+curr_height_change
|
||||
if next_column-1 == curr_column:
|
||||
self.columns[next_column][0] = self.get_column_height(next_column)+next_height_change
|
||||
|
||||
def get_column_wire(self, column: int, bit: int):
|
||||
"""Retrieves wire from desired partial product column bit position.
|
||||
|
||||
If bit pair is present at the desired position, it is reduced to one wire with AND/NAND gate accordingly.
|
||||
|
||||
Args:
|
||||
column (int): Partial product column index.
|
||||
bit (int): Bit position within the chosen column.
|
||||
|
||||
Returns:
|
||||
Wire: Return Wire present at specified position.
|
||||
"""
|
||||
if isinstance(self.columns[column][bit], AndGate) or isinstance(self.columns[column][bit], NandGate):
|
||||
self.add_component(self.columns[column][bit])
|
||||
return self.get_previous_component(1).out
|
||||
@ -106,6 +170,16 @@ class MultiplierCircuit(ArithmeticCircuit):
|
||||
return self.columns[column][bit]
|
||||
|
||||
def update_column_wires(self, curr_column: int, adder: ArithmeticCircuit, next_column: int = 0):
|
||||
"""Provides bit height reduction of the chosen column.
|
||||
|
||||
Inserts chosen column's top bits into an `adder` circuit to reduce its bit height.
|
||||
Generated sum is stored to the bottom of the column and generated carry bit is stored to the top of the next column.
|
||||
|
||||
Args:
|
||||
curr_column (int): Current pp column index.
|
||||
adder (ArithmeticCircuit): Two/three input one bit adder.
|
||||
next_column (int, optional): Subsequent pp column index. Defaults to 0.
|
||||
"""
|
||||
if hasattr(adder, "c"):
|
||||
self.columns[curr_column].pop(1)
|
||||
self.columns[curr_column].pop(1)
|
||||
|
@ -13,11 +13,23 @@ class ThreeInputOneBitCircuit(TwoInputOneBitCircuit):
|
||||
# FLAT C #
|
||||
# Function prototype with three inputs
|
||||
def get_prototype_c(self):
|
||||
"""Generates C code function header to describe corresponding three input one bit circuit's interface in C code.
|
||||
|
||||
Returns:
|
||||
str: Function's name and parameters in C code.
|
||||
"""
|
||||
return f"{self.c_data_type} {self.prefix}({self.c_data_type} {self.a.prefix}, {self.c_data_type} {self.b.prefix}, {self.c_data_type} {self.c.prefix})" + "{" + "\n"
|
||||
|
||||
# HIERARCHICAL C #
|
||||
# Subcomponent generation (3 inputs)
|
||||
# Subcomponent generation (three inputs)
|
||||
def get_out_invocation_c(self, **kwargs):
|
||||
"""Generates hierarchical C code invocation of corresponding three input one bit circuit's generated function block.
|
||||
|
||||
Assigns output values from invocation of the correspoding function block into inner wires present inside the upper component from which function block has been invoked.
|
||||
|
||||
Returns:
|
||||
str: Hierarchiacal C code subcomponent's C function invocation and output assignment.
|
||||
"""
|
||||
circuit_class = self.__class__()
|
||||
return "".join([f' {o.name} = ({circuit_class.prefix}({self.a.name}, {self.b.name}, {self.c.name}) >> {self.out.bus.index(o)}) & 0x01;\n' for o in self.out.bus])
|
||||
|
||||
@ -25,11 +37,21 @@ class ThreeInputOneBitCircuit(TwoInputOneBitCircuit):
|
||||
# FLAT VERILOG #
|
||||
# Module prototype with three inputs
|
||||
def get_prototype_v(self):
|
||||
"""Generates Verilog module header to describe corresponding three input one bit circuit's interface in Verilog.
|
||||
|
||||
Returns:
|
||||
str: Module's name and parameters in Verilog.
|
||||
"""
|
||||
return f"module {self.prefix}(input {self.a.name}, input {self.b.name}, input {self.c.name}{''.join([f', output {o.name}' for o in self.out.bus])});\n"
|
||||
|
||||
# HIERARCHICAL VERILOG #
|
||||
# Subcomponent generation (3 inputs)
|
||||
# Subcomponent generation (three inputs)
|
||||
def get_invocation_v(self, **kwargs):
|
||||
"""Generates hierarchical Verilog code invocation of corresponding three input one bit circuit's generated function block.
|
||||
|
||||
Returns:
|
||||
str: Hierarchiacal Verilog code subcomponent's module invocation.
|
||||
"""
|
||||
circuit_class = self.__class__()
|
||||
return f" {circuit_class.prefix} {circuit_class.prefix}_{self.out.get_wire().name}({self.a.name}, {self.b.name}, {self.c.name}{''.join([f', {o.name}' for o in self.out.bus])});\n"
|
||||
|
||||
@ -37,12 +59,22 @@ class ThreeInputOneBitCircuit(TwoInputOneBitCircuit):
|
||||
# FLAT BLIF #
|
||||
# Model prototype with three inputs
|
||||
def get_declaration_blif(self):
|
||||
"""Generates flat Blif code declaration of three input one bit circuit's input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Flattened Blif code containing declaration of circuit's interface wires.
|
||||
"""
|
||||
return f".inputs {self.a.name} {self.b.name} {self.c.name}\n" + \
|
||||
f".outputs{self.out.get_wire_declaration_blif(array=False)}\n"
|
||||
|
||||
# HIERARCHICAL BLIF #
|
||||
# Subcomponent generation (3 inputs)
|
||||
def get_invocation_blif_hier(self, **kwargs):
|
||||
"""Generates hierarchical Blif code invocation of corresponding three input one bit circuit's generated function block.
|
||||
|
||||
Returns:
|
||||
str: Hierarchiacal Blif code subcomponent's model invocation.
|
||||
"""
|
||||
circuit_class = self.__class__()
|
||||
return f"{self.get_wire_mapping_blif()}" + \
|
||||
f".subckt {circuit_class.prefix} a={self.inputs[0].name} b={self.inputs[1].name} cin={self.inputs[2].name}{''.join([f' {o.name}={self.out.get_wire(circuit_class.out.bus.index(o)).name}' for o in circuit_class.out.bus])}\n"
|
||||
@ -51,5 +83,12 @@ class ThreeInputOneBitCircuit(TwoInputOneBitCircuit):
|
||||
# FLAT CGP #
|
||||
# Chromosome prototype with three inputs
|
||||
def get_parameters_cgp(self):
|
||||
"""Generates CGP chromosome parameters of corresponding three input one bit 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 circuit.
|
||||
"""
|
||||
self.circuit_gates = self.get_circuit_gates()
|
||||
return f"{{3,2,1,{len(self.circuit_gates)},2,1,0}}"
|
||||
|
@ -14,17 +14,32 @@ class TwoInputOneBitCircuit(ArithmeticCircuit):
|
||||
# Obtaining list of all the unique circuit wires from all contained logic gates
|
||||
# to ensure non-recurring declaration of same wires
|
||||
def get_declaration_c_flat(self):
|
||||
"""Generates flat C code declaration of input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Flattened C code containing unique declaration of circuit wires.
|
||||
"""
|
||||
self.get_circuit_wires()
|
||||
# Unique declaration of all circuit's interconnections
|
||||
return "".join([c[0].get_declaration_c() for c in self.circuit_wires])
|
||||
|
||||
# Wires values initialization and assignment
|
||||
def get_init_c_flat(self):
|
||||
"""Generates flat C code initialization and assignment of corresponding two input one bit circuit's input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Flattened C code initialization of two input one bit circuit wires.
|
||||
"""
|
||||
return "".join([i.get_assign_c(name=i.get_wire_value_c(name=i.name.replace(self.prefix+"_", ""))) for i in self.inputs]) + \
|
||||
"".join([f" {c.out.name} = {c.get_init_c_flat()};\n" for c in self.components])
|
||||
|
||||
# Generating flat C code representation of circuit
|
||||
def get_c_code_flat(self, file_object):
|
||||
"""Generates flat C code representation of corresponding two input one bit 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())
|
||||
@ -37,46 +52,100 @@ class TwoInputOneBitCircuit(ArithmeticCircuit):
|
||||
# HIERARCHICAL C #
|
||||
# Subcomponent generation
|
||||
def get_function_block_c(self):
|
||||
"""Generates hierarchical C code representation of corresponding two input one bit circuit used as function block in hierarchical circuit description.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code of two input one bit circuit's function block description.
|
||||
"""
|
||||
adder_block = self.__class__()
|
||||
return f"{adder_block.get_circuit_c()}\n\n"
|
||||
|
||||
def get_wire_declaration_c_hier(self):
|
||||
"""Generates hierarchical C code declaration of corresponding subcomponent output wires inside the upper component.
|
||||
|
||||
Generates wires used to connect output values from invocation of the correspoding function block into inner wires present inside the upper component from which function block has been invoked.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code of two input one bit circuit's output wires declaration.
|
||||
"""
|
||||
return f"{self.out.get_wire_declaration_c()}"
|
||||
|
||||
def get_out_invocation_c(self, **kwargs):
|
||||
"""Generates hierarchical C code invocation of corresponding two input one bit circuit's generated function block.
|
||||
|
||||
Assigns output values from invocation of the correspoding function block into inner wires present inside the upper component from which function block has been invoked.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code subcomponent's C function invocation and output assignment.
|
||||
"""
|
||||
circuit_class = self.__class__()
|
||||
return "".join([f' {o.name} = ({circuit_class.prefix}({self.a.name}, {self.b.name}) >> {self.out.bus.index(o)}) & 0x01;\n' for o in self.out.bus])
|
||||
|
||||
# Self circuit hierarchical generation
|
||||
def get_declaration_c_hier(self):
|
||||
"""Generates hierarchical C code declaration of input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code containing unique declaration of circuit wires.
|
||||
"""
|
||||
self.get_circuit_wires()
|
||||
# Unique declaration of all circuit's interconnections
|
||||
return "".join([c[0].get_declaration_c() for c in self.circuit_wires])
|
||||
|
||||
def get_init_c_hier(self):
|
||||
"""Generates hierarchical C code initialization and assignment of corresponding two input one bit circuit's input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code initialization of two input one bit circuit wires.
|
||||
"""
|
||||
return "".join([i.get_assign_c(name=i.get_wire_value_c(name=i.name.replace(self.prefix+"_", ""))) for i in self.inputs]) + \
|
||||
"".join([f" {c.out.name} = {c.get_gate_invocation_c(remove_prefix=False)}" for c in self.components])
|
||||
|
||||
def get_function_out_c_hier(self):
|
||||
"""Generates hierarchical C code assignment of corresponding two input one bit circuit's output wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical C code containing output bus wires assignment.
|
||||
"""
|
||||
return "".join([f" {self.out.prefix} |= {o.return_wire_value_c(offset=self.out.bus.index(o))};\n" for o in self.out.bus])
|
||||
|
||||
""" VERILOG CODE GENERATION """
|
||||
# FLAT VERILOG #
|
||||
def get_prototype_v(self):
|
||||
"""Generates Verilog module header to describe corresponding two input one bit circuit's interface in Verilog.
|
||||
|
||||
Returns:
|
||||
str: Module's name and parameters in Verilog.
|
||||
"""
|
||||
return f"module {self.prefix}(input {self.a.name}, input {self.b.name}{''.join([f', output {o.name}' for o in self.out.bus])});\n"
|
||||
|
||||
def get_declaration_v_flat(self):
|
||||
"""Generates flat Verilog code declaration of input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Flattened Verilog code containing unique declaration of circuit wires.
|
||||
"""
|
||||
self.get_circuit_wires()
|
||||
# Unique declaration of all circuit's interconnections
|
||||
return "".join([c[0].get_declaration_v() for c in self.circuit_wires])
|
||||
|
||||
# Wires values initialization and assignment
|
||||
def get_init_v_flat(self):
|
||||
"""Generates flat Verilog code initialization and assignment of corresponding two input one bit circuit's input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Flattened Verilog code initialization of two input one bit circuit wires.
|
||||
"""
|
||||
return "".join([i.get_assign_v(name=i.name.replace(self.prefix+"_", "")) for i in self.inputs]) + \
|
||||
"".join([f" assign {c.out.name} = {c.get_init_v_flat()};\n" for c in self.components])
|
||||
|
||||
# Generating flat Verilog code representation of circuit
|
||||
def get_v_code_flat(self, file_object):
|
||||
"""Generates flat Verilog code representation of corresponding two input one bit 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())
|
||||
@ -86,62 +155,141 @@ class TwoInputOneBitCircuit(ArithmeticCircuit):
|
||||
# HIERARCHICAL VERILOG #
|
||||
# Subcomponent generation
|
||||
def get_function_block_v(self):
|
||||
"""Generates hierarchical Verilog code representation of corresponding two input one bit circuit used as function block in hierarchical circuit description.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code of two input one bit circuit's function block description.
|
||||
"""
|
||||
adder_block = self.__class__()
|
||||
return f"{adder_block.get_circuit_v()}\n\n"
|
||||
|
||||
def get_wire_declaration_v_hier(self):
|
||||
"""Generates hierarchical Verilog code declaration of corresponding subcomponent output wires inside the upper component.
|
||||
|
||||
Generates wires used to connect output values from invocation of the correspoding function block into inner wires present inside the upper component from which function block has been invoked.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code of two input one bit circuit's output wires declaration.
|
||||
"""
|
||||
return f"{self.out.get_wire_declaration_v()}"
|
||||
|
||||
def get_invocation_v(self, **kwargs):
|
||||
"""Generates hierarchical Verilog code invocation of corresponding two input one bit circuit's generated function block.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code subcomponent's module invocation.
|
||||
"""
|
||||
circuit_class = self.__class__()
|
||||
return f" {circuit_class.prefix} {circuit_class.prefix}_{self.out.get_wire().name}({self.a.name}, {self.b.name}{''.join([f', {o.name}' for o in self.out.bus])});\n"
|
||||
|
||||
# Self circuit hierarchical generation
|
||||
def get_declaration_v_hier(self):
|
||||
"""Generates hierarchical Verilog code declaration of input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code containing unique declaration of circuit wires.
|
||||
"""
|
||||
self.get_circuit_wires()
|
||||
# Unique declaration of all circuit's interconnections
|
||||
return "".join([c[0].get_declaration_v() for c in self.circuit_wires if c[0] not in self.out.bus])
|
||||
|
||||
def get_init_v_hier(self):
|
||||
"""Generates hierarchical Verilog code initialization and assignment of corresponding two input one bit circuit's input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code initialization of two input one bit circuit wires.
|
||||
"""
|
||||
return "".join([i.get_assign_v(name=i.name.replace(self.prefix+"_", "")) for i in self.inputs])
|
||||
|
||||
def get_function_out_v_hier(self):
|
||||
"""Generates hierarchical Verilog code invocation of corresponding two input one bit circuit's inner subcomponents to map their output values into circuit's output wires.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Verilog code of inner subcomponents invocations and their inner assignment of output wires values.
|
||||
"""
|
||||
return "".join([f"{c.get_gate_invocation_v(remove_prefix=False)}" for c in self.components])
|
||||
|
||||
""" BLIF CODE GENERATION """
|
||||
# FLAT BLIF #
|
||||
def get_declaration_blif(self):
|
||||
"""Generates flat Blif code declaration of two input one bit circuit's input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Flattened Blif code containing declaration of circuit's interface wires.
|
||||
"""
|
||||
return f".inputs {self.a.name} {self.b.name}\n" + \
|
||||
f".outputs{self.out.get_wire_declaration_blif(array=False)}\n"
|
||||
|
||||
def get_wire_mapping_blif(self):
|
||||
"""Generates flat Blif code used to map the input wires into other inner wires to obtain proper wire names used for interconnections inside the circuit.
|
||||
|
||||
Returns:
|
||||
str: Flattened Blif code containing unique mapping of all circuit's input interconnections.
|
||||
"""
|
||||
# For unique mapping of all circuit's input interconnections
|
||||
self.get_circuit_wires()
|
||||
return "".join([i.get_assign_blif(name=i.name.replace(self.prefix+"_", "")) for i in self.inputs])
|
||||
|
||||
def get_function_blif_flat(self):
|
||||
"""Generates flat Blif code with unique input wire mapping and invocation of subcomponents Boolean functions via their corresponding truth tables.
|
||||
|
||||
Returns:
|
||||
str: Flattened Blif code containing input wires mapping and inner subcomponents Boolean functions invocation.
|
||||
"""
|
||||
return f"{self.get_wire_mapping_blif()}"+"".join([c.get_function_blif_flat() for c in self.components])
|
||||
|
||||
def get_function_out_blif(self):
|
||||
return f""
|
||||
# Generating flat BLIF code representation of circuit
|
||||
def get_blif_code_flat(self, file_object):
|
||||
"""Generates flat Blif code representation of corresponding two input one bit 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(f".end\n")
|
||||
file_object.close()
|
||||
|
||||
# HIERARCHICAL BLIF #
|
||||
# Subcomponent generation
|
||||
def get_function_block_blif(self):
|
||||
"""Generates hierarchical Blif code representation of corresponding two input one bit circuit used as function block in hierarchical circuit description.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Blif code of two input one bit circuit's function block description.
|
||||
"""
|
||||
adder_block = self.__class__()
|
||||
return f"{adder_block.get_circuit_blif()}"
|
||||
|
||||
def get_invocation_blif_hier(self, **kwargs):
|
||||
"""Generates hierarchical Blif code invocation of corresponding two input one bit circuit's generated function block.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Blif code subcomponent's model invocation.
|
||||
"""
|
||||
circuit_class = self.__class__()
|
||||
return f"{self.get_wire_mapping_blif()}" + \
|
||||
f".subckt {circuit_class.prefix} a={self.inputs[0].name} b={self.inputs[1].name}{''.join([f' {o.name}={self.out.get_wire(circuit_class.out.bus.index(o)).name}' for o in circuit_class.out.bus])}\n"
|
||||
|
||||
# Self circuit hierarchical generation
|
||||
def get_function_blif_hier(self):
|
||||
"""Generates hierarchical Blif code with unique input wire mapping and invocation of subcomponents function blocks.
|
||||
|
||||
Returns:
|
||||
str: Hierarchical Blif code containing input wires mapping and inner subcomponents function blocks invocation.
|
||||
"""
|
||||
return f"{self.get_wire_mapping_blif()}"+"".join(c.get_invocation_blif_hier(init=False) for c in self.components)
|
||||
|
||||
""" CGP CODE GENERATION """
|
||||
# FLAT CGP #
|
||||
def get_parameters_cgp(self):
|
||||
"""Generates CGP chromosome parameters of corresponding two input one bit 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 circuit.
|
||||
"""
|
||||
self.circuit_gates = self.get_circuit_gates()
|
||||
return f"{{2,2,1,{len(self.circuit_gates)},2,1,0}}"
|
||||
|
@ -40,9 +40,9 @@ class UnsignedCarryLookaheadAdder(ArithmeticCircuit):
|
||||
│ PG │ │ PG │ │ PG │ │ PG │
|
||||
│ block│ │ block│ │ block│ │ block│
|
||||
│ │ │ │ │ │ │ │
|
||||
└─┬──┬─┘ └─┬──┬─┘ └─┬──┬─┘ └─┬──┬─┘
|
||||
│ │ G3P3 │ │ G2P2 │ │ G1P1 │ │ G0P0
|
||||
┌─▼──▼───────▼──▼───────▼──▼───────▼──▼─┐
|
||||
└─┬┬┬──┘ └─┬┬┬──┘ └─┬┬┬──┘ └─┬┬┬──┘
|
||||
│││G3P3S3 │││G2P2S2 │││G1P1S1 │││G0P0S0
|
||||
┌─▼▼▼────────▼▼▼────────▼▼▼────────▼▼▼──┐
|
||||
│ Carry Lookahead logic │
|
||||
│ │
|
||||
└┬────┬───────┬──────────┬──────────┬───┘
|
||||
@ -162,9 +162,9 @@ class SignedCarryLookaheadAdder(UnsignedCarryLookaheadAdder, ArithmeticCircuit):
|
||||
│ PG │ │ PG │ │ PG │ │ PG │
|
||||
│ block│ │ block│ │ block│ │ block│
|
||||
│ │ │ │ │ │ │ │
|
||||
└─┬──┬─┘ └─┬──┬─┘ └─┬──┬─┘ └─┬──┬─┘
|
||||
│ │ G3P3 │ │ G2P2 │ │ G1P1 │ │ G0P0
|
||||
┌─▼──▼───────▼──▼───────▼──▼───────▼──▼─┐
|
||||
└─┬┬┬──┘ └─┬┬┬──┘ └─┬┬┬──┘ └─┬┬┬──┘
|
||||
│││G3P3S3 │││G2P2S2 │││G1P1S1 │││G0P0S0
|
||||
┌─▼▼▼────────▼▼▼────────▼▼▼────────▼▼▼──┐
|
||||
│ Carry Lookahead logic │
|
||||
│ with sign extension │
|
||||
└┬────┬───────┬──────────┬──────────┬───┘
|
||||
|
@ -33,23 +33,23 @@ class UnsignedPGRippleCarryAdder(ArithmeticCircuit):
|
||||
of N-bit unsigned adder which is composed of N one bit full adders with P/G logic.
|
||||
|
||||
```
|
||||
B3 A3 B2 A2 B1 A1 B0 A0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
||||
│ PG │ │ PG │ │ PG │ │ PG │
|
||||
│ FA │ │ FA │ │ FA │ │ FA │
|
||||
│ │ │ │ │ │ │ │
|
||||
└─┬──┬┬┘ └─┬┬┬──┘ └─┬┬┬──┘ └─┬┬┬──┘
|
||||
│ ││G3P3S3 │││G2P2S2 │││G1P1S1 │││ G0P0S0
|
||||
│ ┌▼▼───────▼▼▼─────────▼▼▼─────────▼▼▼──┐
|
||||
│ │ Group PG logic │
|
||||
│ │ │
|
||||
│ └─┬───────┬──────────┬──────────┬──────┘
|
||||
B3 A3 B2 A2 B1 A1 B0 A0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
||||
│ PG │ C3 │ PG │ C2 │ PG │ C1 │ PG │
|
||||
│ FA │◄────┐│ FA │◄──┐│ FA │◄──┐│ FA │◄──0
|
||||
│ │ ││ │ ││ │ ││ │
|
||||
└─┬──┬┬┘ │└─┬┬┬──┘ │└─┬┬┬──┘ │└─┬┬┬──┘
|
||||
│ ││G3P3S3│ │││G2P2S2│ │││G1P1S1│ │││G0P0S0
|
||||
│ ┌▼▼──────┴──▼▼▼──────┴──▼▼▼──────┴──▼▼▼──┐
|
||||
│ │ Group PG logic │
|
||||
│ │ │
|
||||
│ └─┬───────┬──────────┬──────────┬────────┘
|
||||
│ │ │ │ │
|
||||
┌─▼───▼───────▼──────────▼──────────▼──────┐
|
||||
│ Sum logic │
|
||||
│ │
|
||||
└┬────┬───────┬──────────┬──────────┬──────┘
|
||||
┌─▼───▼───────▼──────────▼──────────▼────────┐
|
||||
│ Sum logic │
|
||||
│ │
|
||||
└┬────┬───────┬──────────┬──────────┬────────┘
|
||||
│ │ │ │ │
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
Cout S3 S1 S0 S0
|
||||
@ -107,23 +107,23 @@ class SignedPGRippleCarryAdder(UnsignedPGRippleCarryAdder, ArithmeticCircuit):
|
||||
At last XOR gates are used to ensure proper sign extension.
|
||||
|
||||
```
|
||||
B3 A3 B2 A2 B1 A1 B0 A0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
||||
│ PG │ │ PG │ │ PG │ │ PG │
|
||||
│ FA │ │ FA │ │ FA │ │ FA │
|
||||
│ │ │ │ │ │ │ │
|
||||
└─┬──┬┬┘ └─┬┬┬──┘ └─┬┬┬──┘ └─┬┬┬──┘
|
||||
│ ││G3P3S3 │││G2P2S2 │││G1P1S1 │││ G0P0S0
|
||||
│ ┌▼▼───────▼▼▼─────────▼▼▼─────────▼▼▼──┐
|
||||
│ │ Group PG logic │
|
||||
│ │ │
|
||||
│ └─┬───────┬──────────┬──────────┬──────┘
|
||||
B3 A3 B2 A2 B1 A1 B0 A0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
||||
│ PG │ C3 │ PG │ C2 │ PG │ C1 │ PG │
|
||||
│ FA │◄────┐│ FA │◄──┐│ FA │◄──┐│ FA │◄──0
|
||||
│ │ ││ │ ││ │ ││ │
|
||||
└─┬──┬┬┘ │└─┬┬┬──┘ │└─┬┬┬──┘ │└─┬┬┬──┘
|
||||
│ ││G3P3S3│ │││G2P2S2│ │││G1P1S1│ │││G0P0S0
|
||||
│ ┌▼▼──────┴──▼▼▼──────┴──▼▼▼──────┴──▼▼▼──┐
|
||||
│ │ Group PG logic │
|
||||
│ │ │
|
||||
│ └─┬───────┬──────────┬──────────┬────────┘
|
||||
│ │ │ │ │
|
||||
┌─▼───▼───────▼──────────▼──────────▼──────┐
|
||||
│ Sum logic │
|
||||
│ with sign extension │
|
||||
└┬────┬───────┬──────────┬──────────┬──────┘
|
||||
┌─▼───▼───────▼──────────▼──────────▼────────┐
|
||||
│ Sum logic │
|
||||
│ with sign extension │
|
||||
└┬────┬───────┬──────────┬──────────┬────────┘
|
||||
│ │ │ │ │
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
Cout S3 S1 S0 S0
|
||||
|
@ -25,28 +25,55 @@ class LogicGate():
|
||||
self.b = Wire(name=prefix+"_"+b.name.replace(prefix+"_", ""), value=b.value)
|
||||
self.prefix = prefix
|
||||
|
||||
def get_component_types(self):
|
||||
return list([self])
|
||||
|
||||
""" 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 two input logic gate's interface in C code.
|
||||
|
||||
Returns:
|
||||
str: Function's name and parameters in C code.
|
||||
"""
|
||||
return f"uint8_t {self.gate_type}(uint8_t {self.a.name}, uint8_t {self.b.name})" + "{" + "\n"
|
||||
|
||||
def get_function_c(self):
|
||||
"""Generates C code representing corresponding two input logic gate's Boolean function using bitwise operators between its bitwise shifted inputs.
|
||||
|
||||
Returns:
|
||||
str: C code description of logic gate's Boolean function (with bitwise shifted inputs).
|
||||
"""
|
||||
return f"{self.a.get_wire_value_c()} {self.operator} {self.b.get_wire_value_c()}"
|
||||
|
||||
def get_declaration_c_flat(self):
|
||||
"""Generates C code declaration of input/output wires.
|
||||
|
||||
Returns:
|
||||
str: C code logic gate's wires declaration.
|
||||
"""
|
||||
return f"{self.a.get_declaration_c()}{self.b.get_declaration_c()}{self.out.get_declaration_c()}"
|
||||
|
||||
def get_init_c_flat(self):
|
||||
"""Generates C code representing corresponding two input logic gate's Boolean function using bitwise operators between its inputs.
|
||||
|
||||
Returns:
|
||||
str: C code description of logic gate's Boolean function.
|
||||
"""
|
||||
return f"{self.a.name} {self.operator} {self.b.name}"
|
||||
|
||||
def get_assign_c_flat(self):
|
||||
"""Generates C code for assigning initial values into logic gate's wires.
|
||||
|
||||
Returns:
|
||||
str: C code initialization of wires values.
|
||||
"""
|
||||
return f"{self.a.get_assign_c(name=self.a.name.replace(self.prefix+'_', ''))}" + \
|
||||
f"{self.b.get_assign_c(name=self.b.name.replace(self.prefix+'_', ''))}" + \
|
||||
f" {self.out.prefix} = {self.get_init_c_flat()};\n"
|
||||
@ -54,6 +81,11 @@ class LogicGate():
|
||||
# Generating flat C code representation of the logic gate itself
|
||||
# (i.e. not as a component of bigger circuit)
|
||||
def get_c_code(self, file_object):
|
||||
"""Generates flat C code representation of corresponding logic gate itself.
|
||||
|
||||
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(" return "+(self.get_function_c())+";\n}")
|
||||
@ -61,30 +93,60 @@ class LogicGate():
|
||||
|
||||
# HIERARCHICAL C #
|
||||
def get_function_block_c(self):
|
||||
"""Generates C code representation of corresponding logic gate used as function block in hierarchical circuit description.
|
||||
|
||||
Returns:
|
||||
str: C code logic gate's function block description.
|
||||
"""
|
||||
gate_block = NotGate(a=Wire(name="a")) if isinstance(self, NotGate) else type(self)(a=Wire(name="a"), b=Wire(name="b"))
|
||||
return f"{gate_block.get_prototype_c()}" + \
|
||||
f" return "+(gate_block.get_function_c())+";\n}\n\n"
|
||||
|
||||
def get_gate_invocation_c(self, remove_prefix: bool = True):
|
||||
"""Generates C code invocation of corresponding logic gate's generated function block.
|
||||
|
||||
Args:
|
||||
remove_prefix (bool, optional): Specifies whether function block's input parameter names should contain also its prefix (parent circuit name) or not. Defaults to True.
|
||||
|
||||
Returns:
|
||||
str: C code logic gate's function block invocation.
|
||||
"""
|
||||
a_name = self.a.name.replace(self.prefix+"_", "") if remove_prefix is True else self.a.name
|
||||
b_name = self.b.name.replace(self.prefix+"_", "") if remove_prefix is True else self.b.name
|
||||
return f"{self.gate_type}({a_name}, {b_name});\n"
|
||||
|
||||
def get_gate_output_c(self, a: Wire, b: Wire, offset: int = 0):
|
||||
return f"({self.gate_type}({a.name}, {b.name}) & 0x01) << {offset}"
|
||||
|
||||
""" VERILOG CODE GENERATION """
|
||||
# FLAT VERILOG #
|
||||
def get_prototype_v(self):
|
||||
"""Generates Verilog module header to describe corresponding two input logic gate's interface in Verilog.
|
||||
|
||||
Returns:
|
||||
str: Module's name and parameters in Verilog.
|
||||
"""
|
||||
return f"module {self.gate_type}(input {self.a.name}, input {self.b.name}, output {self.out.name});\n"
|
||||
|
||||
def get_declaration_v_flat(self):
|
||||
"""Generates Verilog code declaration of input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Verilog code logic gate's wires declaration.
|
||||
"""
|
||||
return f"{self.a.get_declaration_v()}{self.b.get_declaration_v()}{self.out.get_declaration_v()}"
|
||||
|
||||
def get_init_v_flat(self):
|
||||
"""Generates Verilog code representing corresponding two input logic gate's Boolean function using bitwise operators between its inputs.
|
||||
|
||||
Returns:
|
||||
str: Verilog description of logic gate's Boolean function.
|
||||
"""
|
||||
return f"{self.a.name} {self.operator} {self.b.name}"
|
||||
|
||||
def get_assign_v_flat(self):
|
||||
"""Generates Verilog code for assigning initial values into logic gate's wires.
|
||||
|
||||
Returns:
|
||||
str: Verilog code initialization of wires values.
|
||||
"""
|
||||
return f"{self.a.get_assign_v(name=self.a.name.replace(self.prefix+'_', ''))}" + \
|
||||
f"{self.b.get_assign_v(name=self.b.name.replace(self.prefix+'_', ''))}" + \
|
||||
f" assign {self.out.prefix} = {self.get_init_v_flat()};\n"
|
||||
@ -92,6 +154,11 @@ class LogicGate():
|
||||
# Generating flat Verilog code representation of the logic gate itself
|
||||
# (i.e. not as a component of bigger circuit)
|
||||
def get_v_code(self, file_object):
|
||||
"""Generates flat Verilog code representation of corresponding logic gate itself.
|
||||
|
||||
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(f" assign {self.out.name} = {self.get_init_v_flat()};\n")
|
||||
file_object.write(f"endmodule")
|
||||
@ -99,12 +166,25 @@ class LogicGate():
|
||||
|
||||
# HIERARCHICAL VERILOG #
|
||||
def get_function_block_v(self):
|
||||
"""Generates Verilog code representation of corresponding logic gate used as function block in hierarchical circuit description.
|
||||
|
||||
Returns:
|
||||
str: Verilog logic gate's function block description.
|
||||
"""
|
||||
gate_block = NotGate(a=Wire(name="a")) if isinstance(self, NotGate) else type(self)(a=Wire(name="a"), b=Wire(name="b"))
|
||||
return f"{gate_block.get_prototype_v()}" + \
|
||||
f" assign {gate_block.out.name} = {gate_block.get_init_v_flat()};\n" + \
|
||||
f"endmodule\n\n"
|
||||
|
||||
def get_gate_invocation_v(self, remove_prefix: bool = True):
|
||||
"""Generates Verilog code invocation of corresponding logic gate's generated function block.
|
||||
|
||||
Args:
|
||||
remove_prefix (bool, optional): Specifies whether function block's input parameter names contain also its prefix (parent circuit name) or not. Defaults to True.
|
||||
|
||||
Returns:
|
||||
str: Verilog code logic gate's function block invocation.
|
||||
"""
|
||||
a_name = self.a.name.replace(self.prefix+"_", "") if remove_prefix is True else self.a.name
|
||||
b_name = self.b.name.replace(self.prefix+"_", "") if remove_prefix is True else self.b.name
|
||||
return f" {self.gate_type} {self.gate_type}_{self.out.name}({a_name}, {b_name}, {self.out.name});\n"
|
||||
@ -112,13 +192,28 @@ class LogicGate():
|
||||
""" BLIF CODE GENERATION """
|
||||
# FLAT BLIF #
|
||||
def get_prototype_blif(self):
|
||||
"""Generates Blif model header to describe corresponding logic gate's interface in Blif.
|
||||
|
||||
Returns:
|
||||
str: Model's name and parameters in Blif.
|
||||
"""
|
||||
return f".model {self.gate_type}\n"
|
||||
|
||||
def get_declaration_blif(self):
|
||||
"""Generates Blif code declaration of input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Blif logic gate's wires declaration.
|
||||
"""
|
||||
return f".inputs {self.a.name} {self.b.name}\n" + \
|
||||
f".outputs {self.out.name}\n"
|
||||
|
||||
def get_init_function_blif_flat(self):
|
||||
"""Generates Blif code representing corresponding two input logic gate's Boolean function between its inputs.
|
||||
|
||||
Returns:
|
||||
str: Blif description of logic gate's Boolean function.
|
||||
"""
|
||||
return f"{self.a.get_assign_blif(name=self.a.name.replace(self.prefix+'_', ''))}" + \
|
||||
f"{self.b.get_assign_blif(name=self.b.name.replace(self.prefix+'_', ''))}" + \
|
||||
f"{self.get_function_blif_flat()}"
|
||||
@ -126,6 +221,11 @@ class LogicGate():
|
||||
# Generating flat BLIF code representation of the logic gate itself
|
||||
# (i.e. not as a component of bigger circuit)
|
||||
def get_blif_code(self, file_object):
|
||||
"""Generates flat Blif code representation of corresponding logic gate itself.
|
||||
|
||||
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())
|
||||
@ -134,6 +234,11 @@ class LogicGate():
|
||||
|
||||
# HIERARCHICAL BLIF #
|
||||
def get_function_block_blif(self):
|
||||
"""Generates Blif code representation of corresponding logic gate used as subcomponent in hierarchical circuit description.
|
||||
|
||||
Returns:
|
||||
str: Blif logic gate subcomponent description.
|
||||
"""
|
||||
gate_block = NotGate(a=Wire(name="a")) if isinstance(self, NotGate) else type(self)(a=Wire(name="a"), b=Wire(name="b"))
|
||||
return f"{gate_block.get_prototype_blif()}" + \
|
||||
f"{gate_block.get_declaration_blif()}" + \
|
||||
@ -141,6 +246,14 @@ class LogicGate():
|
||||
f".end\n"
|
||||
|
||||
def get_invocation_blif_hier(self, init: bool = False):
|
||||
"""Generates Blif code invocation of corresponding logic gate's generated subcomponent.
|
||||
|
||||
Args:
|
||||
init (bool, optional): Specifies whether subcomponent's input wires initializiation is neccessary before its invocation. Defaults to False.
|
||||
|
||||
Returns:
|
||||
str: Blif logic gate subcomponent invocation.
|
||||
"""
|
||||
if init is True:
|
||||
return f"{self.a.get_assign_blif(name=self.a.name.replace(self.prefix+'_', ''))}" + \
|
||||
f"{self.b.get_assign_blif(name=self.b.name.replace(self.prefix+'_', ''))}" + \
|
||||
@ -152,16 +265,47 @@ class LogicGate():
|
||||
# FLAT CGP #
|
||||
@staticmethod
|
||||
def get_parameters_cgp():
|
||||
"""Generates CGP chromosome parameters of corresponding logic gate.
|
||||
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 logic gate.
|
||||
"""
|
||||
return "{2,1,1,1,2,1,0}"
|
||||
|
||||
def get_triplet_cgp(self, a_index: int = 0, b_index: int = 1):
|
||||
"""Generates logic gate triplet (2 input wires, 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
|
||||
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.
|
||||
|
||||
Args:
|
||||
a_index (int, optional): First input wire index position. Defaults to 0.
|
||||
b_index (int, optional): Second input wire index position. Defaults to 1.
|
||||
|
||||
Returns:
|
||||
str: Triplet describing function of corresponding two input logic gate.
|
||||
"""
|
||||
return f"({a_index},{b_index},{self.cgp_function})"
|
||||
|
||||
@staticmethod
|
||||
def get_output_cgp(out_index: int = 2):
|
||||
"""Generates list of output wires indexes of described two input logic gate from MSB to LSB.
|
||||
|
||||
Args:
|
||||
out_index (int, optional): Output wire index. Defaults to 2.
|
||||
|
||||
Returns:
|
||||
str: List of logic gate's output wire indexes.
|
||||
"""
|
||||
return f"({out_index})"
|
||||
|
||||
def get_cgp_code(self, file_object):
|
||||
"""Generates flat CGP chromosome representation of corresponding logic gate itself.
|
||||
|
||||
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_triplet_cgp())
|
||||
file_object.write(self.get_output_cgp())
|
||||
@ -192,14 +336,29 @@ class InvertedLogicGate(LogicGate):
|
||||
""" C CODE GENERATION """
|
||||
# FLAT C #
|
||||
def get_function_c(self):
|
||||
"""Generates C code representing corresponding negated two input logic gate's Boolean function using bitwise operators between its bitwise shifted inputs.
|
||||
|
||||
Returns:
|
||||
str: C code description of negated logic gate's Boolean function (with bitwise shifted inputs).
|
||||
"""
|
||||
return "~("+(super().get_function_c())+") & 0x01 << 0"
|
||||
|
||||
def get_init_c_flat(self):
|
||||
"""Generates C code representing corresponding negated two input logic gate's Boolean function using bitwise operators between its inputs.
|
||||
|
||||
Returns:
|
||||
str: C code description of negated logic gate's Boolean function.
|
||||
"""
|
||||
return "~("+(super().get_init_c_flat())+")"
|
||||
|
||||
""" VERILOG CODE GENERATION """
|
||||
# FLAT VERILOG #
|
||||
def get_init_v_flat(self):
|
||||
"""Generates Verilog code representing corresponding negated two input logic gate's Boolean function using bitwise operators between its inputs.
|
||||
|
||||
Returns:
|
||||
str: Verilog description of negated logic gate's Boolean function.
|
||||
"""
|
||||
return "~("+(super().get_init_v_flat())+")"
|
||||
|
||||
|
||||
@ -231,6 +390,11 @@ class AndGate(LogicGate):
|
||||
|
||||
""" BLIF CODE GENERATION """
|
||||
def get_function_blif_flat(self):
|
||||
"""Generates Blif code representing AND gate Boolean function using its truth table.
|
||||
|
||||
Returns:
|
||||
str: Blif description of AND gate's Boolean function.
|
||||
"""
|
||||
return f".names {self.a.name} {self.b.name} {self.out.name}\n" + \
|
||||
f"11 1\n"
|
||||
|
||||
@ -263,6 +427,11 @@ class NandGate(InvertedLogicGate):
|
||||
|
||||
""" BLIF CODE GENERATION """
|
||||
def get_function_blif_flat(self):
|
||||
"""Generates Blif code representing NAND gate Boolean function using its truth table.
|
||||
|
||||
Returns:
|
||||
str: Blif description of NAND gate's Boolean function.
|
||||
"""
|
||||
return f".names {self.a.name} {self.b.name} {self.out.name}\n" + \
|
||||
f"0- 1\n-0 1\n"
|
||||
|
||||
@ -295,6 +464,11 @@ class OrGate(LogicGate):
|
||||
|
||||
""" BLIF CODE GENERATION """
|
||||
def get_function_blif_flat(self):
|
||||
"""Generates Blif code representing OR gate Boolean function using its truth table.
|
||||
|
||||
Returns:
|
||||
str: Blif description of OR gate's Boolean function.
|
||||
"""
|
||||
return f".names {self.a.name} {self.b.name} {self.out.name}\n" + \
|
||||
f"1- 1\n-1 1\n"
|
||||
|
||||
@ -327,6 +501,11 @@ class NorGate(InvertedLogicGate):
|
||||
|
||||
""" BLIF CODE GENERATION """
|
||||
def get_function_blif_flat(self):
|
||||
"""Generates Blif code representing NOR gate Boolean function using its truth table.
|
||||
|
||||
Returns:
|
||||
str: Blif description of NOR gate's Boolean function.
|
||||
"""
|
||||
return f".names {self.a.name} {self.b.name} {self.out.name}\n" + \
|
||||
f"00 1\n"
|
||||
|
||||
@ -359,6 +538,11 @@ class XorGate(LogicGate):
|
||||
|
||||
""" BLIF CODE GENERATION """
|
||||
def get_function_blif_flat(self):
|
||||
"""Generates Blif code representing XOR gate Boolean function using its truth table.
|
||||
|
||||
Returns:
|
||||
str: Blif description of XOR gate's Boolean function.
|
||||
"""
|
||||
return f".names {self.a.name} {self.b.name} {self.out.name}\n" + \
|
||||
f"01 1\n10 1\n"
|
||||
|
||||
@ -391,6 +575,11 @@ class XnorGate(InvertedLogicGate):
|
||||
|
||||
""" BLIF CODE GENERATION """
|
||||
def get_function_blif_flat(self):
|
||||
"""Generates Blif code representing XNOR gate Boolean function using its truth table.
|
||||
|
||||
Returns:
|
||||
str: Blif description of XNOR gate's Boolean function.
|
||||
"""
|
||||
return f".names {self.a.name} {self.b.name} {self.out.name}\n" + \
|
||||
f"00 1\n11 1\n"
|
||||
|
||||
@ -425,65 +614,146 @@ class NotGate(InvertedLogicGate):
|
||||
""" C CODE GENERATION """
|
||||
# FLAT C #
|
||||
def get_prototype_c(self):
|
||||
"""Generates C code function header to describe corresponding one input logic gate's interface in C code.
|
||||
|
||||
Returns:
|
||||
str: Function's name and parameter in C code.
|
||||
"""
|
||||
return f"uint8_t {self.gate_type}(uint8_t {self.a.name})" + "{" + "\n"
|
||||
|
||||
def get_function_c(self):
|
||||
"""Generates C code representing corresponding one input logic gate's Boolean function using bitwise operators between its bitwise shifted input.
|
||||
|
||||
Returns:
|
||||
str: C code description of logic gate's Boolean function (with bitwise shifted input).
|
||||
"""
|
||||
return f"{self.operator}{self.a.get_wire_value_c()} & 0x01 << 0"
|
||||
|
||||
def get_declaration_c_flat(self):
|
||||
"""Generates C code declaration of input/output wires.
|
||||
|
||||
Returns:
|
||||
str: C code logic gate's wires declaration.
|
||||
"""
|
||||
return f"{self.a.get_declaration_c()}{self.out.get_declaration_c()}"
|
||||
|
||||
def get_init_c_flat(self):
|
||||
"""Generates C code representing corresponding one input logic gate's Boolean function using bitwise operators between its input.
|
||||
|
||||
Returns:
|
||||
str: C code description of logic gate's Boolean function.
|
||||
"""
|
||||
return f"{self.operator}{self.a.name}"
|
||||
|
||||
def get_assign_c_flat(self):
|
||||
"""Generates C code for assigning initial values into logic gate's wires.
|
||||
|
||||
Returns:
|
||||
str: C code initialization of wires values.
|
||||
"""
|
||||
return f"{self.a.get_assign_c(name=self.a.name.replace(self.prefix+'_', ''))}" + \
|
||||
f" {self.out.prefix} = {self.get_init_c_flat()};\n"
|
||||
|
||||
# HIERARCHICAL C #
|
||||
def get_gate_invocation_c(self, remove_prefix: bool = True):
|
||||
"""Generates C code invocation of corresponding logic gate's generated function block.
|
||||
|
||||
Args:
|
||||
remove_prefix (bool, optional): Specifies whether function block's input parameter name should contain also its prefix (parent circuit name) or not. Defaults to True.
|
||||
|
||||
Returns:
|
||||
str: C code logic gate's function block invocation.
|
||||
"""
|
||||
a_name = self.a.name.replace(self.prefix+"_", "") if remove_prefix is True else self.a.name
|
||||
return f"{self.gate_type}({a_name});"
|
||||
|
||||
def get_gate_output_c(self, a: Wire, offset: int = 0):
|
||||
return f"({self.gate_type}({a.name}) & 0x01) << {offset}"
|
||||
|
||||
""" VERILOG CODE GENERATION """
|
||||
# FLAT VERILOG #
|
||||
def get_prototype_v(self):
|
||||
"""Generates Verilog module header to describe corresponding one input logic gate's interface in Verilog.
|
||||
|
||||
Returns:
|
||||
str: Module's name and parameter in Verilog.
|
||||
"""
|
||||
return f"module {self.gate_type}(input {self.a.name}, output {self.out.name});\n"
|
||||
|
||||
def get_declaration_v_flat(self):
|
||||
"""Generates Verilog code declaration of input/output wires.
|
||||
|
||||
Returns:
|
||||
str: Verilog code logic gate's wires declaration.
|
||||
"""
|
||||
return f"{self.a.get_declaration_v()}{self.out.get_declaration_v()}"
|
||||
|
||||
def get_init_v_flat(self):
|
||||
"""Generates Verilog code representing corresponding one input logic gate's Boolean function using bitwise operators between its input.
|
||||
|
||||
Returns:
|
||||
str: Verilog description of logic gate's Boolean function.
|
||||
"""
|
||||
return f"{self.operator}{self.a.name}"
|
||||
|
||||
def get_assign_v_flat(self):
|
||||
"""Generates Verilog code for assigning initial values into logic gate's wires.
|
||||
|
||||
Returns:
|
||||
str: Verilog code initialization of wires values.
|
||||
"""
|
||||
return f"{self.a.get_assign_v(name=self.a.name.replace(self.prefix+'_', ''))}" + \
|
||||
f" assign {self.out.prefix} = {self.get_init_v_flat()};\n"
|
||||
|
||||
# HIERARCHICAL VERILOG #
|
||||
def get_gate_invocation_v(self, remove_prefix: bool = True):
|
||||
"""Generates Verilog code invocation of corresponding logic gate's generated function block.
|
||||
|
||||
Args:
|
||||
remove_prefix (bool, optional): Specifies whether function block's input parameter name should contain also its prefix (parent circuit name) or not. Defaults to True.
|
||||
|
||||
Returns:
|
||||
str: Verilog code logic gate's function block invocation.
|
||||
"""
|
||||
a_name = self.a.name.replace(self.prefix+"_", "") if remove_prefix is True else self.a.name
|
||||
return f" {self.gate_type} {self.gate_type}_{self.out.name}({a_name}, {self.out.name});\n"
|
||||
|
||||
""" BLIF CODE GENERATION """
|
||||
# FLAT BLIF #
|
||||
def get_declaration_blif(self):
|
||||
"""Generates Blif model header to describe corresponding logic gate's interface in Blif.
|
||||
|
||||
Returns:
|
||||
str: Model's name and parameter in Blif.
|
||||
"""
|
||||
return f".inputs {self.a.name}\n" + \
|
||||
f".outputs {self.out.name}\n"
|
||||
|
||||
def get_function_blif_flat(self):
|
||||
"""Generates Blif code representing NOT gate Boolean function using its truth table.
|
||||
|
||||
Returns:
|
||||
str: Blif description of NOT gate's Boolean function.
|
||||
"""
|
||||
return f".names {self.a.name} {self.out.name}\n" + \
|
||||
f"0 1\n"
|
||||
|
||||
def get_init_function_blif_flat(self):
|
||||
"""Generates Blif code representing corresponding one input logic gate's Boolean function between its input.
|
||||
|
||||
Returns:
|
||||
str: Blif description of logic gate's Boolean function.
|
||||
"""
|
||||
return f"{self.a.get_assign_blif(name=self.a.name.replace(self.prefix+'_', ''))}" + \
|
||||
f"{self.get_function_blif_flat()}"
|
||||
|
||||
# HIERARCHICAL BLIF #
|
||||
def get_invocation_blif_hier(self, init: bool = False):
|
||||
"""Generates Blif code invocation of corresponding logic gate's generated subcomponent.
|
||||
|
||||
Args:
|
||||
init (bool, optional): Specifies whether subcomponent's input wire initializiation is neccessary before its invocation. Defaults to False.
|
||||
|
||||
Returns:
|
||||
str: Blif logic gate subcomponent invocation.
|
||||
"""
|
||||
if init is True:
|
||||
return f"{self.a.get_assign_blif(name=self.a.name.replace(self.prefix+'_', ''))}" + \
|
||||
f".subckt {self.gate_type} _a={self.a.name} _y0={self.out.name}\n"
|
||||
@ -493,8 +763,27 @@ class NotGate(InvertedLogicGate):
|
||||
""" CGP CODE GENERATION """
|
||||
# FLAT CGP #
|
||||
def get_triplet_cgp(self, a_index: int = 0):
|
||||
"""Generates logic gate triplet (2 input wires, 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.
|
||||
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.
|
||||
|
||||
Args:
|
||||
a_index (int, optional): First (used also as the second) input wire index position. Defaults to 0.
|
||||
|
||||
Returns:
|
||||
str: Triplet describing function of corresponding one input logic gate.
|
||||
"""
|
||||
return f"({a_index},{a_index},{self.cgp_function})"
|
||||
|
||||
@staticmethod
|
||||
def get_output_cgp(out_index: int = 1):
|
||||
"""Generates list of output wires indexes of described one input logic gate from MSB to LSB.
|
||||
|
||||
Args:
|
||||
out_index (int, optional): Output wire index. Defaults to 1.
|
||||
|
||||
Returns:
|
||||
str: List of logic gate's output wire indexes.
|
||||
"""
|
||||
return f"({out_index})"
|
||||
|
@ -99,10 +99,25 @@ class FullAdderPG(ThreeInputOneBitCircuit):
|
||||
self.out.connect(2, sum_xor.out)
|
||||
|
||||
def get_propagate_wire(self):
|
||||
"""Get output wire carrying propagate signal value.
|
||||
|
||||
Returns:
|
||||
Wire: Return propagate wire.
|
||||
"""
|
||||
return self.out.get_wire(0)
|
||||
|
||||
def get_generate_wire(self):
|
||||
"""Get output wire carrying generate signal value.
|
||||
|
||||
Returns:
|
||||
Wire: Return generate wire.
|
||||
"""
|
||||
return self.out.get_wire(1)
|
||||
|
||||
def get_sum_wire(self):
|
||||
"""Get output wire carrying sum value.
|
||||
|
||||
Returns:
|
||||
Wire: Return sum wire.
|
||||
"""
|
||||
return self.out.get_wire(2)
|
||||
|
@ -49,8 +49,8 @@ class PGLogicBlock(TwoInputOneBitCircuit):
|
||||
```
|
||||
┌──────┐
|
||||
──►│ ├─► P
|
||||
│ │
|
||||
──►│ ├─► G
|
||||
│ ├─► G
|
||||
──►│ ├─► S
|
||||
└──────┘
|
||||
```
|
||||
|
||||
@ -83,12 +83,27 @@ class PGLogicBlock(TwoInputOneBitCircuit):
|
||||
self.out.connect(2, sum_xor.out)
|
||||
|
||||
def get_propagate_wire(self):
|
||||
"""Get output wire carrying propagate signal value.
|
||||
|
||||
Returns:
|
||||
Wire: Return propagate wire.
|
||||
"""
|
||||
return self.out.get_wire(0)
|
||||
|
||||
def get_generate_wire(self):
|
||||
"""Get output wire carrying generate signal value.
|
||||
|
||||
Returns:
|
||||
Wire: Return generate wire.
|
||||
"""
|
||||
return self.out.get_wire(1)
|
||||
|
||||
def get_sum_wire(self):
|
||||
"""Get output wire carrying sum value.
|
||||
|
||||
Returns:
|
||||
Wire: Return sum wire.
|
||||
"""
|
||||
return self.out.get_wire(2)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user