Merge pull request #7 from ehw-fit/devel

Signed version
This commit is contained in:
Vojta Mrazek 2021-10-11 08:02:52 +02:00 committed by GitHub
commit 49cf3150ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 126 additions and 128 deletions

View File

@ -51,9 +51,9 @@ For more detailed description of script's usage, use help.
## CGP testing
The `chr2c.py` script converts the input CGP chromosome generated by ArithsGen to the corresponding C code and prints it to standard output.
It is a modified version of a script originally authored by Vojtech Mrazek. Note that it required Python2 to run!
It is a modified version of a script originally authored by Vojtech Mrazek.
### Usage
```bash
python2 chr2c.py input.chr > output.c
python3 chr2c.py input.chr > output.c
```

View File

@ -11,15 +11,14 @@ from ariths_gen.core.arithmetic_circuits.general_circuit import GeneralCircuit
class ArithmeticCircuit(GeneralCircuit):
"""Class represents a general arithmetic circuit and ensures their generation to various representations.
"""Class represents a general arithmetic circuit and ensures its generation to various representations.
The __init__ method fills some mandatory attributes concerning arithmetic circuit
that are later used for generation into various representations.
"""
def __init__(self, a, b, prefix: str, name: str, out_N: int, inner_component: bool = False, one_bit_circuit: bool = False):
super().__init__(prefix, name, out_N, inner_component, inputs=[a, b])
def __init__(self, a, b, prefix: str, name: str, out_N: int, inner_component: bool = False, one_bit_circuit: bool = False, signed: bool = False):
super().__init__(prefix, name, out_N, inner_component, inputs=[a, b], signed=signed)
if one_bit_circuit is False:
if prefix == "":
self.prefix = name
@ -40,7 +39,7 @@ class ArithmeticCircuit(GeneralCircuit):
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.out = Bus(self.prefix+"_out", out_N, out_bus=True, signed=self.signed)
""" C CODE GENERATION """
def get_prototype_c(self):
@ -51,22 +50,7 @@ class ArithmeticCircuit(GeneralCircuit):
"""
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_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"), name=circuit_prefix)
return f"{circuit_block.get_circuit_c()}\n\n"
""" 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.
@ -74,50 +58,21 @@ class ArithmeticCircuit(GeneralCircuit):
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"
# HIERARCHICAL VERILOG #
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.
""" BLIF CODE GENERATION """
def get_declaration_blif(self):
"""Generates flat Blif code declaration of input/output circuit wires.
Returns:
str: Hierarchical Verilog code of multi-bit arithmetic circuit's function block description.
str: Flat Blif code containing declaration of circuit's wires.
"""
# 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"), name=circuit_prefix)
return f"{circuit_block.get_circuit_v()}\n\n"
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"), 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"
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_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(
N=self.N, prefix="b"))
return f"{circuit_block.get_circuit_blif()}"
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"

View File

@ -10,13 +10,13 @@ from ariths_gen.wire_components import (
from io import StringIO
class GeneralCircuit():
"""Class represents a general arithmetic circuit and ensures their generation to various representations.
"""Class represents a general circuit and ensures its generation to various representations.
The __init__ method fills some mandatory attributes concerning arithmetic circuit
that are later used for generation into various representations.
"""
def __init__(self, prefix: str, name: str, out_N: int, inner_component: bool = False, inputs: list=[]):
def __init__(self, prefix: str, name: str, out_N: int, inner_component: bool = False, inputs: list=[], signed: bool = False):
if prefix == "":
self.prefix = name
else:
@ -29,6 +29,7 @@ class GeneralCircuit():
self.circuit_wires = []
self.circuit_gates = []
self.c_data_type = "uint64_t"
self.signed = signed
self.pyc = None # Python compiled function
def __call__(self, *args):
@ -242,30 +243,30 @@ class GeneralCircuit():
""" PYTHON CODE GENERATION """
# FLAT PYTHON #
def get_prototype_python(self):
"""Generates python code function header to describe corresponding arithmetic circuit's interface in python code.
"""Generates Python code function header to describe corresponding arithmetic circuit's interface in Python code.
Returns:
str: Function's name and parameters in C code.
str: Function's name and parameters in Python code.
"""
return f"def {self.prefix}(" + ", ".join([f"{x.prefix}" for x in self.inputs]) + ")" + ":" + "\n"
def get_init_python_flat(self):
"""Generates flat C code initialization and assignment of corresponding arithmetic circuit's input/output wires.
"""Generates flat Python code initialization and assignment of corresponding arithmetic circuit's input/output wires.
Returns:
str: Flat C code initialization of arithmetic circuit wires.
str: Flat Python code initialization of arithmetic circuit wires.
"""
return "".join([c.get_assign_python_flat() if isinstance(c, TwoInputLogicGate) else c.get_init_python_flat() for c in self.components])
def get_function_out_python_flat(self):
"""Generates flat C code assignment of corresponding arithmetic circuit's output bus wires.
"""Generates flat Python code assignment of corresponding arithmetic circuit's output bus wires.
Returns:
str: Flat C code containing output bus wires assignment.
str: Flat Python code containing output bus wires assignment.
"""
return self.out.return_bus_wires_values_python_flat()
# Generating flat C code representation of circuit
# Generating flat Python code representation of circuit
def get_python_code_flat(self, file_object):
"""Generates flat Python code representation of corresponding arithmetic circuit.
@ -277,6 +278,7 @@ class GeneralCircuit():
#file_object.write(self.get_declaration_python_flat()+"\n")
file_object.write(self.get_init_python_flat()+"\n")
file_object.write(self.get_function_out_python_flat())
file_object.write(self.out.return_bus_wires_sign_extend_python())
file_object.write(f" return {self.out.prefix}"+"\n")
""" C CODE GENERATION """
@ -335,6 +337,7 @@ class GeneralCircuit():
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(self.out.return_bus_wires_sign_extend_c())
file_object.write(f" return {self.out.prefix}"+";\n}")
# HIERARCHICAL C #
@ -358,7 +361,7 @@ class GeneralCircuit():
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)
N=self.N, prefix="b"), name=circuit_prefix)
return f"{circuit_block.get_circuit_c()}\n\n"
def get_declarations_c_hier(self):
@ -427,6 +430,7 @@ class GeneralCircuit():
f"{self.get_declarations_c_hier()}\n" + \
f"{self.get_init_c_hier()}\n" + \
f"{self.get_function_out_c_hier()}" + \
f"{self.out.return_bus_wires_sign_extend_c()}" + \
f" return {self.out.prefix}"+";\n}"
# Generating hierarchical C code representation of circuit
@ -509,7 +513,7 @@ class GeneralCircuit():
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)
N=self.N, prefix="b"), name=circuit_prefix)
return f"{circuit_block.get_circuit_v()}\n\n"
def get_declarations_v_hier(self):
@ -561,7 +565,7 @@ class GeneralCircuit():
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)
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"
@ -612,16 +616,10 @@ class GeneralCircuit():
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"
return f".inputs{''.join([w.get_wire_declaration_blif() for w in self.inputs])}\n" + \
f".outputs{self.out.get_wire_declaration_blif()}\n" + \
f".names vdd\n1\n" + \
f".names gnd\n0\n"
def get_function_blif_flat(self):
"""Generates flat Blif code with invocation of subcomponents logic gates functions via their corresponding truth tables.
@ -715,7 +713,7 @@ class GeneralCircuit():
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)
N=self.N, prefix="b"), name=circuit_prefix)
return f"{circuit_block.get_circuit_blif()}"
# Generating hierarchical BLIF code representation of circuit

View File

@ -195,11 +195,13 @@ class TwoInputLogicGate():
else:
return f" {self.out.name} = {self.gate_type}({self.a.get_wire_value_c_hier()}, {self.b.get_wire_value_c_hier()});\n"
""" PYTHON CODE GENERATION """
# FLAT PYTHON #
def get_assign_python_flat(self):
"""Generates C code for invocation of logical functions and subsequently provides assignment to their output.
"""Generates Python code for invocation of logical functions and subsequently provides assignment to their output.
Returns:
str: C code invocation of logical function and assignment to output.
str: Python code invocation of logical function and assignment to output.
"""
# No gate logic is generated if one of the inputs is a wire with constant value.
# I.e. either the constant or the second input wire is propagated to the output for the corresponding logic gate's logic function.

