Merge branch 'devel' of github.com:ehw-fit/ariths-gen into devel

This commit is contained in:
Vojta 2024-10-03 08:19:27 +02:00
commit 813f111df7
20 changed files with 507 additions and 130 deletions

@ -35,7 +35,7 @@ jobs:
- name: Run generating axmults
run: python generate_axmuls.py
- name: Upload results
uses: actions/upload-artifact@v1.0.0
uses: actions/upload-artifact@v4
with:
name: arithmetic-circuits-8
path: test_circuits
@ -54,7 +54,7 @@ jobs:
python-version: '3.x'
- run: python -m pip install numpy
- name: Download workflow run artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: arithmetic-circuits-8
path: test_circuits
@ -82,6 +82,42 @@ jobs:
bash test_circuits_verilog.sh
cd ..
- name: Python circuits testing
run: |
cd tests
python test_all.py
cd ..
- name: Python ax testing
run: |
cd tests
python test_ax.py
cd ..
- name: Python CGP testing
run: |
cd tests
python test_cgp.py
cd ..
- name: Python Compare testing
run: |
cd tests
python test_compare.py
cd ..
- name: Python Popcount testing
run: |
cd tests
python test_popcnt.py
cd ..
- name: Python Reduce testing
run: |
cd tests
python test_reduce.py
cd ..
test_python:
runs-on: ubuntu-latest
needs: build

@ -17,7 +17,7 @@ class UnsignedRippleCarryAdder(GeneralCircuit):
"""Class representing unsigned ripple carry adder.
Unsigned ripple carry adder represents N-bit unsigned adder which is composed of
N one bit adders, where first is a half adder and rest are full adders.
N one bit adders, where the first is a half adder and rest are full adders.
Its downside is its long propagation delay the bigger the circuit is.
@ -68,7 +68,7 @@ class SignedRippleCarryAdder(UnsignedRippleCarryAdder, GeneralCircuit):
"""Class representing signed ripple carry adder.
Signed ripple carry adder represents N-bit signed adder which is composed of
N one bit adders, where first is a half adder and rest are full adders.
N one bit adders, where the first is a half adder and rest are full adders.
At last XOR gates are used to ensure proper sign extension.
Its downside is its long propagation delay the bigger the circuit is.

@ -1,3 +1,8 @@
from ariths_gen.multi_bit_circuits.subtractors.ripple_carry_subtractor import (
UnsignedRippleCarrySubtractor, SignedRippleCarrySubtractor
)
from ariths_gen.multi_bit_circuits.subtractors.ripple_borrow_subtractor import (
UnsignedRippleBorrowSubtractor, SignedRippleBorrowSubtractor
)

