Added generation of hierarchical C code for implemented circuits.
This commit is contained in:
parent
94af6fec34
commit
397d3bc658
@ -1,6 +1,7 @@
|
||||
from wire_components import wire, bus
|
||||
from logic_gates_generator import and_gate, xor_gate, or_gate
|
||||
from logic_gates_generator import not_gate, and_gate, xor_gate, or_gate, nand_gate, xnor_gate, nor_gate
|
||||
import sys
|
||||
import itertools
|
||||
|
||||
|
||||
""" ARITHMETIC CIRCUITS """
|
||||
@ -13,7 +14,6 @@ class arithmetic_circuit():
|
||||
self.c_data_type = "uint64_t"
|
||||
|
||||
# TODO delete?
|
||||
self.input_N = 0
|
||||
self.carry_out_gate = None
|
||||
self.sum_out_gates = []
|
||||
|
||||
@ -23,6 +23,16 @@ class arithmetic_circuit():
|
||||
def get_previous_component(self):
|
||||
return self.components[-1]
|
||||
|
||||
def get_component_types(self):
|
||||
return list({type(c): c for c in self.components}.values())
|
||||
|
||||
def get_unique_types(self):
|
||||
hier_components = self.all_gates + self.component_types
|
||||
return list({type(c): c for c in hier_components}.values())
|
||||
|
||||
def get_gate_types(self):
|
||||
return list({type(g): g for g in self.all_gates}.values())
|
||||
|
||||
def get_sum_wire(self):
|
||||
return self.out.get_wire(0)
|
||||
|
||||
@ -35,34 +45,76 @@ class arithmetic_circuit():
|
||||
return f"#include <stdio.h>\n#include <stdint.h>\n\n"
|
||||
|
||||
def get_prototype_c(self):
|
||||
return f"uint64_t {self.prefix}({self.c_data_type} {self.a.prefix}, {self.c_data_type} {self.b.prefix})" + "{" + '\n'
|
||||
return f"uint64_t {self.prefix}({self.c_data_type} {self.a.prefix}, {self.c_data_type} {self.b.prefix})" + "{" + "\n"
|
||||
|
||||
def get_declaration_c(self):
|
||||
return f"".join([c.get_declaration_c() for c in self.components])
|
||||
def get_declaration_c_flat(self):
|
||||
return f"".join([c.get_declaration_c_flat() for c in self.components])
|
||||
|
||||
def get_initialization_c(self):
|
||||
return "".join([c.get_initialization_c() for c in self.components])
|
||||
def get_init_c_flat(self):
|
||||
return "".join([c.get_init_c_flat() for c in self.components])
|
||||
|
||||
def get_function_sum_c(self):
|
||||
return "".join([c.get_function_sum_c(self.components.index(c)) for c in self.components])
|
||||
def get_function_sum_c_flat(self):
|
||||
return "".join([c.get_function_sum_c_flat(offset=self.components.index(c)) for c in self.components])
|
||||
|
||||
def get_function_carry_c(self):
|
||||
return f"{self.get_previous_component().get_function_carry_c(offset=self.out.N-1)}"
|
||||
def get_function_carry_c_flat(self):
|
||||
return f"{self.get_previous_component().get_function_carry_c_flat(offset=self.out.N-1)}"
|
||||
|
||||
# Generating flat C code representation of circuit
|
||||
def get_c_code(self, file_object):
|
||||
def get_c_code_flat(self, file_object):
|
||||
file_object.write(self.get_includes_c())
|
||||
file_object.write(self.get_prototype_c())
|
||||
file_object.write(self.out.get_declaration_c())
|
||||
file_object.write(self.get_declaration_c()+"\n")
|
||||
file_object.write(self.get_initialization_c()+"\n")
|
||||
file_object.write(self.get_function_sum_c())
|
||||
file_object.write(self.get_function_carry_c())
|
||||
file_object.write(self.get_declaration_c_flat()+"\n")
|
||||
file_object.write(self.get_init_c_flat()+"\n")
|
||||
file_object.write(self.get_function_sum_c_flat())
|
||||
file_object.write(self.get_function_carry_c_flat())
|
||||
file_object.write(f" return {self.out.prefix}"+";\n}")
|
||||
file_object.close()
|
||||
|
||||
# HIERARCHICAL C GENERATION #
|
||||
# TODO
|
||||
def get_function_blocks_c(self):
|
||||
# Add unique 1-bit adder components (ha, fa)
|
||||
self.component_types = self.get_component_types()
|
||||
# Add unique logic gates composing subcomponents
|
||||
self.all_gates = list(itertools.chain.from_iterable([c.get_component_types() for c in self.component_types]))
|
||||
self.component_types = self.get_unique_types()
|
||||
return "".join([c.get_function_block_c() for c in self.component_types])
|
||||
|
||||
def get_declaration_c_hier(self):
|
||||
self.cout = bus(N=self.N-1, prefix="cout")
|
||||
return "".join(self.a.get_wire_declaration_c()) + \
|
||||
"".join(self.b.get_wire_declaration_c()) + \
|
||||
"".join(self.cout.get_wire_declaration_c())
|
||||
|
||||
def get_init_sum_c_hier(self):
|
||||
self.in_wires = self.a.bus + self.b.bus
|
||||
return ";\n".join([f" {w.name} = " + w.get_wire_value_c(offset=int(w.name[2:])) for w in self.in_wires])
|
||||
|
||||
def get_init_cout_c_hier(self):
|
||||
return "\n".join([c.get_invocation_c(wire_n=self.cout.get_wire(self.components.index(c)).name, offset=self.components.index(c)) for c in self.components[:-1]])
|
||||
|
||||
def get_function_sum_c_hier(self):
|
||||
return ";\n".join([c.get_adder_sum(offset=self.components.index(c)) for c in self.components])+";\n"
|
||||
|
||||
def get_function_carry_c_hier(self):
|
||||
return f"{self.get_previous_component().get_adder_cout(offset=self.out.N-1)};\n"
|
||||
|
||||
def get_circuit_c(self):
|
||||
return f"{self.get_prototype_c()}" + \
|
||||
f"{self.out.get_declaration_c()}" + \
|
||||
f"{self.get_declaration_c_hier()}\n" + \
|
||||
f"{self.get_init_sum_c_hier()};\n" + \
|
||||
f"{self.get_init_cout_c_hier()}\n\n" + \
|
||||
f"{self.get_function_sum_c_hier()}" + \
|
||||
f"{self.get_function_carry_c_hier()}" + \
|
||||
f" return {self.out.prefix}"+";\n}"
|
||||
|
||||
# Generating hierarchical C code representation of circuit
|
||||
def get_c_code_hier(self, file_object):
|
||||
file_object.write(self.get_includes_c())
|
||||
file_object.write(self.get_function_blocks_c())
|
||||
file_object.write(self.get_circuit_c())
|
||||
file_object.close()
|
||||
|
||||
|
||||
class half_adder(arithmetic_circuit):
|
||||
@ -90,11 +142,11 @@ class half_adder(arithmetic_circuit):
|
||||
# FLAT C GENERATION #
|
||||
# Half adder function prototype with two inputs
|
||||
def get_prototype_c(self):
|
||||
return f"{self.c_data_type} {self.prefix}({self.c_data_type} {self.a.name}, {self.c_data_type} {self.b.name})" + "{" + '\n'
|
||||
return f"{self.c_data_type} {self.prefix}({self.c_data_type} {self.a.name}, {self.c_data_type} {self.b.name})" + "{" + "\n"
|
||||
|
||||
# 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(self):
|
||||
def get_declaration_c_flat(self):
|
||||
for component in self.components:
|
||||
if not [item for item in self.circuit_wires if item[1] == component.a.name]:
|
||||
self.circuit_wires.append((component.a, component.a.name))
|
||||
@ -109,17 +161,52 @@ class half_adder(arithmetic_circuit):
|
||||
return "".join([c[0].get_declaration_c() for c in self.circuit_wires])
|
||||
|
||||
# Half adder wires values initialization
|
||||
def get_initialization_c(self):
|
||||
def get_init_c_flat(self):
|
||||
self.a.prefix = self.a.name if self.a.prefix == "" else self.a.prefix
|
||||
self.b.prefix = self.b.name if self.b.prefix == "" else self.b.prefix
|
||||
return f" {self.components[0].a.name} = {self.a.get_wire_value_c(offset=self.a.index)};\n" + \
|
||||
f" {self.components[0].b.name} = {self.b.get_wire_value_c(offset=self.b.index)};\n" + \
|
||||
f" {self.components[0].output.name} = {self.components[0].get_initialization_c()};\n" + \
|
||||
f" {self.components[1].output.name} = {self.components[1].get_initialization_c()};\n"
|
||||
f" {self.components[0].output.name} = {self.components[0].get_init_c_flat()};\n" + \
|
||||
f" {self.components[1].output.name} = {self.components[1].get_init_c_flat()};\n"
|
||||
|
||||
def get_function_sum_c(self, offset: int = 0):
|
||||
return f" {self.out.prefix} |= {self.components[0].output.return_wire_value_c(offset = offset)};\n"
|
||||
def get_function_sum_c_flat(self, offset: int = 0):
|
||||
return f" {self.out.prefix} |= {self.components[0].output.return_wire_value_c(offset=offset)};\n"
|
||||
|
||||
def get_function_carry_c(self, offset: int = 1):
|
||||
return f" {self.out.prefix} |= {self.components[1].output.return_wire_value_c(offset = offset)};\n"
|
||||
def get_function_carry_c_flat(self, offset: int = 1):
|
||||
return f" {self.out.prefix} |= {self.components[1].output.return_wire_value_c(offset=offset)};\n"
|
||||
|
||||
# HIERARCHICAL C GENERATION #
|
||||
def get_function_block_c(self):
|
||||
self.component_types = self.get_component_types()
|
||||
self.prefix = "ha"
|
||||
return f"{self.get_circuit_c()}\n\n"
|
||||
|
||||
def get_function_blocks_c(self):
|
||||
self.component_types = self.get_component_types()
|
||||
return "".join([c.get_function_block_c() for c in self.component_types])
|
||||
|
||||
def get_invocation_c(self, wire_n: str, offset: int = 0):
|
||||
self.prefix = "ha" if (offset == 0) else "fa"
|
||||
return f" {wire_n} = ({self.prefix}({self.a.name}, {self.b.name}) >> 1) & 0x01;"
|
||||
|
||||
def get_adder_sum(self, offset: int = 0):
|
||||
return f" {self.out.prefix} |= (({self.prefix}({self.a.name}, {self.b.name}) >> 0) & 0x01) << {offset}"
|
||||
|
||||
def get_adder_cout(self, offset: int = 1):
|
||||
return f" {self.out.prefix} |= (({self.prefix}({self.a.name}, {self.b.name}) >> 1) & 0x01) << {offset}"
|
||||
|
||||
def get_function_sum_c_hier(self, offset: int = 0):
|
||||
return f" {self.out.prefix} |= {self.component_types[0].get_gate_output_c(a=self.a ,b=self.b, offset=offset)};\n"
|
||||
|
||||
def get_function_carry_c_hier(self, offset: int = 1):
|
||||
return f" {self.out.prefix} |= {self.component_types[1].get_gate_output_c(a=self.a ,b=self.b, offset=offset)};\n"
|
||||
|
||||
def get_circuit_c(self):
|
||||
return f"{self.get_prototype_c()}" + \
|
||||
f"{self.out.get_declaration_c()}\n" + \
|
||||
f"{self.get_function_sum_c_hier()}" + \
|
||||
f"{self.get_function_carry_c_hier()}" + \
|
||||
f" return {self.out.prefix}"+";\n}"
|
||||
|
||||
|
||||
class full_adder(arithmetic_circuit):
|
||||
@ -162,11 +249,11 @@ class full_adder(arithmetic_circuit):
|
||||
# FLAT C GENERATION #
|
||||
# Full adder function prototype with three inputs
|
||||
def get_prototype_c(self):
|
||||
return f"{self.c_data_type} {self.prefix}({self.c_data_type} {self.a.name}, {self.c_data_type} {self.b.name}, {self.c_data_type} {self.c.name})" + "{" + '\n'
|
||||
return f"{self.c_data_type} {self.prefix}({self.c_data_type} {self.a.name}, {self.c_data_type} {self.b.name}, {self.c_data_type} {self.c.name})" + "{" + "\n"
|
||||
|
||||
# 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(self):
|
||||
def get_declaration_c_flat(self):
|
||||
for component in self.components:
|
||||
if not [item for item in self.circuit_wires if item[1] == component.a.name]:
|
||||
self.circuit_wires.append((component.a, component.a.name))
|
||||
@ -181,21 +268,77 @@ class full_adder(arithmetic_circuit):
|
||||
return "".join([c[0].get_declaration_c() for c in self.circuit_wires])
|
||||
|
||||
# Full adder wires values initialization
|
||||
def get_initialization_c(self):
|
||||
def get_init_c_flat(self):
|
||||
self.a.prefix = self.a.name if self.a.prefix == "" else self.a.prefix
|
||||
self.b.prefix = self.b.name if self.b.prefix == "" else self.b.prefix
|
||||
self.c.prefix = self.c.name
|
||||
return f" {self.components[0].a.name} = {self.a.get_wire_value_c(offset=self.a.index)};\n" + \
|
||||
f" {self.components[0].b.name} = {self.b.get_wire_value_c(offset=self.b.index)};\n" + \
|
||||
f" {self.components[2].b.name} = {self.c.get_wire_value_c()};\n" + \
|
||||
f" {self.components[0].output.name} = {self.components[0].get_initialization_c()};\n" + \
|
||||
f" {self.components[1].output.name} = {self.components[1].get_initialization_c()};\n" + \
|
||||
f" {self.components[2].output.name} = {self.components[2].get_initialization_c()};\n" + \
|
||||
f" {self.components[3].output.name} = {self.components[3].get_initialization_c()};\n" + \
|
||||
f" {self.components[4].output.name} = {self.components[4].get_initialization_c()};\n"
|
||||
f" {self.components[0].output.name} = {self.components[0].get_init_c_flat()};\n" + \
|
||||
f" {self.components[1].output.name} = {self.components[1].get_init_c_flat()};\n" + \
|
||||
f" {self.components[2].output.name} = {self.components[2].get_init_c_flat()};\n" + \
|
||||
f" {self.components[3].output.name} = {self.components[3].get_init_c_flat()};\n" + \
|
||||
f" {self.components[4].output.name} = {self.components[4].get_init_c_flat()};\n"
|
||||
|
||||
def get_function_sum_c(self, offset: int = 0):
|
||||
return f" {self.out.prefix} |= {self.components[2].output.return_wire_value_c(offset = offset)};\n"
|
||||
def get_function_sum_c_flat(self, offset: int = 0):
|
||||
return f" {self.out.prefix} |= {self.components[2].output.return_wire_value_c(offset=offset)};\n"
|
||||
|
||||
def get_function_carry_c(self, offset: int = 1):
|
||||
return f" {self.out.prefix} |= {self.components[4].output.return_wire_value_c(offset = offset)};\n"
|
||||
def get_function_carry_c_flat(self, offset: int = 1):
|
||||
return f" {self.out.prefix} |= {self.components[4].output.return_wire_value_c(offset=offset)};\n"
|
||||
|
||||
# HIERARCHICAL C GENERATION #
|
||||
def get_function_block_c(self):
|
||||
self.component_types = self.get_component_types()
|
||||
self.prefix = "fa"
|
||||
self.c.name = "cin"
|
||||
return f"{self.get_circuit_c()}\n\n"
|
||||
|
||||
def get_function_blocks_c(self):
|
||||
self.component_types = self.get_component_types()
|
||||
return "".join([c.get_function_block_c() for c in self.component_types])
|
||||
|
||||
def get_declaration_c_hier(self):
|
||||
self.component_types[0].a.name = "xor_1"
|
||||
self.component_types[2].a.name = "and_1"
|
||||
self.component_types[2].b.name = "and_2"
|
||||
return f"{self.component_types[0].a.get_declaration_c()}" + \
|
||||
f"{self.component_types[2].a.get_declaration_c()}" + \
|
||||
f"{self.component_types[2].b.get_declaration_c()}"
|
||||
|
||||
def get_init_c_hier(self):
|
||||
return f" {self.component_types[0].a.name} = {self.component_types[0].get_invocation_c(self.a, self.b)}\n" + \
|
||||
f" {self.component_types[2].a.name} = {self.component_types[1].get_invocation_c(self.a, self.b)}\n" + \
|
||||
f" {self.component_types[2].b.name} = {self.component_types[1].get_invocation_c(self.component_types[0].a, self.c)}\n"
|
||||
|
||||
def get_invocation_c(self, wire_n: str, offset: int = 0):
|
||||
self.prefix = "ha" if (offset == 0) else "fa"
|
||||
self.c.name = "cout_"+str(offset-1)
|
||||
return f" {wire_n} = ({self.prefix}({self.a.name}, {self.b.name}, {self.c.name}) >> 1) & 0x01;"
|
||||
|
||||
def get_adder_sum(self, offset: int = 0):
|
||||
self.c.name = "cout_"+str(offset-1)
|
||||
return f" {self.out.prefix} |= (({self.prefix}({self.a.name}, {self.b.name}, {self.c.name}) >> 0) & 0x01) << {offset}"
|
||||
|
||||
def get_adder_cout(self, offset: int = 1):
|
||||
self.c.name = "cout_"+str(offset-2)
|
||||
return f" {self.out.prefix} |= (({self.prefix}({self.a.name}, {self.b.name}, {self.c.name}) >> 1) & 0x01) << {offset}"
|
||||
|
||||
def get_function_sum_c_hier(self, offset: int = 0):
|
||||
return f" {self.out.prefix} |= {self.component_types[0].get_gate_output_c(a=self.component_types[0].a, b=self.c, offset=offset)};\n"
|
||||
|
||||
def get_function_carry_c_hier(self, offset: int = 1):
|
||||
return f" {self.out.prefix} |= {self.component_types[-1].get_gate_output_c(a=self.component_types[2].a, b=self.component_types[2].b, offset=offset)};\n"
|
||||
|
||||
def get_circuit_c(self):
|
||||
self.component_types = self.component_types
|
||||
return f"{self.get_prototype_c()}" + \
|
||||
f"{self.out.get_declaration_c()}" + \
|
||||
f"{self.get_declaration_c_hier()}\n" + \
|
||||
f"{self.get_init_c_hier()}\n" + \
|
||||
f"{self.get_function_sum_c_hier()}" + \
|
||||
f"{self.get_function_carry_c_hier()}" + \
|
||||
f" return {self.out.prefix}"+";\n}"
|
||||
|
||||
|
||||
class signed_ripple_carry_adder(arithmetic_circuit):
|
||||
@ -204,8 +347,8 @@ class signed_ripple_carry_adder(arithmetic_circuit):
|
||||
self.N = max(a.N, b.N)
|
||||
self.c_data_type = "int64_t"
|
||||
# Bus sign extension in case buses have different lengths
|
||||
a.sign_extend(self.N)
|
||||
b.sign_extend(self.N)
|
||||
a.bus_extend(N=self.N, prefix=a.prefix)
|
||||
b.bus_extend(N=self.N, prefix=b.prefix)
|
||||
self.a = a
|
||||
self.b = b
|
||||
if prefix == "s_rca":
|
||||
@ -240,29 +383,49 @@ class signed_ripple_carry_adder(arithmetic_circuit):
|
||||
|
||||
# FLAT C GENERATION #
|
||||
# Initialization of 1-bit adders and sign extension XOR gates
|
||||
def get_initialization_c(self):
|
||||
return f"".join([c.get_initialization_c() for c in self.components[:-2]]) + \
|
||||
def get_init_c_flat(self):
|
||||
self.components[-2].output.prefix = self.components[-2].output.name
|
||||
self.components[-3].get_carry_wire().prefix = self.components[-3].get_carry_wire().name
|
||||
return f"".join([c.get_init_c_flat() for c in self.components[:-2]]) + \
|
||||
f" {self.components[-2].a.name} = {self.a.get_wire_value_c(offset=self.N-1)};\n" + \
|
||||
f" {self.components[-2].b.name} = {self.b.get_wire_value_c(offset=self.N-1)};\n" + \
|
||||
f" {self.components[-2].output.name} = {self.components[-2].get_initialization_c()};\n" + \
|
||||
f" {self.components[-2].output.name} = {self.components[-2].get_init_c_flat()};\n" + \
|
||||
f" {self.components[-1].a.name} = {self.components[-2].output.get_wire_value_c()};\n" + \
|
||||
f" {self.components[-1].b.name} = {self.components[-3].get_carry_wire().get_wire_value_c()};\n" + \
|
||||
f" {self.components[-1].output.name} = {self.components[-1].get_initialization_c()};\n"
|
||||
f" {self.components[-1].output.name} = {self.components[-1].get_init_c_flat()};\n"
|
||||
|
||||
def get_function_sum_c(self):
|
||||
return "".join([c.get_function_sum_c(self.components.index(c)) for c in self.components[:-2]])
|
||||
def get_function_sum_c_flat(self):
|
||||
return "".join([c.get_function_sum_c_flat(offset=self.components.index(c)) for c in self.components[:-2]])
|
||||
|
||||
def get_function_carry_c(self):
|
||||
def get_function_carry_c_flat(self):
|
||||
return f" {self.out.prefix} |= {self.get_previous_component().output.return_wire_value_c(offset = self.N)};\n"
|
||||
|
||||
# HIERARCHICAL C GENERATION #
|
||||
def get_declaration_c_hier(self):
|
||||
self.cout = bus(N=self.N, prefix="cout")
|
||||
return "".join(self.a.get_wire_declaration_c()) + \
|
||||
"".join(self.b.get_wire_declaration_c()) + \
|
||||
"".join(self.cout.get_wire_declaration_c()) + \
|
||||
f"{self.components[-2].output.get_declaration_c()}"
|
||||
|
||||
def get_init_cout_c_hier(self):
|
||||
return "\n".join([c.get_invocation_c(wire_n=self.cout.get_wire(self.components.index(c)).name, offset=self.components.index(c)) for c in self.components[:-2]]) + \
|
||||
f"\n {self.components[-2].output.name} = {self.components[-2].get_invocation_c(a=self.a.bus[-1], b=self.b.bus[-1])}"
|
||||
|
||||
def get_function_sum_c_hier(self):
|
||||
return ";\n".join([c.get_adder_sum(offset=self.components.index(c)) for c in self.components[:-2]])+";\n"
|
||||
|
||||
def get_function_carry_c_hier(self):
|
||||
return f" {self.out.prefix} |= {self.get_previous_component().get_gate_output_c(a=self.components[-2].output, b=self.cout.bus[-1], offset=self.out.N-1)};\n"
|
||||
|
||||
|
||||
class unsigned_ripple_carry_adder(arithmetic_circuit):
|
||||
def __init__(self, a: bus, b: bus, prefix: str = "u_rca"):
|
||||
super().__init__()
|
||||
self.N = max(a.N, b.N)
|
||||
# Bus sign extension in case buses have different lengths
|
||||
a.sign_extend(self.N)
|
||||
b.sign_extend(self.N)
|
||||
# Bus sign extension in ase buses have different lengths
|
||||
a.bus_extend(N=self.N, prefix=a.prefix)
|
||||
b.bus_extend(N=self.N, prefix=b.prefix)
|
||||
self.a = a
|
||||
self.b = b
|
||||
if prefix == "u_rca":
|
||||
@ -293,28 +456,14 @@ class unsigned_ripple_carry_adder(arithmetic_circuit):
|
||||
if __name__ == "__main__":
|
||||
a = bus(N=8, prefix="a")
|
||||
b = bus(N=8, prefix="b")
|
||||
rca = signed_ripple_carry_adder(a, b)
|
||||
rca.get_c_code(open("s_rca8.c", "w"))
|
||||
rca = unsigned_ripple_carry_adder(a, b)
|
||||
|
||||
# rca.get_c_code_hier(open("h_u_rca8.c", "w"))
|
||||
|
||||
w1 = wire(name="a")
|
||||
w2 = wire(name="b")
|
||||
w3 = wire(name="cin")
|
||||
fa = full_adder(w1, w2, w3)
|
||||
fa.get_c_code(open("fa.c", "w"))
|
||||
w3 = wire(name="cout")
|
||||
fa = full_adder(w1, w2, w3, prefix="h_fa")
|
||||
ha = half_adder(w1, w2, prefix="h_ha")
|
||||
|
||||
"""
|
||||
# Generation of 8-bit rca
|
||||
a = bus(N=8, prefix="a")
|
||||
b = bus(N=8, prefix="b")
|
||||
rca = ripple_carry_adder(a, b)
|
||||
# Export to C code (flat) and save to file
|
||||
rca.get_c_code(open("rca_8.c", "w"))
|
||||
|
||||
# Generation of OR logic gate
|
||||
# Values just for testing functionality within Python
|
||||
a1 = wire(name="a", value=1)
|
||||
b1 = wire(name="b", value=0)
|
||||
xor = xor_gate(a1, b1)
|
||||
# Export to C code (flat) and display to stdout
|
||||
xor.get_c_code(sys.stdout)
|
||||
"""
|
||||
# ha.get_c_code_hier(open("h_ha.c","w"))
|
||||
|
@ -6,28 +6,33 @@ from wire_components import wire
|
||||
|
||||
class logic_gate():
|
||||
def __init__(self, a: wire, b: wire, prefix: str = "w"):
|
||||
self.a = wire(prefix+"_"+a.name.replace(prefix+"_", ''), a.value)
|
||||
self.b = wire(prefix+"_"+b.name.replace(prefix+"_", ''), b.value)
|
||||
self.a = wire(name=prefix+"_"+a.name.replace(prefix+"_", ""), value=a.value)
|
||||
self.b = wire(name=prefix+"_"+b.name.replace(prefix+"_", ""), value=b.value)
|
||||
self.prefix = prefix
|
||||
|
||||
def get_component_types(self):
|
||||
return list([self])
|
||||
|
||||
# FLAT C GENERATION #
|
||||
@staticmethod
|
||||
def get_includes_c():
|
||||
return f"#include <stdio.h>\n#include <stdint.h>\n\n"
|
||||
|
||||
def get_prototype_c(self):
|
||||
return f"uint8_t {self.gate_type}(uint8_t a, uint8_t b)" + "{" + '\n'
|
||||
self.a.name = self.a.name.replace(self.prefix+"_", "")
|
||||
self.b.name = self.b.name.replace(self.prefix+"_", "")
|
||||
return f"uint8_t {self.gate_type}(uint8_t {self.a.name}, uint8_t {self.b.name})" + "{" + "\n"
|
||||
|
||||
def get_declaration_c(self):
|
||||
def get_declaration_c_flat(self):
|
||||
return f"{self.a.get_declaration_c()}{self.b.get_declaration_c()}{self.output.get_declaration_c()}"
|
||||
|
||||
def get_initialization_c(self):
|
||||
def get_init_c_flat(self):
|
||||
return f"{self.a.name} {self.operator} {self.b.name}"
|
||||
|
||||
def get_function_c(self):
|
||||
self.a.name = self.a.name.replace(self.prefix+"_", '')
|
||||
self.b.name = self.b.name.replace(self.prefix+"_", '')
|
||||
return f"{self.a.get_wire_value_c()} {self.operator} {self.b.get_wire_value_c(0)}"
|
||||
self.a.prefix = self.a.name.replace(self.prefix+"_", "")
|
||||
self.b.prefix = self.b.name.replace(self.prefix+"_", "")
|
||||
return f"{self.a.get_wire_value_c()} {self.operator} {self.b.get_wire_value_c()}"
|
||||
|
||||
# Generating flat C code representation of separate logic gate
|
||||
# (i.e. not as a component of bigger circuit)
|
||||
@ -38,15 +43,25 @@ class logic_gate():
|
||||
file_object.close()
|
||||
|
||||
# HIERARCHICAL C GENERATION #
|
||||
# TODO
|
||||
def get_function_block_c(self):
|
||||
self.a.name = "a"
|
||||
self.b.name = "b"
|
||||
return f"{self.get_prototype_c()}" + \
|
||||
f" return "+(self.get_function_c())+";\n}\n\n"
|
||||
|
||||
def get_invocation_c(self, a: wire, b: wire):
|
||||
return f"{self.gate_type}({a.name}, {b.name});"
|
||||
|
||||
def get_gate_output_c(self, a: wire, b: wire, offset: int = 0):
|
||||
return f"({self.gate_type}({a.name}, {b.name}) & 0x01) << {offset}"
|
||||
|
||||
|
||||
# Single-input
|
||||
class not_gate(logic_gate):
|
||||
def __init__(self, a: wire, prefix: str = "w", outid: int = 0):
|
||||
self.gate_type = 'not_gate'
|
||||
self.operator = '~'
|
||||
self.a = wire(prefix+"_"+a.name.replace(prefix+"_", ''), a.value)
|
||||
self.gate_type = "not_gate"
|
||||
self.operator = "~"
|
||||
self.a = wire(prefix+"_"+a.name.replace(prefix+"_", ""), a.value)
|
||||
self.prefix = prefix
|
||||
|
||||
if self.a.value == 1:
|
||||
@ -54,26 +69,39 @@ class not_gate(logic_gate):
|
||||
else:
|
||||
self.output = wire(name=prefix+"_y"+str(outid), value=1)
|
||||
|
||||
# FLAT C GENERATION #
|
||||
def get_prototype_c(self):
|
||||
return f"uint8_t {self.gate_type}(uint8_t a)" + "{" + '\n'
|
||||
return f"uint8_t {self.gate_type}(uint8_t a)" + "{" + "\n"
|
||||
|
||||
def get_declaration_c(self):
|
||||
return f"{self.a.get_declaration_c()}{self.output.get_declaration_c()}"
|
||||
|
||||
def get_initialization_c(self):
|
||||
def get_init_c_flat(self):
|
||||
return f"{self.operator}{self.a.name}"
|
||||
|
||||
def get_function_c(self):
|
||||
self.a.name = self.a.name.replace(self.prefix+"_", '')
|
||||
self.a.prefix = self.a.name.replace(self.prefix+"_", "")
|
||||
return f"{self.operator}{self.a.get_wire_value_c()} & 0x01 << 0"
|
||||
|
||||
# HIERARCHICAL C GENERATION #
|
||||
def get_function_block_c(self):
|
||||
self.a.name = "a"
|
||||
return f"{self.get_prototype_c()}" + \
|
||||
f" return "+(self.get_function_c())+";\n}\n\n"
|
||||
|
||||
def get_invocation_c(self, a: wire):
|
||||
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}"
|
||||
|
||||
|
||||
# Two-input
|
||||
class and_gate(logic_gate):
|
||||
def __init__(self, a: wire, b: wire, prefix: str = "w", outid: int = 0):
|
||||
super().__init__(a, b, prefix)
|
||||
self.gate_type = 'and_gate'
|
||||
self.operator = '&'
|
||||
self.gate_type = "and_gate"
|
||||
self.operator = "&"
|
||||
|
||||
if a.value == 1 and b.value == 1:
|
||||
self.output = wire(name=prefix+"_y"+str(outid), value=1)
|
||||
@ -84,8 +112,8 @@ class and_gate(logic_gate):
|
||||
class nand_gate(logic_gate):
|
||||
def __init__(self, a: wire, b: wire, prefix: str = "w", outid: int = 0):
|
||||
super().__init__(a, b, prefix)
|
||||
self.gate_type = 'nand_gate'
|
||||
self.operator = '&'
|
||||
self.gate_type = "nand_gate"
|
||||
self.operator = "&"
|
||||
|
||||
if (self.a.value == 1 and self.b.value == 1):
|
||||
self.output = wire(name=prefix+"_y"+str(outid), value=0)
|
||||
@ -99,8 +127,8 @@ class nand_gate(logic_gate):
|
||||
class or_gate(logic_gate):
|
||||
def __init__(self, a: wire, b: wire, prefix: str = "w", outid: int = 0):
|
||||
super().__init__(a, b, prefix)
|
||||
self.gate_type = 'or_gate'
|
||||
self.operator = '|'
|
||||
self.gate_type = "or_gate"
|
||||
self.operator = "|"
|
||||
|
||||
if self.a.value == 1 or self.b.value == 1:
|
||||
self.output = wire(name=prefix+"_y"+str(outid), value=1)
|
||||
@ -111,8 +139,8 @@ class or_gate(logic_gate):
|
||||
class nor_gate(logic_gate):
|
||||
def __init__(self, a: wire, b: wire, prefix: str = "w", outid: int = 0):
|
||||
super().__init__(a, b, prefix)
|
||||
self.gate_type = 'nor_gate'
|
||||
self.operator = '|'
|
||||
self.gate_type = "nor_gate"
|
||||
self.operator = "|"
|
||||
|
||||
if self.a.value == 1 or self.b.value == 1:
|
||||
self.output = wire(name=prefix+"_y"+str(outid), value=0)
|
||||
@ -126,8 +154,8 @@ class nor_gate(logic_gate):
|
||||
class xor_gate(logic_gate):
|
||||
def __init__(self, a: wire, b: wire, prefix: str = "w", outid: int = 0):
|
||||
super().__init__(a, b, prefix)
|
||||
self.gate_type = 'xor_gate'
|
||||
self.operator = '^'
|
||||
self.gate_type = "xor_gate"
|
||||
self.operator = "^"
|
||||
|
||||
if (a.value == 1 and b.value == 0) or (a.value == 0 and b.value == 1):
|
||||
self.output = wire(name=prefix+"_y"+str(outid), value=1)
|
||||
@ -138,8 +166,8 @@ class xor_gate(logic_gate):
|
||||
class xnor_gate(logic_gate):
|
||||
def __init__(self, a: wire, b: wire, prefix: str = "w", outid: int = 0):
|
||||
super().__init__(a, b, prefix)
|
||||
self.gate_type = 'xnor_gate'
|
||||
self.operator = '^'
|
||||
self.gate_type = "xnor_gate"
|
||||
self.operator = "^"
|
||||
|
||||
if (self.a.value == 1 and self.b.value == 0) or (self.a.value == 0 and self.b.value == 1):
|
||||
self.output = wire(name=prefix+"_y"+str(outid), value=0)
|
||||
|
@ -2,16 +2,18 @@
|
||||
|
||||
|
||||
class wire():
|
||||
def __init__(self, name: str, value: int = 0, index: int = 0):
|
||||
def __init__(self, name: str = "w", value: int = 0, index: int = 0):
|
||||
self.name = name
|
||||
self.prefix = name[0:int(name.rfind(str(index))-1)]
|
||||
self.value = value
|
||||
self.index = index
|
||||
|
||||
# C GENERATION #
|
||||
def get_declaration_c(self):
|
||||
return f" uint8_t {self.name} = 0;\n"
|
||||
|
||||
def get_wire_value_c(self, offset: int = 0):
|
||||
return f"(({self.name} >> {offset}) & 0x01)"
|
||||
return f"(({self.prefix} >> {offset}) & 0x01)"
|
||||
|
||||
def return_wire_value_c(self, offset: int = 0):
|
||||
return f"({self.name} & 0x01) << {offset}"
|
||||
@ -19,7 +21,7 @@ class wire():
|
||||
|
||||
class bus():
|
||||
def __init__(self, prefix: str = "bus", N: int = 1):
|
||||
self.bus = [wire(name=prefix, index=i) for i in range(N)]
|
||||
self.bus = [wire(name=prefix+"_"+str(i), index=i) for i in range(N)]
|
||||
self.prefix = prefix
|
||||
self.N = N
|
||||
|
||||
@ -31,21 +33,25 @@ class bus():
|
||||
def connect(self, out_wire_index: int, inner_component_out_wire: wire):
|
||||
self.bus[out_wire_index] = inner_component_out_wire
|
||||
|
||||
def get_wire(self, wire_index: int):
|
||||
return self.bus[wire_index]
|
||||
|
||||
def bus_extend(self, N: int, prefix: str = "bus"):
|
||||
self.bus = [wire(name=prefix+"_"+str(i), index=i) for i in range(N)]
|
||||
self.N = N
|
||||
|
||||
# C GENERATION #
|
||||
def get_wire_value_c(self, offset: int = 0):
|
||||
return self.bus[offset].get_wire_value_c(offset=offset)
|
||||
|
||||
def return_wire_value_c(self, offset: int = 0):
|
||||
self.bus[offset].return_wire_value_c(offset)
|
||||
|
||||
def get_wire_declaration_c(self):
|
||||
return [w.get_declaration_c() for w in self.bus]
|
||||
|
||||
def get_declaration_c(self):
|
||||
if self.N > 8:
|
||||
return f" uint64_t {self.prefix} = 0;\n"
|
||||
else:
|
||||
return f" uint8_t {self.prefix} = 0;\n"
|
||||
|
||||
def get_wire(self, wire_index: int):
|
||||
return self.bus[wire_index]
|
||||
|
||||
def sign_extend(self, N: int):
|
||||
self.bus = [wire(name=self.prefix, index=i) for i in range(N)]
|
||||
self.N = N
|
||||
|
Loading…
x
Reference in New Issue
Block a user