View File

@ -184,7 +184,7 @@ class SignedCarryLookaheadAdder(UnsignedCarryLookaheadAdder, ArithmeticCircuit):
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 = "", name: str = "s_cla", **kwargs):
super().__init__(a=a, b=b, cla_block_size=cla_block_size, prefix=prefix, name=name, **kwargs)
super().__init__(a=a, b=b, cla_block_size=cla_block_size, prefix=prefix, name=name, signed=True, **kwargs)
self.c_data_type = "int64_t"
# Additional XOR gates to ensure correct sign extension in case of sign addition

View File

@ -167,7 +167,7 @@ class SignedCarrySkipAdder(UnsignedCarrySkipAdder, ArithmeticCircuit):
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 = "", name: str = "s_cska", **kwargs):
super().__init__(a=a, b=b, bypass_block_size=bypass_block_size, prefix=prefix, name=name, **kwargs)
super().__init__(a=a, b=b, bypass_block_size=bypass_block_size, prefix=prefix, name=name, signed=True, **kwargs)
self.c_data_type = "int64_t"
# Additional XOR gates to ensure correct sign extension in case of sign addition

View File

@ -130,7 +130,7 @@ class SignedPGRippleCarryAdder(UnsignedPGRippleCarryAdder, ArithmeticCircuit):
name (str, optional): Name of signed P/G rca. Defaults to "s_pg_rca".
"""
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)
super().__init__(a=a, b=b, prefix=prefix, name=name, signed=True, **kwargs)
self.c_data_type = "int64_t"
# Additional XOR gates to ensure correct sign extension in case of sign addition

View File

@ -106,7 +106,7 @@ class SignedRippleCarryAdder(UnsignedRippleCarryAdder, ArithmeticCircuit):
name (str, optional): Name of signed rca. Defaults to "s_rca".
"""
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)
super().__init__(a=a, b=b, prefix=prefix, name=name, signed=True, **kwargs)
self.c_data_type = "int64_t"
# Additional XOR gates to ensure correct sign extension in case of sign addition