@ -0,0 +1,101 @@
from ariths_gen.wire_components import (
Bus
)
from ariths_gen.core.arithmetic_circuits import (
GeneralCircuit
)
from ariths_gen.one_bit_circuits.one_bit_components import (
HalfSubtractor,
FullSubtractor
)
from ariths_gen.one_bit_circuits.logic_gates import (
XorGate
)
class UnsignedRippleBorrowSubtractor(GeneralCircuit):
"""Class representing unsigned ripple borrow subtractor.
Unsigned ripple borrow subtractor represents N-bit unsigned subtractor which is composed of
N one bit subtractors, where the first is a half subtractor and rest are full subtractor.
```
B3 A3 B2 A2 B1 A1 B0 A0
B3 B2 B1
FS FS FS HS
Bout D3 D2 D1 D0
```
Description of the __init__ method.
Args:
a (Bus): First input bus.
b (Bus): Second input bus.
prefix (str, optional): Prefix name of unsigned rbs. Defaults to "".
name (str, optional): Name of unsigned rbs. Defaults to "u_rbs".
"""
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_rbs", **kwargs):
self.N = max(a.N, b.N)
super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N + 1, signed_out=True, **kwargs)
# Bus sign extension in case buses have different lengths
self.a.bus_extend(N=self.N, prefix=a.prefix)
self.b.bus_extend(N=self.N, prefix=b.prefix)
# Gradual addition of 1-bit subtractor components
for input_index in range(self.N):
# First adder is a half subtractor
if input_index == 0:
obj_subtractor = HalfSubtractor(self.a.get_wire(input_index), self.b.get_wire(input_index), prefix=self.prefix+"_hs")
# Rest adders are full subtractor
else:
obj_subtractor = FullSubtractor(self.a.get_wire(input_index), self.b.get_wire(input_index), obj_subtractor.get_borrow_wire(), prefix=self.prefix+"_fs"+str(input_index))
self.add_component(obj_subtractor)
self.out.connect(input_index, obj_subtractor.get_difference_wire())
if input_index == (self.N-1):
self.out.connect(self.N, obj_subtractor.get_borrow_wire())
class SignedRippleBorrowSubtractor(UnsignedRippleBorrowSubtractor, GeneralCircuit):
"""Class representing signed ripple borrow subtractor.
Signed ripple borrow subtractor represents N-bit signed subtractor which is composed of
N one bit subtractor, where the first is a half subtractor and rest are full subtractor.
At last XOR gates are used to ensure proper sign extension.
Its downside is its long propagation delay the bigger the circuit is.
```
B3 A3 B3 A3 B2 A2 B1 A1 B0 A0
SIGN B4 B3 B2 B1
Extend FS FS FS HS
Bout D3 D2 D1 D0
```
Description of the __init__ method.
Args:
a (Bus): First input bus.
b (Bus): Second input bus.
prefix (str, optional): Prefix name of signed rbs. Defaults to "".
name (str, optional): Name of signed rbs. Defaults to "s_rbs".
"""
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_rbs", **kwargs):
super().__init__(a=a, b=b, prefix=prefix, name=name, signed=True, **kwargs)
# Additional XOR gates to ensure correct sign extension in case of sign addition
sign_xor_1 = XorGate(self.get_previous_component(1).a, self.get_previous_component(1).b, prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate)), parent_component=self)
self.add_component(sign_xor_1)
sign_xor_2 = XorGate(sign_xor_1.out, self.get_previous_component(2).get_borrow_wire(), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate)), parent_component=self)
self.add_component(sign_xor_2)
self.out.connect(self.N, sign_xor_2.out)

