Skip to content

Commit

Permalink
popcount and compare
Browse files Browse the repository at this point in the history
  • Loading branch information
mrazekv committed Mar 22, 2024
1 parent 7e1112c commit 2e1694c
Show file tree
Hide file tree
Showing 10 changed files with 477 additions and 3 deletions.
18 changes: 16 additions & 2 deletions ariths_gen/core/arithmetic_circuits/general_circuit.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Dict
from ariths_gen.core.logic_gate_circuits.logic_gate_circuit import OneInputLogicGate, TwoInputLogicGate

from ariths_gen.wire_components import (
Expand Down Expand Up @@ -52,12 +53,22 @@ def __str__(self):

# super().__init__(prefix, name, out_N, inner_component, inputs=[a, b], signed=signed, **kwargs)


def get_circuit_def(self) -> Dict[str, Wire]:
""" returns IDs and wires of the inputs and output"""
#.{circuit_block.a.prefix}({self.a.prefix}), .{circuit_block.b.prefix}({self.b.prefix}), .{circuit_block.out.prefix}({self.out.prefix}));\n"
r = {chr(97 + i): self.inputs[i] for i in range(len(self.inputs))}
r['out'] = self.get_global_prefix() + "_out"
return r

def add_component(self, component):
"""Adds a component into list of circuit's inner subcomponents.
Args:
component: Subcomponent to be added into list of components composing described circuit.
"""
prefixes = [c.prefix for c in self.components]
#assert component.prefix not in prefixes, f"Component with prefix {component.prefix} already exists in the circuit."
self.components.append(component)
return component

Expand Down Expand Up @@ -550,6 +561,8 @@ 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 f" wire [{self.a.N-1}:0] {self.a.prefix};\n" + \
f" wire [{self.b.N-1}:0] {self.b.prefix};\n" + \
f" wire [{self.out.N-1}:0] {self.out.prefix};\n"
Expand All @@ -576,8 +589,9 @@ def get_out_invocation_v(self):
circuit_type = 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_type)
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"
return "".join([c.return_bus_wires_values_v_hier() for c in self.inputs]) + \
f" {circuit_type} {circuit_type}_{self.out.prefix}(" + ",".join([f".{a.prefix}({b.prefix})" for a, b in zip(circuit_block.inputs, self.inputs)]) + f", .{circuit_block.out.prefix}({self.out.prefix}));\n"
#.{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_out_v_hier(self):
"""Generates hierarchical Verilog code assignment of corresponding arithmetic circuit's output bus wires.
Expand Down
2 changes: 1 addition & 1 deletion ariths_gen/multi_bit_circuits/adders/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,4 @@
from ariths_gen.multi_bit_circuits.adders.carry_increment_adder import (
UnsignedCarryIncrementAdder,
SignedCarryIncrementAdder
)
)
12 changes: 12 additions & 0 deletions ariths_gen/multi_bit_circuits/others/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

from ariths_gen.multi_bit_circuits.others.popcount import (
UnsignedPopCount
)

from ariths_gen.multi_bit_circuits.others.bit_reduce import (
BitReduce, AndReduce, OrReduce
)

from ariths_gen.multi_bit_circuits.others.compare import (
UnsignedCompareLT
)
89 changes: 89 additions & 0 deletions ariths_gen/multi_bit_circuits/others/bit_reduce.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""
"""

from ariths_gen.wire_components import (
Wire,
ConstantWireValue0,
ConstantWireValue1,
Bus,
wires
)
from ariths_gen.core.arithmetic_circuits import (
ArithmeticCircuit,
GeneralCircuit,
MultiplierCircuit
)
from ariths_gen.core.logic_gate_circuits import (
MultipleInputLogicGate
)
from ariths_gen.one_bit_circuits.one_bit_components import (
HalfAdder,
FullAdder,
FullAdderP,
TwoOneMultiplexer
)
from ariths_gen.one_bit_circuits.logic_gates import (
AndGate,
NandGate,
OrGate,
NorGate,
XorGate,
XnorGate,
NotGate
)

from ariths_gen.core.logic_gate_circuits import TwoInputLogicGate, TwoInputInvertedLogicGate, OneInputLogicGate
from ariths_gen.multi_bit_circuits.adders import UnsignedRippleCarryAdder

from math import log2, ceil

class BitReduce(GeneralCircuit):
"""Class representing tree reducer circuit. Doent work for NAND gate!
"""

def __init__(self, a: Bus, gate : TwoInputLogicGate, prefix : str = "", name : str = "bitreduce", **kwargs):
self.N = a.N
self.a = a

outc = 1
super().__init__(name=name, prefix=prefix, inputs = [self.a], out_N=outc)

# tree reduction
def create_tree(a: Bus, depth: int, branch="A"):

#print(a)
if a.N == 1:
return a[0]
else:
half = a.N // 2
b_in = Bus(N=half, prefix=f"b_inn{depth}A")
c_in = Bus(N=a.N - half, prefix=f"b_inn{depth}B")
#print(a, half, a.N)


for i, j in enumerate(range(half)):
b_in[i] = a[j]

for i, j in enumerate(range(half, a.N)):
c_in[i] = a[j]

b = create_tree(b_in, depth=depth + 1, branch = "A")
c = create_tree(c_in, depth= depth + 1, branch = "B")
d = gate(a=b, b=c, prefix = f"{self.prefix}_red_{branch}_{depth}")
self.add_component(d)
return d.out

sumwire = create_tree(self.a, 0, "X")
#print(sumbus)
self.out[0] = sumwire