View File

@ -191,7 +191,7 @@ class SignedArrayMultiplier(MultiplierCircuit):
"""
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_arrmul", **kwargs):
self.N = max(a.N, b.N)
super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs)
super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, signed=True, **kwargs)
self.c_data_type = "int64_t"
# Bus sign extension in case buses have different lengths

View File

@ -155,7 +155,7 @@ class SignedDaddaMultiplier(MultiplierCircuit):
"""
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_dadda_cla", unsigned_adder_class_name: str = UnsignedCarryLookaheadAdder, **kwargs):
self.N = max(a.N, b.N)
super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs)
super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, signed=True, **kwargs)
self.c_data_type = "int64_t"
# Bus sign extension in case buses have different lengths

View File

@ -148,7 +148,7 @@ class SignedWallaceMultiplier(MultiplierCircuit):
"""
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)
super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, **kwargs)
super().__init__(a=a, b=b, prefix=prefix, name=name, out_N=self.N*2, signed=True, **kwargs)
self.c_data_type = "int64_t"
# Bus sign extension in case buses have different lengths

View File

@ -11,8 +11,9 @@ class Bus():
N (int, optional): Number of wires in the bus. Defaults to 1.
wires_list (list, optional): List of Wire objects used to clone one bus to another. Defaults to 0.
out_bus (bool, optional): Specifies whether this Bus is an output bus of some previous component. Defaults to False.
signed (bool, optional): Specifies whether this Bus should consider signed numbers or not (used for C code generation). Defaults to False.
"""
def __init__(self, prefix: str = "bus", N: int = 1, wires_list: list = None, out_bus: bool = False):
def __init__(self, prefix: str = "bus", N: int = 1, wires_list: list = None, out_bus: bool = False, signed: bool = False):
self.out_bus = out_bus
if wires_list is None:
self.prefix = prefix
@ -23,6 +24,21 @@ class Bus():
self.prefix = prefix
self.bus = wires_list
self.N = len(self.bus)
# Determine C code signedness
self.signed = signed
if self.N > 8:
self.c_var_size = 64
if signed is True:
self.c_type = "int64_t"
else:
self.c_type = "uint64_t"
else:
self.c_var_size = 8
if signed is True:
self.c_type = "int8_t"
else:
self.c_type = "uint8_t"
def is_output_bus(self):
"""Tells whether this Bus is an output bus.
@ -79,21 +95,42 @@ 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):
def connect_bus(self, connecting_bus: object, start_connection_pos: int = 0, end_connection_pos: int = -1):
"""Ensures connection of specified bus wires to this bus wires.
Used for connection of some inner circuit component's output bus (`connecting_bus`) wires
to the appropriate input bus (this `self` bus) wires of some other circuit.
Args:
connecting_bus (object): Specifies the connecting bus.
start_connection_pos (int, optional): Specifies the position from which to start interconnecting wires from the `connecting_bus` to this `self` bus. Defaults to 0.
end_connection_pos (int, optional): Specifies the position from which to end interconnecting wires from the `connecting_bus` to this `self` bus. Defaults to -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)]
""" PYTHON CODE GENERATION """
def return_bus_wires_values_python_flat(self):
"""Retrieves values from bus's wires and stores them in bus's corresponding C variable at proper offset bit position in the bus for flat generation.
"""Retrieves values from bus's wires and stores them in bus's corresponding Python variable (object) at proper offset bit position in the bus for flat generation.
Returns:
str: C code for assigning wire values into bus represented in C code variable.
str: Python code for assigning wire values into bus represented in Python code variable.
"""
return "".join([f" {self.prefix} = 0\n"] + [f" {self.prefix} |= {w.return_wire_value_python_flat(offset=self.bus.index(w))}" for w in self.bus])
def return_bus_wires_sign_extend_python(self):
"""Sign extends the bus's corresponding Python variable (object) to ensure proper Python code variable signedness.
Returns:
str: Python code for sign extending the bus variable wire values.
"""
if self.signed is True:
last_bus_wire = self.bus[-1]
return "".join([f" {self.prefix} |= {last_bus_wire.return_wire_value_python_flat(offset=i)}" for i in range(len(self.bus), 64)])
else:
return ""
""" C CODE GENERATION """
def get_declaration_c(self):
@ -102,10 +139,8 @@ class Bus():
Returns:
str: C code for declaration and initialization of bus name.
"""
if self.N > 8:
return f" uint64_t {self.prefix} = 0;\n"
else:
return f" uint8_t {self.prefix} = 0;\n"
return f" {self.c_type} {self.prefix} = 0;\n"
def return_bus_wires_values_c_flat(self):
"""Retrieves values from bus's wires and stores them in bus's corresponding C variable at proper offset bit position in the bus for flat generation.
@ -123,6 +158,18 @@ class Bus():
"""
return "".join([f" {self.prefix} |= {w.return_wire_value_c_hier(offset=self.bus.index(w))}" for w in self.bus])
def return_bus_wires_sign_extend_c(self):
"""Sign extends the bus's corresponding C variable to ensure proper C code variable signedness.
Returns:
str: C code for sign extending the bus variable wire values.
"""
if self.signed is True:
last_bus_wire = self.bus[-1]
return "".join([f" {self.prefix} |= {last_bus_wire.return_wire_value_c_flat(offset=i)}" for i in range(len(self.bus), self.c_var_size)])
else:
return ""
""" VERILOG CODE GENERATION """
def return_bus_wires_values_v_flat(self):
"""Retrieves values from bus's wires and stores them in bus's corresponding Verilog variable at proper offset bit position in the bus for flat generation.

View File

@ -26,15 +26,15 @@ class Wire():
"""
return False
""" Python CODE GENERATION """
""" PYTHON CODE GENERATION """
def return_wire_value_python_flat(self, offset: int = 0):
"""Retrieves desired bit value from wire represented in C code variable and bitwise shifts it to desired position for storing it within a bus for flat generation.
"""Retrieves desired bit value from wire represented in Python code variable (object) and bitwise shifts it to desired position for storing it within a bus for flat generation.
Args:
offset (int, optional): Used to shift wire value in order to be stored in proper location inside a bus. Defaults to 0.
Returns:
str: C code bitwise shift for storing (constant/variable) wire value at desired offset position.
str: Python code bitwise shift for storing (constant/variable) wire value at desired offset position.
"""
if self.is_const():
return f"({self.c_const}) << {offset}\n"
@ -92,7 +92,7 @@ class Wire():
if self.is_const():
return f"({self.c_const}) << {offset};\n"
else:
return f"(({self.name} >> 0) & 0x01) << {offset};\n"
return f"(({self.name} >> 0) & 0x01ull) << {offset};\n"
def return_wire_value_c_hier(self, offset: int = 0):
"""Retrieves desired bit value from wire represented in C code variable and bitwise shifts it to desired position for storing it within a bus for hierarchical generation.
@ -106,7 +106,7 @@ class Wire():
if self.is_const():
return f"({self.c_const}) << {offset};\n"
else:
return f"(({self.prefix} >> {self.index}) & 0x01) << {offset};\n"
return f"(({self.prefix} >> {self.index}) & 0x01ull) << {offset};\n"
""" VERILOG CODE GENERATION """
def get_declaration_v_flat(self):

