mirror of
https://github.com/ehw-fit/ariths-gen.git
synced 2025-04-10 17:22:11 +01:00
Merge branch 'popcount' into devel
This commit is contained in:
commit
1219d7bec5
@ -91,8 +91,8 @@ class GeneralCircuit():
|
|||||||
Args:
|
Args:
|
||||||
component: Subcomponent to be added into list of components composing described circuit.
|
component: Subcomponent to be added into list of components composing described circuit.
|
||||||
"""
|
"""
|
||||||
prefixes = [c.prefix for c in self.components] # TODO ?
|
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."
|
assert component.prefix not in prefixes, f"Component with prefix {component.prefix} already exists in the circuit."
|
||||||
self.components.append(component)
|
self.components.append(component)
|
||||||
return component
|
return component
|
||||||
|
|
||||||
@ -236,28 +236,16 @@ class GeneralCircuit():
|
|||||||
"""
|
"""
|
||||||
self.circuit_wires = []
|
self.circuit_wires = []
|
||||||
circuit_wires_names = []
|
circuit_wires_names = []
|
||||||
if isinstance(self.a, Bus):
|
|
||||||
[self.circuit_wires.append(
|
for input in self.inputs:
|
||||||
(w, f"{w.name}", self.save_wire_id(wire=w))) for w in self.a.bus]
|
if isinstance(input, Bus):
|
||||||
[self.circuit_wires.append(
|
|
||||||
(w, f"{w.name}", self.save_wire_id(wire=w))) for w in self.b.bus]
|
|
||||||
[circuit_wires_names.append(w.name) for w in self.a.bus]
|
|
||||||
[circuit_wires_names.append(w.name) for w in self.b.bus]
|
|
||||||
if hasattr(self, 'c'):
|
|
||||||
[self.circuit_wires.append(
|
[self.circuit_wires.append(
|
||||||
(w, f"{w.name}", self.save_wire_id(wire=w))) for w in self.c.bus]
|
(w, f"{w.name}", self.save_wire_id(wire=w))) for w in input.bus]
|
||||||
[circuit_wires_names.append(w.name) for w in self.c.bus]
|
[circuit_wires_names.append(w.name) for w in input.bus]
|
||||||
else:
|
else:
|
||||||
self.circuit_wires.append(
|
|
||||||
(self.a, f"{self.a.name}", self.save_wire_id(wire=self.a)))
|
|
||||||
self.circuit_wires.append(
|
|
||||||
(self.b, f"{self.b.name}", self.save_wire_id(wire=self.b)))
|
|
||||||
circuit_wires_names.append(self.a.name)
|
|
||||||
circuit_wires_names.append(self.b.name)
|
|
||||||
if hasattr(self, 'c'):
|
|
||||||
self.circuit_wires.append(
|
self.circuit_wires.append(
|
||||||
(self.c, f"{self.c.name}", self.save_wire_id(wire=self.c)))
|
(input, f"{input.name}", self.save_wire_id(wire=input)))
|
||||||
circuit_wires_names.append(self.c.name)
|
circuit_wires_names.append(input.name)
|
||||||
|
|
||||||
for gate in self.circuit_gates:
|
for gate in self.circuit_gates:
|
||||||
if gate.a.name not in circuit_wires_names:
|
if gate.a.name not in circuit_wires_names:
|
||||||
|
@ -123,7 +123,13 @@ class UnsignedCGPCircuit(GeneralCircuit):
|
|||||||
return ConstantWireValue0()
|
return ConstantWireValue0()
|
||||||
if i == 1:
|
if i == 1:
|
||||||
return ConstantWireValue1()
|
return ConstantWireValue1()
|
||||||
return self.vals[i]
|
try:
|
||||||
|
return self.vals[i]
|
||||||
|
except KeyError:
|
||||||
|
|
||||||
|
raise KeyError(f"Key {i} not found in " + ", ".join(
|
||||||
|
[f"{i}: {v}" for i, v in self.vals.items()]
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
class SignedCGPCircuit(UnsignedCGPCircuit):
|
class SignedCGPCircuit(UnsignedCGPCircuit):
|
||||||
|
@ -33,14 +33,16 @@ class MultipleInputLogicGate():
|
|||||||
prefix (str, optional): Prefix used to name inner composite logic gates. Defaults to "".
|
prefix (str, optional): Prefix used to name inner composite logic gates. Defaults to "".
|
||||||
"""
|
"""
|
||||||
def __init__(self, a: Bus, two_input_gate_cls, parent_component: object, prefix: str = ""):
|
def __init__(self, a: Bus, two_input_gate_cls, parent_component: object, prefix: str = ""):
|
||||||
|
i = 0
|
||||||
while a.N != 1:
|
while a.N != 1:
|
||||||
N = math.floor(a.N/2)
|
N = math.floor(a.N/2)
|
||||||
out_wires = []
|
out_wires = []
|
||||||
# Creation of composite two input logic gates from bus `a`'s bit pairs and addition of generated blocks outputs for next iteration
|
# Creation of composite two input logic gates from bus `a`'s bit pairs and addition of generated blocks outputs for next iteration
|
||||||
for bus_index in range(0, N):
|
for bus_index in range(0, N):
|
||||||
gate = two_input_gate_cls(a=a.get_wire(bus_index), b=a.get_wire(bus_index+N), prefix=prefix+str(parent_component.get_instance_num(cls=two_input_gate_cls, count_disabled_gates=False)), parent_component=parent_component)
|
gate = two_input_gate_cls(a=a.get_wire(bus_index), b=a.get_wire(bus_index+N), prefix=prefix+ "_" + str(i) + "_" + str(parent_component.get_instance_num(cls=two_input_gate_cls, count_disabled_gates=False)), parent_component=parent_component)
|
||||||
parent_component.add_component(gate)
|
parent_component.add_component(gate)
|
||||||
out_wires.append(gate.out)
|
out_wires.append(gate.out)
|
||||||
|
i += 1
|
||||||
|
|
||||||
# In case bus `a` has odd number of wires
|
# In case bus `a` has odd number of wires
|
||||||
if a.N % 2 != 0:
|
if a.N % 2 != 0:
|
||||||
@ -110,6 +112,8 @@ class TwoInputLogicGate():
|
|||||||
Returns:
|
Returns:
|
||||||
str: C code description of logic gate's Boolean function (with bitwise shifted inputs).
|
str: C code description of logic gate's Boolean function (with bitwise shifted inputs).
|
||||||
"""
|
"""
|
||||||
|
if self.out.is_const():
|
||||||
|
return self.out.get_wire_value_c_flat()
|
||||||
return f"{self.a.get_wire_value_c_flat()} {self.operator} {self.b.get_wire_value_c_flat()}"
|
return f"{self.a.get_wire_value_c_flat()} {self.operator} {self.b.get_wire_value_c_flat()}"
|
||||||
|
|
||||||
def get_declaration_c_flat(self):
|
def get_declaration_c_flat(self):
|
||||||
@ -206,6 +210,8 @@ class TwoInputLogicGate():
|
|||||||
# No gate logic is generated if one of the inputs is a wire with constant value.
|
# 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.
|
# I.e. either the constant or the second input wire is propagated to the output for the corresponding logic gate's logic function.
|
||||||
if self.disable_generation:
|
if self.disable_generation:
|
||||||
|
#return f" {self.out.prefix} = {self.get_function_c()} # DD {self.prefix} \n"
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
else:
|
else:
|
||||||
return f" {self.out.prefix} = {self.get_function_c()}\n"
|
return f" {self.out.prefix} = {self.get_function_c()}\n"
|
||||||
|
@ -109,14 +109,14 @@ class UnsignedCarryLookaheadAdder(ArithmeticCircuit):
|
|||||||
|
|
||||||
# For each pg pair values algorithmically combine two input AND gates to replace multiple input gates (resolves fan-in issue)
|
# For each pg pair values algorithmically combine two input AND gates to replace multiple input gates (resolves fan-in issue)
|
||||||
pg_wires = Bus(wires_list=composite_wires)
|
pg_wires = Bus(wires_list=composite_wires)
|
||||||
multi_bit_and_gate = MultipleInputLogicGate(a=pg_wires, two_input_gate_cls=AndGate, prefix=self.prefix+"_and", parent_component=self)
|
multi_bit_and_gate = MultipleInputLogicGate(a=pg_wires, two_input_gate_cls=AndGate, prefix=self.prefix+f"_and{block_n}_{i}_{g_index}", parent_component=self)
|
||||||
composite_or_gates_inputs.append(multi_bit_and_gate.out)
|
composite_or_gates_inputs.append(multi_bit_and_gate.out)
|
||||||
|
|
||||||
# Final OR gates cascade using generated AND gates output wires
|
# Final OR gates cascade using generated AND gates output wires
|
||||||
composite_or_wires = Bus(wires_list=composite_or_gates_inputs)
|
composite_or_wires = Bus(wires_list=composite_or_gates_inputs)
|
||||||
multi_bit_or_gate = MultipleInputLogicGate(a=composite_or_wires, two_input_gate_cls=OrGate, prefix=self.prefix+"_or", parent_component=self)
|
multi_bit_or_gate = MultipleInputLogicGate(a=composite_or_wires, two_input_gate_cls=OrGate, prefix=self.prefix+f"_orred{block_n}_{i}_{g_index}_", parent_component=self)
|
||||||
# Carry bit generation
|
# Carry bit generation
|
||||||
obj_cout_or = OrGate(pg_block.get_generate_wire(), multi_bit_or_gate.out, prefix=self.prefix+"_or"+str(self.get_instance_num(cls=OrGate, count_disabled_gates=False)), parent_component=self)
|
obj_cout_or = OrGate(pg_block.get_generate_wire(), multi_bit_or_gate.out, prefix=self.prefix+f"_or{block_n}_{i}_{g_index}_"+str(self.get_instance_num(cls=OrGate, count_disabled_gates=False)), parent_component=self)
|
||||||
self.add_component(obj_cout_or)
|
self.add_component(obj_cout_or)
|
||||||
# Updating cin for the the next cla block/sum XOR
|
# Updating cin for the the next cla block/sum XOR
|
||||||
cin = obj_cout_or.out
|
cin = obj_cout_or.out
|
||||||
|
@ -8,5 +8,7 @@ from ariths_gen.multi_bit_circuits.others.bit_reduce import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from ariths_gen.multi_bit_circuits.others.compare import (
|
from ariths_gen.multi_bit_circuits.others.compare import (
|
||||||
UnsignedCompareLT
|
UnsignedCompareLT, UnsignedCompareLTE, UnsignedCompareGT, UnsignedCompareGTE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from ariths_gen.multi_bit_circuits.others.popcount_compare import PopCountCompare
|
@ -68,8 +68,8 @@ class BitReduce(GeneralCircuit):
|
|||||||
for i, j in enumerate(range(half, a.N)):
|
for i, j in enumerate(range(half, a.N)):
|
||||||
c_in[i] = a[j]
|
c_in[i] = a[j]
|
||||||
|
|
||||||
b = create_tree(b_in, depth=depth + 1, branch = "A")
|
b = create_tree(b_in, depth=depth + 1, branch = branch + "A")
|
||||||
c = create_tree(c_in, depth= depth + 1, branch = "B")
|
c = create_tree(c_in, depth= depth + 1, branch = branch + "B")
|
||||||
d = gate(a=b, b=c, prefix = f"{self.prefix}_red_{branch}_{depth}")
|
d = gate(a=b, b=c, prefix = f"{self.prefix}_red_{branch}_{depth}")
|
||||||
self.add_component(d)
|
self.add_component(d)
|
||||||
return d.out
|
return d.out
|
||||||
|
@ -44,7 +44,6 @@ class UnsignedCompareLT(GeneralCircuit):
|
|||||||
|
|
||||||
|
|
||||||
Returns true if a < b
|
Returns true if a < b
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_lt", **kwargs):
|
def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_lt", **kwargs):
|
||||||
@ -52,32 +51,144 @@ class UnsignedCompareLT(GeneralCircuit):
|
|||||||
self.b = b
|
self.b = b
|
||||||
self.N = max(a.N, b.N)
|
self.N = max(a.N, b.N)
|
||||||
|
|
||||||
#print("outc", outc)
|
|
||||||
super().__init__(name=name, prefix=prefix,
|
super().__init__(name=name, prefix=prefix,
|
||||||
inputs = [self.a, self.b], out_N=1)
|
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
|
# create wires
|
||||||
psum = ConstantWireValue1()
|
psum = ConstantWireValue1()
|
||||||
|
|
||||||
res = Bus(N = self.N, prefix=self.prefix + "res")
|
res = Bus(N = self.N, prefix=self.prefix + "res")
|
||||||
|
|
||||||
|
|
||||||
for i in reversed(range(self.N)):
|
for i in reversed(range(self.N)):
|
||||||
|
iA = self.a[i] if i < self.a.N else ConstantWireValue0()
|
||||||
i1 = self.add_component(NotGate(self.a[i], f"{self.prefix}_i1_{i}")).out
|
iB = self.b[i] if i < self.b.N else ConstantWireValue0()
|
||||||
i2 = self.b[i]
|
|
||||||
|
i1 = self.add_component(NotGate(iA, f"{self.prefix}_i1_{i}")).out
|
||||||
|
i2 = iB
|
||||||
|
|
||||||
and1 = self.add_component(AndGate(i1, i2, f"{self.prefix}_and1_{i}")).out
|
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
|
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
|
pi = self.add_component(XnorGate(iA, iB, f"{self.prefix}_pi_{i}", parent_component=self)).out
|
||||||
psum = self.add_component(AndGate(pi, psum, f"{self.prefix}_psum_{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
|
red = self.add_component(OrReduce(res, prefix=f"{self.prefix}_orred", inner_component=True))
|
||||||
#self.out.connect_bus(sumbus )
|
self.out.connect_bus(red.out)
|
||||||
|
|
||||||
|
|
||||||
|
class UnsignedCompareLTE(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)
|
||||||
|
|
||||||
|
super().__init__(name=name, prefix=prefix,
|
||||||
|
inputs = [self.a, self.b], out_N=1)
|
||||||
|
|
||||||
|
# create wires
|
||||||
|
psum = ConstantWireValue1()
|
||||||
|
|
||||||
|
res = Bus(N = self.N + 1, prefix=self.prefix + "res")
|
||||||
|
|
||||||
|
for i in reversed(range(self.N)):
|
||||||
|
iA = self.a[i] if i < self.a.N else ConstantWireValue0()
|
||||||
|
iB = self.b[i] if i < self.b.N else ConstantWireValue0()
|
||||||
|
|
||||||
|
i1 = self.add_component(NotGate(iA, f"{self.prefix}_i1_{i}")).out
|
||||||
|
i2 = iB
|
||||||
|
|
||||||
|
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(iA, iB, f"{self.prefix}_pi_{i}", parent_component=self)).out
|
||||||
|
psum = self.add_component(AndGate(pi, psum, f"{self.prefix}_psum_{i}")).out
|
||||||
|
|
||||||
|
res[self.N] = psum # or all equal (xor)
|
||||||
|
|
||||||
|
red = self.add_component(OrReduce(res, prefix=f"{self.prefix}_orred", inner_component=True))
|
||||||
|
|
||||||
|
self.out.connect_bus(red.out)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class UnsignedCompareGT(GeneralCircuit):
|
||||||
|
"""Class representing unsigned compare
|
||||||
|
|
||||||
|
|
||||||
|
Returns true if a < b
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_gt", **kwargs):
|
||||||
|
self.a = a
|
||||||
|
self.b = b
|
||||||
|
self.N = max(a.N, b.N)
|
||||||
|
|
||||||
|
super().__init__(name=name, prefix=prefix,
|
||||||
|
inputs = [self.a, self.b], out_N=1)
|
||||||
|
|
||||||
|
# create wires
|
||||||
|
psum = ConstantWireValue1()
|
||||||
|
|
||||||
|
res = Bus(N = self.N, prefix=self.prefix + "res")
|
||||||
|
|
||||||
|
for i in reversed(range(self.N)):
|
||||||
|
iA = self.a[i] if i < self.a.N else ConstantWireValue0()
|
||||||
|
iB = self.b[i] if i < self.b.N else ConstantWireValue0()
|
||||||
|
|
||||||
|
i1 = iA
|
||||||
|
i2 = self.add_component(NotGate(iB, f"{self.prefix}_i2_{i}")).out
|
||||||
|
|
||||||
|
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(iA, iB, f"{self.prefix}_pi_{i}", parent_component=self)).out
|
||||||
|
psum = self.add_component(AndGate(pi, psum, f"{self.prefix}_psum_{i}")).out
|
||||||
|
|
||||||
|
|
||||||
|
red = self.add_component(OrReduce(res, prefix=f"{self.prefix}_orred", inner_component=True))
|
||||||
|
self.out.connect_bus(red.out)
|
||||||
|
|
||||||
|
|
||||||
|
class UnsignedCompareGTE(GeneralCircuit):
|
||||||
|
"""Class representing unsigned compare
|
||||||
|
|
||||||
|
Returns true if a <= b
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_gte", **kwargs):
|
||||||
|
self.a = a
|
||||||
|
self.b = b
|
||||||
|
self.N = max(a.N, b.N)
|
||||||
|
|
||||||
|
super().__init__(name=name, prefix=prefix,
|
||||||
|
inputs = [self.a, self.b], out_N=1)
|
||||||
|
|
||||||
|
# create wires
|
||||||
|
psum = ConstantWireValue1()
|
||||||
|
|
||||||
|
res = Bus(N = self.N + 1, prefix=self.prefix + "res")
|
||||||
|
|
||||||
|
for i in reversed(range(self.N)):
|
||||||
|
iA = self.a[i] if i < self.a.N else ConstantWireValue0()
|
||||||
|
iB = self.b[i] if i < self.b.N else ConstantWireValue0()
|
||||||
|
|
||||||
|
i1 = iA
|
||||||
|
i2 = self.add_component(NotGate(iB, f"{self.prefix}_i1_{i}", parent_component=self)).out
|
||||||
|
|
||||||
|
and1 = self.add_component(AndGate(i1, i2, f"{self.prefix}_and1_{i}", parent_component=self)).out
|
||||||
|
res[i] = self.add_component(AndGate(and1, psum, f"{self.prefix}_and2_{i}", parent_component=self)).out
|
||||||
|
|
||||||
|
pi = self.add_component(XnorGate(iA, iB, f"{self.prefix}_pi_{i}", parent_component=self)).out
|
||||||
|
psum = self.add_component(AndGate(pi, psum, f"{self.prefix}_psum_{i}", parent_component=self)).out
|
||||||
|
|
||||||
|
res[self.N] = psum # or all equal (xor)
|
||||||
|
|
||||||
|
red = self.add_component(OrReduce(res, prefix=f"{self.prefix}_orred", inner_component=True))
|
||||||
|
|
||||||
|
self.out.connect_bus(red.out)
|
@ -79,8 +79,8 @@ class UnsignedPopCount(GeneralCircuit):
|
|||||||
for i, j in enumerate(range(half, a.N)):
|
for i, j in enumerate(range(half, a.N)):
|
||||||
c_in[i] = a[j]
|
c_in[i] = a[j]
|
||||||
|
|
||||||
b = create_tree(b_in, depth=depth + 1, branch = "A")
|
b = create_tree(b_in, depth=depth + 1, branch = branch + "A")
|
||||||
c = create_tree(c_in, depth= depth + 1, branch = "B")
|
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}")
|
d = self.adder(a=b, b=c, prefix = f"{self.prefix}_add{branch}_{depth}")
|
||||||
self.add_component(d)
|
self.add_component(d)
|
||||||
return d.out
|
return d.out
|
||||||
|
81
ariths_gen/multi_bit_circuits/others/popcount_compare.py
Normal file
81
ariths_gen/multi_bit_circuits/others/popcount_compare.py
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ariths_gen.multi_bit_circuits.others import UnsignedPopCount
|
||||||
|
from ariths_gen.multi_bit_circuits.others.compare import UnsignedCompareGTE
|
||||||
|
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 PopCountCompare(GeneralCircuit):
|
||||||
|
"""Class representing a circiut
|
||||||
|
if number of ones in a is larger or equal than number of ones in b
|
||||||
|
|
||||||
|
│ │ │ │ │ │ │ │ │
|
||||||
|
▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼
|
||||||
|
┌───────┐ ┌─────────┐
|
||||||
|
│ popcnt│ │ popcnt │
|
||||||
|
└──┬────┘ └─────┬───┘
|
||||||
|
│ │
|
||||||
|
└───────┐ ┌──────┘
|
||||||
|
┌──▼───▼──┐
|
||||||
|
│ <= │
|
||||||
|
└────┬────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, a: Bus, b: Bus, prefix : str = "", name : str = "cmp_lt", **kwargs):
|
||||||
|
self.a = a
|
||||||
|
self.b = b
|
||||||
|
|
||||||
|
super().__init__(name=name, prefix=prefix,
|
||||||
|
inputs = [self.a, self.b], out_N=1)
|
||||||
|
|
||||||
|
p1 = self.add_component(UnsignedPopCount(self.a,
|
||||||
|
prefix=f"{prefix}_popcount1",
|
||||||
|
inner_component=True)).out
|
||||||
|
p2 = self.add_component(UnsignedPopCount(self.b,
|
||||||
|
prefix=f"{prefix}_popcount2",
|
||||||
|
inner_component=True)).out
|
||||||
|
|
||||||
|
N = max(p1.N, p2.N)
|
||||||
|
p1.bus_extend(N)
|
||||||
|
p2.bus_extend(N)
|
||||||
|
|
||||||
|
red = self.add_component(UnsignedCompareGTE(p1, p2, prefix=f"{prefix}_cmp", inner_component = True))
|
||||||
|
self.out.connect_bus(red.out)
|
@ -92,7 +92,8 @@ class NandGate(TwoInputInvertedLogicGate):
|
|||||||
# If constant input is present, logic gate is not generated and corresponding
|
# If constant input is present, logic gate is not generated and corresponding
|
||||||
# input value is propagated to the output to connect to other components
|
# input value is propagated to the output to connect to other components
|
||||||
if a.is_const() and a.value == 1:
|
if a.is_const() and a.value == 1:
|
||||||
output = NotGate(a=b, prefix=prefix, outid=outid, parent_component=parent_component)
|
assert self.parent_component, "Parent component for gate {self} is not defined"
|
||||||
|
output = NotGate(a=b, prefix=prefix + "_not", outid=outid, parent_component=parent_component)
|
||||||
self.parent_component.add_component(output) if parent_component is not None else None
|
self.parent_component.add_component(output) if parent_component is not None else None
|
||||||
self.out = output.out
|
self.out = output.out
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
@ -100,7 +101,8 @@ class NandGate(TwoInputInvertedLogicGate):
|
|||||||
self.out = ConstantWireValue1()
|
self.out = ConstantWireValue1()
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
elif b.is_const() and b.value == 1:
|
elif b.is_const() and b.value == 1:
|
||||||
output = NotGate(a=a, prefix=prefix, outid=outid, parent_component=parent_component)
|
assert self.parent_component, "Parent component for gate {self} is not defined"
|
||||||
|
output = NotGate(a=a, prefix=prefix + "_not", outid=outid, parent_component=parent_component)
|
||||||
self.parent_component.add_component(output) if parent_component is not None else None
|
self.parent_component.add_component(output) if parent_component is not None else None
|
||||||
self.out = output.out
|
self.out = output.out
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
@ -217,7 +219,8 @@ class NorGate(TwoInputInvertedLogicGate):
|
|||||||
self.out = ConstantWireValue0()
|
self.out = ConstantWireValue0()
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
elif a.is_const() and a.value == 0:
|
elif a.is_const() and a.value == 0:
|
||||||
output = NotGate(a=b, prefix=prefix, outid=outid, parent_component=parent_component)
|
assert self.parent_component, "Parent component for gate {self} is not defined"
|
||||||
|
output = NotGate(a=b, prefix=prefix + "_not", outid=outid, parent_component=parent_component)
|
||||||
self.parent_component.add_component(output) if parent_component is not None else None
|
self.parent_component.add_component(output) if parent_component is not None else None
|
||||||
self.out = output.out
|
self.out = output.out
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
@ -225,7 +228,8 @@ class NorGate(TwoInputInvertedLogicGate):
|
|||||||
self.out = ConstantWireValue0()
|
self.out = ConstantWireValue0()
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
elif b.is_const() and b.value == 0:
|
elif b.is_const() and b.value == 0:
|
||||||
output = NotGate(a=a, prefix=prefix, outid=outid, parent_component=parent_component)
|
assert self.parent_component, "Parent component for gate {self} is not defined"
|
||||||
|
output = NotGate(a=a, prefix=prefix + "_not", outid=outid, parent_component=parent_component)
|
||||||
self.parent_component.add_component(output) if parent_component is not None else None
|
self.parent_component.add_component(output) if parent_component is not None else None
|
||||||
self.out = output.out
|
self.out = output.out
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
@ -277,7 +281,8 @@ class XorGate(TwoInputLogicGate):
|
|||||||
# If constant input is present, logic gate is not generated and corresponding
|
# If constant input is present, logic gate is not generated and corresponding
|
||||||
# input value is propagated to the output to connect to other components
|
# input value is propagated to the output to connect to other components
|
||||||
if a.is_const() and a.value == 1:
|
if a.is_const() and a.value == 1:
|
||||||
output = NotGate(a=b, prefix=prefix, outid=outid, parent_component=parent_component)
|
assert self.parent_component, "Parent component for gate {self} is not defined"
|
||||||
|
output = NotGate(a=b, prefix=prefix + "_not", outid=outid, parent_component=parent_component)
|
||||||
self.parent_component.add_component(output) if parent_component is not None else None
|
self.parent_component.add_component(output) if parent_component is not None else None
|
||||||
self.out = output.out
|
self.out = output.out
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
@ -285,7 +290,8 @@ class XorGate(TwoInputLogicGate):
|
|||||||
self.out = b
|
self.out = b
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
elif b.is_const() and b.value == 1:
|
elif b.is_const() and b.value == 1:
|
||||||
output = NotGate(a=a, prefix=prefix, outid=outid, parent_component=parent_component)
|
assert self.parent_component, "Parent component for gate {self} is not defined"
|
||||||
|
output = NotGate(a=a, prefix=prefix + "_not", outid=outid, parent_component=parent_component)
|
||||||
self.parent_component.add_component(output) if parent_component is not None else None
|
self.parent_component.add_component(output) if parent_component is not None else None
|
||||||
self.out = output.out
|
self.out = output.out
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
@ -343,7 +349,8 @@ class XnorGate(TwoInputInvertedLogicGate):
|
|||||||
self.out = b
|
self.out = b
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
elif a.is_const() and a.value == 0:
|
elif a.is_const() and a.value == 0:
|
||||||
output = NotGate(a=b, prefix=prefix, outid=outid, parent_component=parent_component)
|
assert self.parent_component, "Parent component for gate {self} is not defined"
|
||||||
|
output = NotGate(a=b, prefix=prefix + "_not", outid=outid, parent_component=parent_component)
|
||||||
self.parent_component.add_component(output) if parent_component is not None else None
|
self.parent_component.add_component(output) if parent_component is not None else None
|
||||||
self.out = output.out
|
self.out = output.out
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
@ -351,7 +358,8 @@ class XnorGate(TwoInputInvertedLogicGate):
|
|||||||
self.out = a
|
self.out = a
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
elif b.is_const() and b.value == 0:
|
elif b.is_const() and b.value == 0:
|
||||||
output = NotGate(a=a, prefix=prefix, outid=outid, parent_component=parent_component)
|
assert self.parent_component, "Parent component for gate {self} is not defined"
|
||||||
|
output = NotGate(a=a, prefix=prefix + "_not", outid=outid, parent_component=parent_component)
|
||||||
self.parent_component.add_component(output) if parent_component is not None else None
|
self.parent_component.add_component(output) if parent_component is not None else None
|
||||||
self.out = output.out
|
self.out = output.out
|
||||||
self.disable_generation = True
|
self.disable_generation = True
|
||||||
|
@ -17,6 +17,9 @@ class Wire():
|
|||||||
self.prefix = name if prefix == "" else prefix
|
self.prefix = name if prefix == "" else prefix
|
||||||
self.parent_bus = parent_bus
|
self.parent_bus = parent_bus
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"wire{self.name}{self.value}{self.index}"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_const():
|
def is_const():
|
||||||
"""Information whether wire carries constant value.
|
"""Information whether wire carries constant value.
|
||||||
|
@ -370,8 +370,8 @@ def test_wire_as_bus():
|
|||||||
def __init__(self, a: Wire, b: Wire, c: Bus, prefix="test_circuit", **kwargs):
|
def __init__(self, a: Wire, b: Wire, c: Bus, prefix="test_circuit", **kwargs):
|
||||||
super().__init__(prefix=prefix, name="test_circuit", inputs=[a, b, c], out_N=1, **kwargs)
|
super().__init__(prefix=prefix, name="test_circuit", inputs=[a, b, c], out_N=1, **kwargs)
|
||||||
g = self.add_component(AndGate(a, b, prefix="g2"))
|
g = self.add_component(AndGate(a, b, prefix="g2"))
|
||||||
g2 = self.add_component(AndGate(g.out, c[0], prefix="g2"))
|
g2 = self.add_component(AndGate(g.out, c[0], prefix="g3"))
|
||||||
g3 = self.add_component(AndGate(g2.out, c[1], prefix="g2"))
|
g3 = self.add_component(AndGate(g2.out, c[1], prefix="g4"))
|
||||||
self.out[0] = g3.out
|
self.out[0] = g3.out
|
||||||
|
|
||||||
circ = test_circuit(Wire("a"), Wire("b"), Bus("c", 2), "c1")
|
circ = test_circuit(Wire("a"), Wire("b"), Bus("c", 2), "c1")
|
||||||
|
@ -18,11 +18,18 @@ from ariths_gen.wire_components import (
|
|||||||
from ariths_gen.core.arithmetic_circuits import GeneralCircuit
|
from ariths_gen.core.arithmetic_circuits import GeneralCircuit
|
||||||
|
|
||||||
from ariths_gen.multi_bit_circuits.others import (
|
from ariths_gen.multi_bit_circuits.others import (
|
||||||
UnsignedCompareLT
|
UnsignedCompareLT, UnsignedCompareLTE, UnsignedCompareGT, UnsignedCompareGTE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from ariths_gen.core.cgp_circuit import UnsignedCGPCircuit, SignedCGPCircuit
|
||||||
|
|
||||||
def test_compare():
|
|
||||||
|
import numpy as np
|
||||||
|
import math
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
|
|
||||||
|
def test_compare_lt_same():
|
||||||
""" Test unsigned comparator """
|
""" Test unsigned comparator """
|
||||||
N = 8
|
N = 8
|
||||||
|
|
||||||
@ -33,9 +40,39 @@ def test_compare():
|
|||||||
|
|
||||||
|
|
||||||
cmp = UnsignedCompareLT(a=a, b=b)
|
cmp = UnsignedCompareLT(a=a, b=b)
|
||||||
o = StringIO()
|
|
||||||
cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
print(o.getvalue())
|
|
||||||
|
v = cmp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
expected = np.array(av < bv).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_compare_lt_small():
|
||||||
|
""" Test unsigned comparator """
|
||||||
|
N = 8
|
||||||
|
|
||||||
|
a = Bus(N=N, prefix="a")
|
||||||
|
b = Bus(N=N//2, prefix="b")
|
||||||
|
av = np.arange(2**N).reshape(1, -1)
|
||||||
|
bv = np.arange(2**(N //2)).reshape(-1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
cmp = UnsignedCompareLT(a=a, b=b)
|
||||||
|
#o = StringIO()
|
||||||
|
cmp.get_python_code_flat(open("tmp.py", "w"))
|
||||||
|
cmp.get_c_code_flat(open("tmp.c", "w"))
|
||||||
|
cmp.get_cgp_code_flat(open("tmp.cgp", "w"))
|
||||||
|
#cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
#print(o.getvalue())
|
||||||
|
|
||||||
# av = 0
|
# av = 0
|
||||||
# bv = 5
|
# bv = 5
|
||||||
@ -53,6 +90,290 @@ def test_compare():
|
|||||||
np.testing.assert_array_equal(v, expected)
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
test_compare()
|
|
||||||
print("Python compare tests were successful!")
|
def test_compare_lte_same():
|
||||||
|
""" Test unsigned comparator """
|
||||||
|
N = 8
|
||||||
|
|
||||||
|
a = Bus(N=N, prefix="a")
|
||||||
|
b = Bus(N=N, prefix="b")
|
||||||
|
av = np.arange(2**N).reshape(1, -1)
|
||||||
|
bv = np.arange(2**N).reshape(-1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
cmp = UnsignedCompareLTE(a=a, b=b)
|
||||||
|
cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
|
||||||
|
v = cmp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
expected = np.array(av <= bv).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_compare_lte_small():
|
||||||
|
""" Test unsigned comparator """
|
||||||
|
N = 8
|
||||||
|
|
||||||
|
a = Bus(N=N, prefix="a")
|
||||||
|
b = Bus(N=N//2, prefix="b")
|
||||||
|
av = np.arange(2**N).reshape(1, -1)
|
||||||
|
bv = np.arange(2**(N //2)).reshape(-1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
cmp = UnsignedCompareLTE(a=a, b=b)
|
||||||
|
#o = StringIO()
|
||||||
|
cmp.get_python_code_flat(open("tmp.py", "w"))
|
||||||
|
cmp.get_c_code_flat(open("tmp.c", "w"))
|
||||||
|
cmp.get_cgp_code_flat(open("tmp.cgp", "w"))
|
||||||
|
#cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
#print(o.getvalue())
|
||||||
|
|
||||||
|
# av = 0
|
||||||
|
# bv = 5
|
||||||
|
|
||||||
|
|
||||||
|
v = cmp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
expected = np.array(av <= bv).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
|
def test_compare_lte_small2():
|
||||||
|
""" Test unsigned comparator """
|
||||||
|
N = 8
|
||||||
|
|
||||||
|
a = Bus(N=N//2, prefix="a")
|
||||||
|
b = Bus(N=N, prefix="b")
|
||||||
|
av = np.arange(2**(N // 2)).reshape(1, -1)
|
||||||
|
bv = np.arange(2**(N)).reshape(-1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
cmp = UnsignedCompareLTE(a=a, b=b)
|
||||||
|
#o = StringIO()
|
||||||
|
cmp.get_python_code_flat(open("tmp.py", "w"))
|
||||||
|
cmp.get_c_code_flat(open("tmp.c", "w"))
|
||||||
|
cmp.get_cgp_code_flat(open("tmp.cgp", "w"))
|
||||||
|
#cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
#print(o.getvalue())
|
||||||
|
|
||||||
|
# av = 0
|
||||||
|
# bv = 5
|
||||||
|
|
||||||
|
|
||||||
|
v = cmp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
expected = np.array(av <= bv).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
|
def test_compare_gt_same():
|
||||||
|
""" Test unsigned comparator """
|
||||||
|
N = 8
|
||||||
|
|
||||||
|
a = Bus(N=N, prefix="a")
|
||||||
|
b = Bus(N=N, prefix="b")
|
||||||
|
av = np.arange(2**N).reshape(1, -1)
|
||||||
|
bv = np.arange(2**N).reshape(-1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
cmp = UnsignedCompareGT(a=a, b=b)
|
||||||
|
cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
|
||||||
|
v = cmp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
expected = np.array(av > bv).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_compare_gt_small():
|
||||||
|
""" Test unsigned comparator """
|
||||||
|
N = 8
|
||||||
|
|
||||||
|
a = Bus(N=N, prefix="a")
|
||||||
|
b = Bus(N=N//2, prefix="b")
|
||||||
|
av = np.arange(2**N).reshape(1, -1)
|
||||||
|
bv = np.arange(2**(N //2)).reshape(-1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
cmp = UnsignedCompareGT(a=a, b=b)
|
||||||
|
#o = StringIO()
|
||||||
|
cmp.get_python_code_flat(open("tmp.py", "w"))
|
||||||
|
cmp.get_c_code_flat(open("tmp.c", "w"))
|
||||||
|
cmp.get_cgp_code_flat(open("tmp.cgp", "w"))
|
||||||
|
#cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
#print(o.getvalue())
|
||||||
|
|
||||||
|
# av = 0
|
||||||
|
# bv = 5
|
||||||
|
|
||||||
|
|
||||||
|
v = cmp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
expected = np.array(av > bv).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_compare_gte_same():
|
||||||
|
""" Test unsigned comparator """
|
||||||
|
N = 8
|
||||||
|
|
||||||
|
a = Bus(N=N, prefix="a")
|
||||||
|
b = Bus(N=N, prefix="b")
|
||||||
|
av = np.arange(2**N).reshape(1, -1)
|
||||||
|
bv = np.arange(2**N).reshape(-1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
cmp = UnsignedCompareGTE(a=a, b=b)
|
||||||
|
cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
|
||||||
|
v = cmp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
expected = np.array(av >= bv).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_compare_gte_small():
|
||||||
|
""" Test unsigned comparator """
|
||||||
|
N = 8
|
||||||
|
|
||||||
|
a = Bus(N=N, prefix="a")
|
||||||
|
b = Bus(N=N//2, prefix="b")
|
||||||
|
av = np.arange(2**N).reshape(1, -1)
|
||||||
|
bv = np.arange(2**(N //2)).reshape(-1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
cmp = UnsignedCompareGTE(a=a, b=b)
|
||||||
|
#o = StringIO()
|
||||||
|
cmp.get_python_code_flat(open("tmp.py", "w"))
|
||||||
|
cmp.get_c_code_flat(open("tmp.c", "w"))
|
||||||
|
cmp.get_cgp_code_flat(open("tmp.cgp", "w"))
|
||||||
|
#cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
#print(o.getvalue())
|
||||||
|
|
||||||
|
# av = 0
|
||||||
|
# bv = 5
|
||||||
|
|
||||||
|
|
||||||
|
v = cmp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
expected = np.array(av >= bv).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_compare_gte_cgp_same():
|
||||||
|
""" Test unsigned comparator """
|
||||||
|
N = 8
|
||||||
|
|
||||||
|
a = Bus(N=N, prefix="a")
|
||||||
|
b = Bus(N=N, prefix="b")
|
||||||
|
av = np.arange(2**N).reshape(1, -1)
|
||||||
|
bv = np.arange(2**N).reshape(-1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
cmp = UnsignedCompareGTE(a=a, b=b)
|
||||||
|
o = StringIO()
|
||||||
|
cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
cmp.get_cgp_code_flat(o)
|
||||||
|
|
||||||
|
cgp = UnsignedCGPCircuit(o.getvalue(), [N, N])
|
||||||
|
|
||||||
|
v = cgp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
expected = np.array(av >= bv).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_compare_gte_cgp_small():
|
||||||
|
""" Test unsigned comparator """
|
||||||
|
N = 8
|
||||||
|
|
||||||
|
a = Bus(N=N, prefix="a")
|
||||||
|
b = Bus(N=N//2, prefix="b")
|
||||||
|
av = np.arange(2**N).reshape(1, -1)
|
||||||
|
bv = np.arange(2**(N //2)).reshape(-1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
cmp = UnsignedCompareGTE(a=a, b=b)
|
||||||
|
o = StringIO()
|
||||||
|
cmp.get_v_code_flat(open("tmp.verilog", "w"))
|
||||||
|
cmp.get_cgp_code_flat(o)
|
||||||
|
cmp.get_cgp_code_flat(open("tmp.cgp", "w"))
|
||||||
|
|
||||||
|
cgp = UnsignedCGPCircuit(o.getvalue(), [N, N // 2])
|
||||||
|
|
||||||
|
v = cgp(av, bv)
|
||||||
|
#cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
#print(o.getvalue())
|
||||||
|
|
||||||
|
# av = 0
|
||||||
|
# bv = 5
|
||||||
|
|
||||||
|
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
expected = np.array(av >= bv).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
@ -1,13 +1,4 @@
|
|||||||
import os
|
from ariths_gen.core.cgp_circuit import UnsignedCGPCircuit
|
||||||
import sys
|
|
||||||
# Add the parent directory to the system path
|
|
||||||
DIR_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
sys.path.insert(0, os.path.join(DIR_PATH, '..'))
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
import math
|
|
||||||
from io import StringIO
|
|
||||||
|
|
||||||
from ariths_gen.wire_components import (
|
from ariths_gen.wire_components import (
|
||||||
Wire,
|
Wire,
|
||||||
ConstantWireValue0,
|
ConstantWireValue0,
|
||||||
@ -52,7 +43,34 @@ def test_popcount():
|
|||||||
|
|
||||||
np.testing.assert_array_equal(popcnt(av), expected)
|
np.testing.assert_array_equal(popcnt(av), expected)
|
||||||
|
|
||||||
|
def test_popcount_cgp():
|
||||||
|
""" Test unsigned adders """
|
||||||
|
N = 7
|
||||||
|
|
||||||
|
for N in [3, 7, 8, 9, 16]:
|
||||||
|
a = Bus(N=N, prefix="a")
|
||||||
|
av = np.arange(2**N)
|
||||||
|
|
||||||
|
|
||||||
|
popcnt = UnsignedPopCount(a=a)
|
||||||
|
o = StringIO()
|
||||||
|
popcnt.get_cgp_code_flat(o)
|
||||||
|
cgp = UnsignedCGPCircuit(o.getvalue(), [N])
|
||||||
|
v = cgp(av)
|
||||||
|
|
||||||
|
|
||||||
|
print(popcnt(av))
|
||||||
|
|
||||||
|
|
||||||
|
# conv to binary
|
||||||
|
r = []
|
||||||
|
a_s = av.copy()
|
||||||
|
for i in range(N):
|
||||||
|
r.append(a_s % 2)
|
||||||
|
a_s = a_s // 2
|
||||||
|
r = np.dstack(r).reshape(-1, N)
|
||||||
|
print("r = ", r)
|
||||||
|
expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
test_popcount()
|
|
||||||
print("Python popcnt tests were successful!")
|
|
||||||
|
169
tests/test_popcount_compare.py
Normal file
169
tests/test_popcount_compare.py
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
from ariths_gen.wire_components import (
|
||||||
|
Wire,
|
||||||
|
ConstantWireValue0,
|
||||||
|
ConstantWireValue1,
|
||||||
|
Bus
|
||||||
|
)
|
||||||
|
|
||||||
|
from ariths_gen.core.arithmetic_circuits import GeneralCircuit
|
||||||
|
|
||||||
|
from ariths_gen.multi_bit_circuits.others import (
|
||||||
|
PopCountCompare
|
||||||
|
)
|
||||||
|
|
||||||
|
from ariths_gen.core.cgp_circuit import UnsignedCGPCircuit, SignedCGPCircuit
|
||||||
|
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import math
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
|
from itertools import product
|
||||||
|
|
||||||
|
def test_popcountcompare_same():
|
||||||
|
N = 10
|
||||||
|
|
||||||
|
a = Bus(N=N, prefix="a")
|
||||||
|
b = Bus(N=N, prefix="b")
|
||||||
|
|
||||||
|
test_cases = list(product(list(range(2**N)), repeat=2))
|
||||||
|
all = np.array(test_cases)
|
||||||
|
|
||||||
|
print(all)
|
||||||
|
av = all[:, 0]
|
||||||
|
bv = all[:, 1]
|
||||||
|
def popcnt(x):
|
||||||
|
mask = x & (2**np.arange(N)).reshape(-1, 1)
|
||||||
|
return np.sum(mask > 0, axis=0)
|
||||||
|
cnta = (popcnt(av))
|
||||||
|
cntb = (popcnt(bv))
|
||||||
|
print(cnta)
|
||||||
|
print(cntb)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cmp = PopCountCompare(a=a, b=b)
|
||||||
|
cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
|
||||||
|
v = cmp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
|
||||||
|
expected = np.array(cnta >= cntb).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
|
def test_popcountcompare_small():
|
||||||
|
N = 10
|
||||||
|
|
||||||
|
a = Bus(N=N, prefix="a")
|
||||||
|
b = Bus(N=N // 2, prefix="b")
|
||||||
|
|
||||||
|
test_cases = list(product(range(2**N), range(2**(N//2))))
|
||||||
|
all = np.array(test_cases)
|
||||||
|
|
||||||
|
print(all)
|
||||||
|
av = all[:, 0]
|
||||||
|
bv = all[:, 1]
|
||||||
|
def popcnt(x):
|
||||||
|
mask = x & (2**np.arange(N)).reshape(-1, 1)
|
||||||
|
return np.sum(mask > 0, axis=0)
|
||||||
|
cnta = (popcnt(av))
|
||||||
|
cntb = (popcnt(bv))
|
||||||
|
|
||||||
|
|
||||||
|
cmp = PopCountCompare(a=a, b=b)
|
||||||
|
cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
|
||||||
|
v = cmp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
|
||||||
|
expected = np.array(cnta >= cntb).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
|
def test_popcountcompare_small2():
|
||||||
|
N = 10
|
||||||
|
|
||||||
|
a = Bus(N=N // 2, prefix="a")
|
||||||
|
b = Bus(N=N, prefix="b")
|
||||||
|
|
||||||
|
test_cases = list(product( range(2**(N//2)), range(2**N)))
|
||||||
|
all = np.array(test_cases)
|
||||||
|
|
||||||
|
print(all)
|
||||||
|
av = all[:, 0]
|
||||||
|
bv = all[:, 1]
|
||||||
|
def popcnt(x):
|
||||||
|
mask = x & (2**np.arange(N)).reshape(-1, 1)
|
||||||
|
return np.sum(mask > 0, axis=0)
|
||||||
|
cnta = (popcnt(av))
|
||||||
|
cntb = (popcnt(bv))
|
||||||
|
|
||||||
|
|
||||||
|
cmp = PopCountCompare(a=a, b=b)
|
||||||
|
cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
|
||||||
|
v = cmp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
|
||||||
|
expected = np.array(cnta >= cntb).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_popcountcompare_small2_cgp():
|
||||||
|
N = 10
|
||||||
|
|
||||||
|
a = Bus(N=N // 2, prefix="a")
|
||||||
|
b = Bus(N=N, prefix="b")
|
||||||
|
|
||||||
|
test_cases = list(product( range(2**(N//2)), range(2**N)))
|
||||||
|
all = np.array(test_cases)
|
||||||
|
|
||||||
|
print(all)
|
||||||
|
av = all[:, 0]
|
||||||
|
bv = all[:, 1]
|
||||||
|
def popcnt(x):
|
||||||
|
mask = x & (2**np.arange(N)).reshape(-1, 1)
|
||||||
|
return np.sum(mask > 0, axis=0)
|
||||||
|
cnta = (popcnt(av))
|
||||||
|
cntb = (popcnt(bv))
|
||||||
|
|
||||||
|
|
||||||
|
cmp = PopCountCompare(a=a, b=b)
|
||||||
|
cmp.get_v_code_hier(open("tmp.verilog", "w"))
|
||||||
|
cmp.get_cgp_code_flat(open("tmp.cgp", "w"))
|
||||||
|
|
||||||
|
o = StringIO()
|
||||||
|
cmp.get_cgp_code_flat(o)
|
||||||
|
cgp = UnsignedCGPCircuit(o.getvalue(), [N//2, N])
|
||||||
|
|
||||||
|
v = cgp(av, bv)
|
||||||
|
print("ret = ", v)
|
||||||
|
|
||||||
|
|
||||||
|
expected = np.array(cnta >= cntb).astype(int)
|
||||||
|
|
||||||
|
print("expected = ", expected)
|
||||||
|
|
||||||
|
#expected = np.sum(r, axis=1)
|
||||||
|
|
||||||
|
np.testing.assert_array_equal(v, expected)
|
Loading…
x
Reference in New Issue
Block a user