@ -15,17 +15,17 @@ from ariths_gen.wire_components.wires import ConstantWireValue1
class UnsignedRippleCarrySubtractor(GeneralCircuit):
"""Class representing unsigned ripple carry adder.
"""Class representing unsigned ripple carry subtractor.
Unsigned ripple carry adder represents N-bit unsigned adder which is composed of
N one bit fulladders. The first has carry-in set to one and the B input is inverted.
Unsigned ripple carry subtractor represents N-bit unsigned subtractor which is composed of
N one bit fulladders. The first FA has carry-in set to one and the B inputs of all FAs are inverted.
```
B3 A3 B2 A2 B1 A1 B0 A0
C3 C2 C1 1
FA FA FA HA
FA FA FA FA
@ -48,8 +48,6 @@ class UnsignedRippleCarrySubtractor(GeneralCircuit):
self.a.bus_extend(N=self.N, prefix=a.prefix)
self.b.bus_extend(N=self.N, prefix=b.prefix)
# Gradual addition of 1-bit adder components
for input_index in range(self.N):
b_not = self.add_component(NotGate(self.b.get_wire(input_index), prefix=self.prefix+"_not"+str(input_index)))
@ -68,26 +66,26 @@ class UnsignedRippleCarrySubtractor(GeneralCircuit):
self.out.connect(self.N, self.get_previous_component().out)
class SignedRippleCarrySubtractor(GeneralCircuit):
class SignedRippleCarrySubtractor(UnsignedRippleCarrySubtractor, GeneralCircuit):
"""Class representing signed ripple carry subtractor.
Signed ripple carry adder represents N-bit signed adder which is composed of
N one bit adders, where first is a half adder and rest are full adders.
Signed ripple carry subtractor represents N-bit signed subtractor which is composed of
N one bit fulladders. The first FA has carry-in set to one and the B inputs of all FAs are inverted.
At last XOR gates are used to ensure proper sign extension.
Its downside is its long propagation delay the bigger the circuit is.
```
__ __ __ __ __ __
B3 A3 B3 A3 B3 A3 B2 A2 B1 A1 B0 A0
SIGN C4 SIGN C4 C3 C2 C1
ExtendExtend FA FA FA HA
2
S5 S4 S3 S2 S1 S0
__ __ __ __ __
B3 A3 B3 A3 B2 A2 B1 A1 B0 A0
SIGN C4 C3 C2 C1 1
ExtendFA FA FA FA
Cout S3 S2 S1 S0
```
Description of the __init__ method.
@ -95,45 +93,16 @@ class SignedRippleCarrySubtractor(GeneralCircuit):
Args:
a (Bus): First input bus.
b (Bus): Second input bus.
prefix (str, optional): Prefix name of signed rca. Defaults to "".
name (str, optional): Name of signed rca. Defaults to "s_rcs".
prefix (str, optional): Prefix name of signed rcs. Defaults to "".
name (str, optional): Name of signed rcs. Defaults to "s_rcs".
"""
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_rcs", **kwargs):
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "s_rcs", **kwargs):
self.N = max(a.N, b.N)
super().__init__(inputs=[a, b], prefix=prefix, name=name, out_N=self.N + 2, signed=True, **kwargs)
super().__init__(a=a, b=b, prefix=prefix, name=name, signed=True, **kwargs)
assert self.a.N == self.b.N, "Both buses must have the same length"
# Bus sign extension in case buses have different lengths - don't know if works
self.a.bus_extend(N=self.N, prefix=a.prefix)
self.b.bus_extend(N=self.N, prefix=b.prefix)
# Gradual addition of 1-bit adder components
for input_index in range(self.N):
b_not = self.add_component(NotGate(self.b.get_wire(input_index), prefix=self.prefix+"_not"+str(input_index)))
# First adder is a half adder
if input_index == 0:
obj_adder = FullAdder(self.a.get_wire(input_index), b_not.out, ConstantWireValue1(), prefix=self.prefix+"_ha")
# Rest adders are full adders
else:
obj_adder = FullAdder(self.a.get_wire(input_index), b_not.out, obj_adder.get_carry_wire(), prefix=self.prefix+"_fa"+str(input_index))
self.add_component(obj_adder)
self.out.connect(input_index, obj_adder.get_sum_wire())
# replicate the last (sign) bit
obj_adder = FullAdder(self.a.get_wire(self.N - 1), b_not.out, obj_adder.get_carry_wire(), prefix=self.prefix+"_fa_repl_"+str(input_index))
self.add_component(obj_adder)
self.out.connect(self.N, self.get_previous_component().get_sum_wire())
obj_adder = FullAdder(self.a.get_wire(self.N - 1), b_not.out, obj_adder.get_carry_wire(), prefix=self.prefix+"_fa_repl2_"+str(input_index))
self.add_component(obj_adder)
self.out.connect(self.N+1, self.get_previous_component().get_sum_wire())
# invert the last carry wire
#onot = self.add_component(NotGate(obj_adder.get_carry_wire(), prefix=self.prefix+"_not_c"+str(self.N-1)))
#self.out.connect(self.N + 1, onot.out)
# Additional XOR gates to ensure correct sign extension in case of sign addition
sign_xor_1 = XorGate(self.get_previous_component(2).a, self.get_previous_component(2).b, prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate)), parent_component=self)
self.add_component(sign_xor_1)
sign_xor_2 = XorGate(sign_xor_1.out, self.get_previous_component(3).get_carry_wire(), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate)), parent_component=self)
self.add_component(sign_xor_2)
self.out.connect(self.N, sign_xor_2.out)

@ -54,6 +54,13 @@ from ariths_gen.multi_bit_circuits.adders import (
SignedCarryIncrementAdder
)
from ariths_gen.multi_bit_circuits.subtractors import (
UnsignedRippleCarrySubtractor,
SignedRippleCarrySubtractor,
UnsignedRippleBorrowSubtractor,
SignedRippleBorrowSubtractor
)
from ariths_gen.multi_bit_circuits.multipliers import (
UnsignedDaddaMultiplier,
UnsignedArrayMultiplier,
@ -222,6 +229,23 @@ if __name__ == "__main__":
circuit = SignedLadnerFischerAdder(a, b, name=name, config_choice=1)
export_circuit(circuit, name)
""" SUBTRACTORS """
name = f"u_rcs{N}"
circuit = UnsignedRippleCarrySubtractor(a, b, name=name)
export_circuit(circuit, name)
name = f"s_rcs{N}"
circuit = SignedRippleCarrySubtractor(a, b, name=name)
export_circuit(circuit, name)
name = f"u_rbs{N}"
circuit = UnsignedRippleBorrowSubtractor(a, b, name=name)
export_circuit(circuit, name)
name = f"s_rbs{N}"
circuit = SignedRippleBorrowSubtractor(a, b, name=name)
export_circuit(circuit, name)
""" MULTIPLIERS """
# Arrmul
name = f"u_arrmul{N}"

@ -1,6 +1,6 @@
[metadata]
name = ariths_gen
version = 0.0.1
version = 0.0.2
description = "arithmetic circuits generator"

18
tests/subtractor_signed.c Normal file

@ -0,0 +1,18 @@
#include <assert.h>
#include <stdio.h>
#include <stdint.h>
int64_t CNAME(int64_t a, int64_t b);
int main() {
int result = 0;
for (int i = -128; i < 128; i++){
for (int j = -128; j < 128; j++){
result = i - j;
assert(result == (int)CNAME(i,j));
}
}
return 0;
}

@ -0,0 +1,18 @@
#include <assert.h>
#include <stdio.h>
#include <stdint.h>
uint64_t CNAME(uint64_t a, uint64_t b);
int main() {
int result = 0;
for (int i = 0; i < 256; i++){
for (int j = 0; j < 256; j++){
result = i - j;
assert(result == (int)CNAME(i,j));
}
}
return 0;
}

@ -22,7 +22,7 @@ module add_signed_tb;
#period;
//$assert(b == 0);c
//$assert(b == 0);
if ( k + j != o) begin
$display("Invalid output: %d + %d = %d", a, b, o);
end

@ -0,0 +1,33 @@
`timescale 1 ns/10 ps // time-unit = 1 ns, precision = 10 ps
module sub_signed_tb;
reg signed [7:0] a;
reg signed [7:0] b;
wire signed [8:0] o;
integer k, j;
localparam period = 20;
`dut dut(a, b, o); //.input_a(a), .input_b(b), .cgp_circuit_out(o));
always
begin
for(k = -127; k < 128; k = k+1) begin
for(j = -127; j < 128; j = j+1) begin
assign a = k;
assign b = j;
#period;
//$assert(b == 0);
if ( k - j != o) begin
$display("Invalid output: %d - %d = %d", a, b, o);
end
end;
end;
$finish;
end
endmodule

@ -0,0 +1,33 @@
`timescale 1 ns/10 ps // time-unit = 1 ns, precision = 10 ps
module sub_unsigned_tb;
reg [7:0] a;
reg [7:0] b;
wire signed [8:0] o; // output must be signed for a subtractor
integer k, j;
localparam period = 20;
`dut dut(a, b, o); //.input_a(a), .input_b(b), .cgp_circuit_out(o));
always
begin
for(k = 0; k < 256; k = k+1) begin
for(j = 0; j < 256; j = j+1) begin
assign a = k;
assign b = j;
#period;
//$assert(b == 0);
if ( k - j != o) begin
$display("Invalid output: %d - %d = %d", a, b, o);
end
end;
end;
$finish;
end
endmodule

@ -45,7 +45,8 @@ from ariths_gen.multi_bit_circuits.adders import (
)
from ariths_gen.multi_bit_circuits.subtractors import (
UnsignedRippleCarrySubtractor, SignedRippleCarrySubtractor
UnsignedRippleCarrySubtractor, SignedRippleCarrySubtractor,
UnsignedRippleBorrowSubtractor, SignedRippleBorrowSubtractor
)
from ariths_gen.multi_bit_circuits.multipliers import (
@ -286,23 +287,6 @@ def test_unsigned_add():
np.testing.assert_array_equal(expected, r)
def test_unsigned_sub():
""" Test unsigned subtractor """
N = 9
a = Bus(N=N, prefix="a")
b = Bus(N=N, prefix="b")
av = np.arange(2**N)
bv = av.reshape(-1, 1)
expected = av - bv
# Non configurable multi-bit subtractors
for c in [UnsignedRippleCarrySubtractor]:
sub = c(a, b)
r = sub(av, bv)
np.testing.assert_array_equal(expected, r)
def test_signed_add():
""" Test signed adders """
N = 9
@ -332,9 +316,26 @@ def test_signed_add():
r = add(av, bv)
np.testing.assert_array_equal(expected, r)
def test_unsigned_sub():
""" Test unsigned subtractor """
N = 9
a = Bus(N=N, prefix="a")
b = Bus(N=N, prefix="b")
av = np.arange(2**N)
bv = av.reshape(-1, 1)
expected = av - bv
for c in [UnsignedRippleCarrySubtractor, UnsignedRippleBorrowSubtractor]:
sub = c(a, b)
r = sub(av, bv)
np.testing.assert_array_equal(expected, r)
def test_signed_sub():
""" Test signed subtractor """
N = 4
N = 9
a = Bus(N=N, prefix="a")
b = Bus(N=N, prefix="b")
av = np.arange(-(2**(N-1)), 2**(N-1))
@ -342,7 +343,7 @@ def test_signed_sub():
expected = av - bv
# Non configurable multi-bit adders
for c in [SignedRippleCarrySubtractor]:
for c in [SignedRippleCarrySubtractor, SignedRippleBorrowSubtractor]:
sub = c(a, b)
r = sub(av, bv)
np.testing.assert_array_equal(expected, r)
@ -442,6 +443,8 @@ if __name__ == "__main__":
test_signed_mul()
test_unsigned_add()
test_signed_add()
test_unsigned_sub()
test_signed_sub()
test_mac()
test_direct()
test_wire_as_bus()

@ -46,6 +46,13 @@ from ariths_gen.multi_bit_circuits.adders import (
SignedCarryIncrementAdder
)
from ariths_gen.multi_bit_circuits.subtractors import (
UnsignedRippleBorrowSubtractor,
UnsignedRippleCarrySubtractor,
SignedRippleBorrowSubtractor,
SignedRippleCarrySubtractor
)
from ariths_gen.multi_bit_circuits.multipliers import (
UnsignedDaddaMultiplier,
UnsignedArrayMultiplier,
@ -205,6 +212,61 @@ def test_cgp_signed_add():
np.testing.assert_array_equal(expected, r)
def test_cgp_unsigned_sub():
""" Test unsigned subtractors """
N = 7
a = Bus(N=N, prefix="a")
b = Bus(N=N, prefix="b")
av = np.arange(2**N)
bv = av.reshape(-1, 1)
expected = av - bv
#for c in [UnsignedRippleBorrowSubtractor, UnsignedRippleCarrySubtractor]:
for c in [UnsignedRippleBorrowSubtractor]:
sub = c(a, b)
code = StringIO()
sub.get_cgp_code_flat(code)
cgp_code = code.getvalue()
sub2 = UnsignedCGPCircuit(cgp_code, [N, N], signed_out=True)
o = StringIO()
sub2.get_v_code_flat(o)
print(o.getvalue())
r = sub2(av, bv)
assert sub(0, 0) == 0
assert sub2(0, 0) == 0
np.testing.assert_array_equal(expected, r)
def test_cgp_signed_sub():
""" Test signed subtractors """
N = 7
a = Bus(N=N, prefix="a")
b = Bus(N=N, prefix="b")
av = np.arange(-(2**(N-1)), 2**(N-1))
bv = av.reshape(-1, 1)
expected = av - bv
for c in [SignedRippleBorrowSubtractor, SignedRippleCarrySubtractor]:
sub = c(a, b)
r = sub(av, bv)
code = StringIO()
sub.get_cgp_code_flat(code)
cgp_code = code.getvalue()
print(cgp_code)
sub2 = SignedCGPCircuit(cgp_code, [N, N])
o = StringIO()
sub2.get_v_code_flat(o)
print(o.getvalue())
r = sub2(av, bv)
assert sub(0, 0) == 0
assert sub2(0, 0) == 0
np.testing.assert_array_equal(expected, r)
def test_cgp_unsigned_mul():
""" Test unsigned multipliers """
N = 7
@ -440,6 +502,8 @@ def test_cgp_variant1():
if __name__ == "__main__":
test_cgp_unsigned_add()
test_cgp_signed_add()
test_cgp_unsigned_sub()
test_cgp_signed_sub()
test_cgp_unsigned_mul()
test_cgp_signed_mul()
test_cgp_variant1()

@ -53,6 +53,14 @@ test_circuit "adder_unsigned" "u_ka8"
test_circuit "adder_unsigned" "u_lfa8"
test_circuit "subtractor_signed" "s_rcs8"
test_circuit "subtractor_signed" "s_rbs8"
test_circuit "subtractor_unsigned" "u_rcs8"
test_circuit "subtractor_unsigned" "u_rbs8"
test_circuit "multiplier_signed" "s_arrmul8"
test_circuit "multiplier_signed" "s_csamul_cla8"
test_circuit "multiplier_signed" "s_csamul_rca8"

@ -57,6 +57,10 @@ test_circuit "adder_unsigned" "u_ka8"
test_circuit "adder_unsigned" "u_lfa8"
test_circuit "subtractor_signed" "s_rcs8"
test_circuit "subtractor_signed" "s_rbs8"
test_circuit "multiplier_signed" "s_arrmul8"
test_circuit "multiplier_signed" "s_csamul_cla8"
test_circuit "multiplier_signed" "s_csamul_rca8"

@ -66,6 +66,14 @@ test_circuit "adder_unsigned" "u_ka8"
test_circuit "adder_unsigned" "u_lfa8"
test_circuit "subtractor_signed" "s_rcs8"
test_circuit "subtractor_signed" "s_rbs8"
test_circuit "subtractor_unsigned" "u_rcs8"
test_circuit "subtractor_unsigned" "u_rbs8"
test_circuit "multiplier_signed" "s_arrmul8"
test_circuit "multiplier_signed" "s_csamul_cla8"
test_circuit "multiplier_signed" "s_csamul_rca8"

@ -21,7 +21,7 @@ from ariths_gen.multi_bit_circuits.others import (
import numpy as np
def test_popcount():
def test_popcount(verbose: bool = False):
""" Test unsigned adders """
N = 7
@ -29,16 +29,14 @@ def test_popcount():
a = Bus(N=N, prefix="a")
av = np.arange(2**N)
popcnt = UnsignedPopCount(a=a)
#o = StringIO()
#popcnt.get_v_code_hier(o)
#print(o.getvalue())
if verbose:
print(popcnt(av))
# conv to binary
r = []
a_s = av.copy()
@ -46,12 +44,18 @@ def test_popcount():
r.append(a_s % 2)
a_s = a_s // 2
r = np.dstack(r).reshape(-1, N)
if verbose:
print("r = ", r)
expected = np.sum(r, axis=1)
if verbose:
print("expected = ", expected)
np.testing.assert_array_equal(popcnt(av), expected)
def test_popcount_cgp():
def test_popcount_cgp(verbose: bool = False):
""" Test unsigned adders """
N = 7
@ -59,17 +63,15 @@ def test_popcount_cgp():
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)
if verbose:
print(popcnt(av))
# conv to binary
r = []
a_s = av.copy()
@ -77,8 +79,19 @@ def test_popcount_cgp():
r.append(a_s % 2)
a_s = a_s // 2
r = np.dstack(r).reshape(-1, N)
if verbose:
print("r = ", r)
expected = np.sum(r, axis=1)
if verbose:
print("expected = ", expected)
np.testing.assert_array_equal(v, expected)
if __name__ == "__main__":
test_popcount()
test_popcount_cgp()
print("Python popcount tests were successful!")

@ -26,7 +26,7 @@ from io import StringIO
from itertools import product
def test_popcountcompare_same():
def test_popcountcompare_same(verbose: bool = False):
N = 10
a = Bus(N=N, prefix="a")
@ -35,7 +35,9 @@ def test_popcountcompare_same():
test_cases = list(product(list(range(2**N)), repeat=2))
all = np.array(test_cases)
if verbose:
print(all)
av = all[:, 0]
bv = all[:, 1]
def popcnt(x):
@ -43,28 +45,29 @@ def test_popcountcompare_same():
return np.sum(mask > 0, axis=0)
cnta = (popcnt(av))
cntb = (popcnt(bv))
if verbose:
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)
if verbose:
print("ret = ", v)
expected = np.array(cnta >= cntb).astype(int)
if verbose:
print("expected = ", expected)
#expected = np.sum(r, axis=1)
np.testing.assert_array_equal(v, expected)
def test_popcountcompare_small():
def test_popcountcompare_small(verbose: bool = False):
N = 10
a = Bus(N=N, prefix="a")
@ -73,7 +76,9 @@ def test_popcountcompare_small():
test_cases = list(product(range(2**N), range(2**(N//2))))
all = np.array(test_cases)
if verbose:
print(all)
av = all[:, 0]
bv = all[:, 1]
def popcnt(x):
@ -82,24 +87,28 @@ def test_popcountcompare_small():
cnta = (popcnt(av))
cntb = (popcnt(bv))
if verbose:
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)
if verbose:
print("ret = ", v)
expected = np.array(cnta >= cntb).astype(int)
if verbose:
print("expected = ", expected)
#expected = np.sum(r, axis=1)
np.testing.assert_array_equal(v, expected)
def test_popcountcompare_small2():
def test_popcountcompare_small2(verbose: bool = False):
N = 10
a = Bus(N=N // 2, prefix="a")
@ -108,7 +117,9 @@ def test_popcountcompare_small2():
test_cases = list(product( range(2**(N//2)), range(2**N)))
all = np.array(test_cases)
if verbose:
print(all)
av = all[:, 0]
bv = all[:, 1]
def popcnt(x):
@ -117,25 +128,28 @@ def test_popcountcompare_small2():
cnta = (popcnt(av))
cntb = (popcnt(bv))
if verbose:
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)
if verbose:
print("ret = ", v)
expected = np.array(cnta >= cntb).astype(int)
if verbose:
print("expected = ", expected)
#expected = np.sum(r, axis=1)
np.testing.assert_array_equal(v, expected)
def test_popcountcompare_small2_cgp():
def test_popcountcompare_small2_cgp(verbose: bool = False):
N = 10
a = Bus(N=N // 2, prefix="a")
@ -144,7 +158,9 @@ def test_popcountcompare_small2_cgp():
test_cases = list(product( range(2**(N//2)), range(2**N)))
all = np.array(test_cases)
if verbose:
print(all)
av = all[:, 0]
bv = all[:, 1]
def popcnt(x):
@ -153,6 +169,9 @@ def test_popcountcompare_small2_cgp():
cnta = (popcnt(av))
cntb = (popcnt(bv))
if verbose:
print(cnta)
print(cntb)
cmp = PopCountCompare(a=a, b=b)
cmp.get_v_code_hier(open("tmp.verilog", "w"))
@ -163,13 +182,22 @@ def test_popcountcompare_small2_cgp():
cgp = UnsignedCGPCircuit(o.getvalue(), [N//2, N])
v = cgp(av, bv)
print("ret = ", v)
if verbose:
print("ret = ", v)
expected = np.array(cnta >= cntb).astype(int)
if verbose:
print("expected = ", expected)
#expected = np.sum(r, axis=1)
np.testing.assert_array_equal(v, expected)
if __name__ == "__main__":
test_popcountcompare_same()
test_popcountcompare_small()
test_popcountcompare_small2()
test_popcountcompare_small2_cgp()
print("Python popcount_compare tests were successful!")

@ -24,7 +24,7 @@ from ariths_gen.multi_bit_circuits.others import (
)
def test_orreduce():
def test_orreduce(verbose: bool = False):
""" Test unsigned adders """
N = 7
@ -32,12 +32,12 @@ def test_orreduce():
a = Bus(N=N, prefix="a")
av = np.arange(2**N)
reduce = OrReduce(a=a)
o = StringIO()
reduce.get_v_code_hier(o)
print(o.getvalue())
if verbose:
print(o.getvalue())
#print(reduce(av))
@ -48,13 +48,19 @@ def test_orreduce():
r.append(a_s % 2)
a_s = a_s // 2
r = np.dstack(r).reshape(-1, N)
if verbose:
print("r = ", r)
expected = np.bitwise_or.reduce(r, axis=1)
if verbose:
print("expected = ", expected)
np.testing.assert_array_equal(reduce(av), expected)
def test_andreduce():
def test_andreduce(verbose: bool = False):
""" Test unsigned adders """
N = 7
@ -62,12 +68,12 @@ def test_andreduce():
a = Bus(N=N, prefix="a")
av = np.arange(2**N)
reduce = AndReduce(a=a)
o = StringIO()
reduce.get_v_code_hier(o)
print(o.getvalue())
if verbose:
print(o.getvalue())
#print(reduce(av))
@ -78,9 +84,15 @@ def test_andreduce():
r.append(a_s % 2)
a_s = a_s // 2
r = np.dstack(r).reshape(-1, N)
if verbose:
print("r = ", r)
expected = np.bitwise_and.reduce(r, axis=1)
if verbose:
print("expected = ", expected)
np.testing.assert_array_equal(reduce(av), expected)