View File

@ -86,7 +86,7 @@ def parse_chromosome(chromosome, signed=False, function=None):
output.append(f"{dtype} {function}({dtype} a, {dtype} b) {{")
output.append(" int wa[%d];" % int(c_in/2))
output.append(" int wb[%d];" % int(c_in/2))
output.append(" uint64_t y = 0;")
output.append(f" {dtype} y = 0;")
# Export converted input assignments into C code function body
trans = {}
@ -126,10 +126,16 @@ def parse_chromosome(chromosome, signed=False, function=None):
# Export converted outputs into C code function body
for i in range(0, c_out):
if outs[i] in trans:
lines_end.append(" y |= (%s & 0x01) << %d; // default output" % (trans[outs[i]], i))
lines_end.append(" y |= (%s & 0x01ull) << %d; // default output" % (trans[outs[i]], i))
else:
assert False
# Ensure proper sign extension if it is needed
if signed is True:
last_out_wire = trans[outs[-1]] # used for sign extension
for i in range(c_out, 64):
lines_end.append(" y |= (%s & 0x01ull) << %d; // default output" % (last_out_wire, i))
# Print final result return in C code function body and close it
lines_end.append(" return y;")
output += lines

View File

@ -10,11 +10,6 @@ int main() {
for (int i = -128; i < 128; i++){
for (int j = -128; j < 128; j++){
result = i + j;
// Calculating 2's complement in case of negative sum
if (result < 0) {
result = 512 + result;
}
assert(result == (int)CNAME(i,j));
}

View File

@ -10,11 +10,6 @@ int main() {
for (int i = -128; i < 128; i++){
for (int j = -128; j < 128; j++){
result = i * j;
// Calculating 2's complement in case of negative sum
if (result < 0) {
result = 65536 + result;
}
assert(result == (int)CNAME(i,j));
}

View File

@ -61,7 +61,7 @@ def test_signed_mul():
mul = c(a, b)
r = mul(av, bv)
r[r >= 2**(2*N-1)] -= 2**(2*N) # hack!!! two's complement not implemented yet
# r[r >= 2**(2*N-1)] -= 2**(2*N) # hack!!! two's complement not implemented yet
np.testing.assert_array_equal(expected, r)
@ -94,7 +94,7 @@ def test_signed_add():
for c in [SignedCarryLookaheadAdder, SignedPGRippleCarryAdder, SignedRippleCarryAdder, SignedCarrySkipAdder]:
mul = c(a, b)
r = mul(av, bv)
r[r >= 2**(N)] -= 2**(N+1) # hack!!! two's complement not implemented yet
# r[r >= 2**(N)] -= 2**(N+1) # hack!!! two's complement not implemented yet
np.testing.assert_array_equal(expected, r)