Skip to content

Commit

Permalink
Fixed hierarchical Verilog generation of popcount compare. BLIF proba…
Browse files Browse the repository at this point in the history
…bly needs a similar treatment, TBD later
  • Loading branch information
honzastor committed Apr 14, 2024
1 parent 97e79b9 commit 6003886
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 38 deletions.
27 changes: 11 additions & 16 deletions ariths_gen/core/arithmetic_circuits/general_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def __init__(self, prefix: str, name: str, out_N: int, inner_component: bool = F
attr_name = chr(97+i)
full_prefix = f"{self.prefix}_{input.prefix}" if self.inner_component else f"{input.prefix}"
if isinstance(input, Bus) or isinstance(input, Wire):
circuit_input = copy.deepcopy(input)
circuit_input = input
circuit_input.prefix = full_prefix
setattr(self, attr_name, circuit_input)
self.inputs.append(circuit_input)
Expand Down Expand Up @@ -452,8 +452,8 @@ def get_declaration_c_hier(self):
Returns:
str: Hierarchical C code of subcomponent arithmetic circuit's wires declaration.
"""
return ";\n".join([f" {self.c_data_type} {i.prefix} = 0" for i in self.inputs]) + ";\n" + \
f" {self.c_data_type} {self.out.prefix} = 0;\n"
return "".join([f" {self.c_data_type} {i.prefix} = 0;\n" for i in self.inputs if ((isinstance(i, Wire)) or (not all((w.is_const()) or (w.parent_bus is not None and w.prefix == i.prefix) for w in i.bus)))]) + \
f" {self.c_data_type} {self.out.prefix} = 0;\n"

def get_init_c_hier(self):
"""Generates hierarchical C code initialization and assignment of corresponding arithmetic circuit's input/output wires.
Expand Down Expand Up @@ -598,9 +598,7 @@ def get_declaration_v_hier(self):
Returns:
str: Hierarchical Verilog code of subcomponent arithmetic circuit's wires declaration.
"""
return "".join(w.get_wire_declaration_v() for w in self.inputs + [self.out]) + "\n"

#return "".join(b.get_wire_declaration_v() for b in self.inputs + [self.out] if not all((w.is_const()) or (w.parent_bus is not None and w.prefix == b.prefix) for w in b.bus)) + "\n"
return "".join(b.get_wire_declaration_v() for b in self.inputs + [self.out] if (b == self.out) or (not all((w.is_const()) or (w.parent_bus is not None and w.prefix == b.prefix) for w in b.bus)))

def get_init_v_hier(self):
"""Generates hierarchical Verilog code initialization and assignment of corresponding arithmetic circuit's input/output wires.
Expand Down Expand Up @@ -676,16 +674,10 @@ def get_declaration_blif(self):
Returns:
str: Flat Blif code containing declaration of circuit's wires.
"""
if self.N == 1:
return f".inputs {' '.join([w.prefix 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"
else:
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"
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.
Expand Down Expand Up @@ -716,6 +708,9 @@ def get_blif_code_flat(self, file_object):
file_object.write(self.get_function_out_blif())
file_object.write(f".end\n")




# HIERARCHICAL BLIF #
def get_invocations_blif_hier(self):
"""Generates hierarchical Blif code with invocations of subcomponents function blocks.
Expand Down
9 changes: 4 additions & 5 deletions ariths_gen/multi_bit_circuits/others/popcount.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,17 @@ def create_tree(a: Bus, depth: int, branch="A"):
#print(b_in.prefix)
#print(a, half, a.N)
for i, j in enumerate(range(half)):
b_in[i] = a[j]
b_in.connect(i, a.get_wire(j))
for i, j in enumerate(range(half, a.N)):
c_in[i] = a[j]
c_in.connect(i, a.get_wire(j))

b = create_tree(b_in, depth=depth + 1, branch = branch + "A")
c = create_tree(c_in, depth=depth + 1, branch = branch + "B")



d = self.adder(a=b, b=c, prefix = f"{self.prefix}_add{branch}_{depth}")
self.add_component(d)
return d.out

sumbus = create_tree(self.a,0, "X")
#print(sumbus)
self.out.connect_bus(sumbus)
7 changes: 1 addition & 6 deletions ariths_gen/multi_bit_circuits/others/popcount_compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,8 @@ def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "popcnt_cmp",
p2 = self.add_component(UnsignedPopCount(a=Bus(wires_list=self.b.bus, prefix=f"{prefix}_popcount2_a"),
prefix=f"{prefix}_popcount2",
inner_component=True)).out
print(p1)
#N = max(p1.N, p2.N)
#p1.bus_extend(N)
#p2.bus_extend(N)
cmp_gte_a = Bus(wires_list=p1.bus, prefix=f"{prefix}_cmp_gte_a")
cmp_gte_a.connect_bus(p1)
cmp_gte_b = Bus(wires_list=p2.bus, prefix=f"{prefix}_cmp_gte_b")
cmp_gte_b.connect_bus(p2)
red = self.add_component(UnsignedCompareGTE(cmp_gte_a, cmp_gte_b, prefix=f"{prefix}_cmp", inner_component = True))
red = self.add_component(UnsignedCompareGTE(p1, p2, prefix=f"{prefix}_cmp", inner_component = True))
self.out.connect_bus(red.out)
5 changes: 2 additions & 3 deletions ariths_gen/wire_components/buses.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ def return_bus_wires_values_c_hier(self):
"""
# Ensures correct binding between the bus wire index and the wire itself
# It is used for the case when multiple of the same wire (e.g. `ContantWireValue0()`) are present in the bus (its id would otherwise be incorrect when using `self.bus.index(_)`)
mapped_positions = [(w_id, self.bus[w_id]) for w_id in range(self.N)]
mapped_positions = [(w_id, w) for w_id, w in enumerate(self.bus) if ((w.parent_bus is None) or (w.parent_bus is not None and w.prefix != self.prefix) or (w.is_const()))]
return "".join([f" {self.prefix} |= {w[1].return_wire_value_c_hier(offset=w[0])}" for w in mapped_positions])

def return_bus_wires_sign_extend_c_flat(self):
Expand Down Expand Up @@ -226,7 +226,7 @@ def return_bus_wires_values_v_hier(self):
"""
# Ensures correct binding between the bus wire index and the wire itself
# It is used for the case when multiple of the same wire (e.g. `ContantWireValue0()`) are present in the bus (its id would otherwise be incorrect when using `self.bus.index(_)`)
mapped_positions = [(w_id, self.bus[w_id]) for w_id in range(self.N)]
mapped_positions = [(w_id, w) for w_id, w in enumerate(self.bus) if ((w.parent_bus is None) or (w.parent_bus is not None and w.prefix != self.prefix) or (w.is_const()))]
return "".join([f" assign {self.prefix}[{w[0]}] = {w[1].return_wire_value_v_hier()}" for w in mapped_positions])

def get_unique_assign_out_wires_v(self, circuit_block: object):
Expand All @@ -250,7 +250,6 @@ def get_wire_declaration_v(self):
"""
return f" wire [{self.N-1}:0] {self.prefix};\n"


""" BLIF CODE GENERATION """
def get_wire_declaration_blif(self, array: bool = True):
"""Declare each wire from the bus independently in Blif code representation.
Expand Down
16 changes: 12 additions & 4 deletions ariths_gen/wire_components/wires.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def return_wire_value_v_hier(self):

""" BLIF CODE GENERATION """
def get_declaration_blif(self, prefix: str = "", offset: int = 0, array: bool = False):
"""Wire declaration in Blif code.
"""Declaration of wire which is part of a bus in Blif code.
Declares basic wire name if wire is not part of a bus
or declares wire by an offset of its position within the bus.
Expand All @@ -207,6 +207,16 @@ def get_declaration_blif(self, prefix: str = "", offset: int = 0, array: bool =
else:
return f"{self.name}"

def get_wire_declaration_blif(self):
"""Declaration of a single wire in Blif code.
Used for declaration of modul inputs.
Returns:
str: Blif code for declaration of a wire.
"""
return f" {self.prefix}\n"

def get_assign_blif(self, prefix: str, output: bool = False):
"""Assignment of wire value to another desired wire in Blif code.
Expand Down Expand Up @@ -245,10 +255,8 @@ def get_wire_value_blif(self):
"""
if self.is_const():
return self.blif_const
elif self.parent_bus is not None and self.parent_bus.N > 1:
return self.name
else:
return self.prefix
return self.name

def __str__(self):
if self.is_const():
Expand Down
4 changes: 2 additions & 2 deletions generate_mac.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ def __init__(self, a: Bus, b: Bus, r: Bus, prefix: str = "", name: str = "mac",
assert a.N == b.N
assert r.N == 2 * a.N

self.mul = self.add_component(UnsignedArrayMultiplier(a=a, b=b, prefix=self.prefix, name=f"u_arrmul{a.N}", inner_component=True))
self.add = self.add_component(UnsignedRippleCarryAdder(a=r, b=self.mul.out, prefix=self.prefix, name=f"u_rca{r.N}", inner_component=True))
self.mul = self.add_component(UnsignedArrayMultiplier(a=Bus(wires_list=a.bus, prefix=a.prefix), b=Bus(wires_list=b.bus, prefix=b.prefix), prefix=self.prefix, name=f"u_arrmul{a.N}", inner_component=True))
self.add = self.add_component(UnsignedRippleCarryAdder(a=Bus(wires_list=r.bus, prefix=r.prefix), b=self.mul.out, prefix=self.prefix, name=f"u_rca{r.N}", inner_component=True))
self.out.connect_bus(connecting_bus=self.add.out)


Expand Down
4 changes: 2 additions & 2 deletions tests/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,8 @@ def __init__(self, a: Bus, b: Bus, r: Bus, prefix: str = "", name: str = "mac",
assert a.N == b.N
assert r.N == 2 * a.N

self.mul = self.add_component(UnsignedArrayMultiplier(a=a, b=b, prefix=self.prefix, name=f"u_arrmul{a.N}", inner_component=True))
self.add = self.add_component(UnsignedRippleCarryAdder(a=r, b=self.mul.out, prefix=self.prefix, name=f"u_rca{r.N}", inner_component=True))
self.mul = self.add_component(UnsignedArrayMultiplier(a=Bus(wires_list=a.bus, prefix=a.prefix), b=Bus(wires_list=b.bus, prefix=b.prefix), prefix=self.prefix, name=f"u_arrmul{a.N}", inner_component=True))
self.add = self.add_component(UnsignedRippleCarryAdder(a=Bus(wires_list=r.bus, prefix=r.prefix), b=self.mul.out, prefix=self.prefix, name=f"u_rca{r.N}", inner_component=True))
self.out.connect_bus(connecting_bus=self.add.out)

# usage
Expand Down
6 changes: 6 additions & 0 deletions tests/test_popcount_compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,9 @@ def popcnt(x):
#expected = np.sum(r, axis=1)

np.testing.assert_array_equal(v, expected)

if __name__ == "__main__":
#test_popcountcompare_small()
#test_popcountcompare_same()
#test_popcountcompare_small2()
#test_popcountcompare_small2_cgp()

0 comments on commit 6003886

Please sign in to comment.