Updated exportation of signed arithmetic circuits to python representation. Also unified some methods from arithmetic_circuit.py into general_circuit.py.

This commit is contained in:
honzastor 2021-10-10 22:15:13 +02:00
parent cfb5bba3ec
commit d41c5f3c94
4 changed files with 41 additions and 78 deletions

View File

@ -50,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.
@ -73,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

@ -278,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 """
@ -336,7 +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())
file_object.write(self.out.return_bus_wires_sign_extend_c())
file_object.write(f" return {self.out.prefix}"+";\n}")
# HIERARCHICAL C #
@ -360,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):
@ -429,7 +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()}" + \
f"{self.out.return_bus_wires_sign_extend_c()}" + \
f" return {self.out.prefix}"+";\n}"
# Generating hierarchical C code representation of circuit
@ -512,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):
@ -564,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"
@ -615,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.
@ -718,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

@ -119,6 +119,18 @@ class Bus():
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):
@ -146,7 +158,7 @@ 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(self):
def return_bus_wires_sign_extend_c(self):
"""Sign extends the bus's corresponding C variable to ensure proper C code variable signedness.
Returns:

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)