class OrReduce(BitReduce):
def __init__(self, a: Bus, prefix : str = "", name : str = "orreduce", **kwargs):
super().__init__(a=a, gate=OrGate, prefix=prefix, name=name, **kwargs)


class AndReduce(BitReduce):
def __init__(self, a: Bus, prefix : str = "", name : str = "orreduce", **kwargs):
super().__init__(a=a, gate=AndGate, prefix=prefix, name=name, **kwargs)
83 changes: 83 additions & 0 deletions ariths_gen/multi_bit_circuits/others/compare.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""
"""

from ariths_gen.wire_components import (
Wire,
ConstantWireValue0,
ConstantWireValue1,
Bus,
wires
)
from ariths_gen.core.arithmetic_circuits import (
ArithmeticCircuit,
GeneralCircuit,
MultiplierCircuit
)

from ariths_gen.core.logic_gate_circuits import (
MultipleInputLogicGate
)
from ariths_gen.one_bit_circuits.one_bit_components import (
HalfAdder,
FullAdder,
FullAdderP,
TwoOneMultiplexer
)
from ariths_gen.one_bit_circuits.logic_gates import (
AndGate,
NandGate,
OrGate,
NorGate,
XorGate,
XnorGate,
NotGate
)

from ariths_gen.multi_bit_circuits.others import OrReduce


from math import log2, ceil

class UnsignedCompareLT(GeneralCircuit):
"""Class representing unsigned compare
Returns true if a < b
"""

def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_lt", **kwargs):
self.a = a
self.b = b
self.N = max(a.N, b.N)

#print("outc", outc)
super().__init__(name=name, prefix=prefix,
inputs = [self.a, self.b], out_N=1)


self.a.bus_extend(self.N, prefix=a.prefix)
self.b.bus_extend(self.N, prefix=b.prefix)


# create wires
psum = ConstantWireValue1()

res = Bus(N = self.N, prefix=self.prefix + "res")


for i in reversed(range(self.N)):

i1 = self.add_component(NotGate(self.a[i], f"{self.prefix}_i1_{i}")).out
i2 = self.b[i]

and1 = self.add_component(AndGate(i1, i2, f"{self.prefix}_and1_{i}")).out
res[i] = self.add_component(AndGate(and1, psum, f"{self.prefix}_and2_{i}")).out

pi = self.add_component(XnorGate(self.a[i], self.b[i], f"{self.prefix}_pi_{i}")).out
psum = self.add_component(AndGate(pi, psum, f"{self.prefix}_psum_{i}")).out


self.out = self.add_component(OrReduce(res, prefix=f"{self.prefix}_orred")).out
#self.out.connect_bus(sumbus )
89 changes: 89 additions & 0 deletions ariths_gen/multi_bit_circuits/others/popcount.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""
"""

from ariths_gen.wire_components import (
Wire,
ConstantWireValue0,
ConstantWireValue1,
Bus,
wires
)
from ariths_gen.core.arithmetic_circuits import (
ArithmeticCircuit,
GeneralCircuit,
MultiplierCircuit
)
from ariths_gen.core.logic_gate_circuits import (
MultipleInputLogicGate
)
from ariths_gen.one_bit_circuits.one_bit_components import (
HalfAdder,
FullAdder,
FullAdderP,
TwoOneMultiplexer
)
from ariths_gen.one_bit_circuits.logic_gates import (
AndGate,
NandGate,
OrGate,
NorGate,
XorGate,
XnorGate,
NotGate
)

from ariths_gen.multi_bit_circuits.adders import UnsignedRippleCarryAdder

from math import log2, ceil

class UnsignedPopCount(GeneralCircuit):
"""Class representing unsigned popcount circuit.
Popcount circuit is a circuit that counts the number of 1s in a binary number.
"""

def __init__(self, a: Bus, adder : ArithmeticCircuit|None = None, prefix : str = "", name : str = "popcnt", **kwargs):
self.N = a.N
self.a = a

outc = ceil(log2(self.N + 1))
#print("outc", outc)
super().__init__(name=name, prefix=prefix, inputs = [self.a], out_N=outc)


self.a.bus_extend(2**(outc - 1), prefix=a.prefix)
#print(self.a)
self.adder = adder
if not self.adder:
self.adder = UnsignedRippleCarryAdder

# tree reduction
def create_tree(a: Bus, depth: int, branch="A"):

#print(a)
if a.N == 1:
return a
else:
half = a.N // 2
b_in = Bus(N=half, prefix=f"b_inn{depth}A")
c_in = Bus(N=a.N - half, prefix=f"b_inn{depth}B")
#print(a, half, a.N)


for i, j in enumerate(range(half)):
b_in[i] = a[j]

for i, j in enumerate(range(half, a.N)):
c_in[i] = a[j]

b = create_tree(b_in, depth=depth + 1, branch = "A")
c = create_tree(c_in, depth= depth + 1, 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 )
9 changes: 9 additions & 0 deletions ariths_gen/wire_components/buses.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,15 @@ def get_unique_assign_out_wires_v(self, circuit_block: object):
[unique_out_wires.append(w.prefix) if w.prefix not in unique_out_wires else None for w in self.bus]
return "".join([f", .{circuit_block.out.get_wire(self.bus.index(o)).prefix}({unique_out_wires.pop(unique_out_wires.index(o.prefix))})" if o.prefix in unique_out_wires else f", .{circuit_block.out.get_wire(self.bus.index(o)).prefix}()" for o in self.bus])

def get_wire_declaration_v(self):
"""Declare the wire in Verilog code representation.
Returns:
str: Verilog code for declaration of individual bus wires.
"""
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
Loading

0 comments on commit 2e1694c

Please sign in to comment.