mirror of
https://github.com/ehw-fit/ariths-gen.git
synced 2025-04-03 13:51:33 +01:00
Added ripple borrow subtractor circuit and updated automated testing.
This commit is contained in:
parent
bc95444995
commit
b87f8350fc
@ -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 │◄──
|
||||
│ │ C3│ │ C2│ │ C1│ │ 1
|
||||
┌──┤ 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│ │
|
||||
│Extend│◄──│Extend│◄──┤ 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
|
||||
│Extend│◄──┤ FA │◄──┤ 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}"
|
||||
|
18
tests/subtractor_signed.c
Normal file
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;
|
||||
}
|
18
tests/subtractor_unsigned.c
Normal file
18
tests/subtractor_unsigned.c
Normal file
@ -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
|
||||
|
33
tests/tb_subtractor_signed.v
Normal file
33
tests/tb_subtractor_signed.v
Normal file
@ -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
|
33
tests/tb_subtractor_unsigned.v
Normal file
33
tests/tb_subtractor_unsigned.v
Normal file
@ -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,15 +29,13 @@ 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())
|
||||
|
||||
|
||||
print(popcnt(av))
|
||||
|
||||
if verbose:
|
||||
print(popcnt(av))
|
||||
|
||||
# conv to binary
|
||||
r = []
|
||||
@ -46,12 +44,18 @@ def test_popcount():
|
||||
r.append(a_s % 2)
|
||||
a_s = a_s // 2
|
||||
r = np.dstack(r).reshape(-1, N)
|
||||
print("r = ", r)
|
||||
|
||||
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,16 +63,14 @@ 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)
|
||||
|
||||
|
||||
print(popcnt(av))
|
||||
|
||||
if verbose:
|
||||
print(popcnt(av))
|
||||
|
||||
# conv to binary
|
||||
r = []
|
||||
@ -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)
|
||||
print("r = ", r)
|
||||
|
||||
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)
|
||||
|
||||
print(all)
|
||||
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))
|
||||
print(cnta)
|
||||
print(cntb)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
print("expected = ", expected)
|
||||
|
||||
#expected = np.sum(r, axis=1)
|
||||
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)
|
||||
|
||||
print(all)
|
||||
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)
|
||||
|
||||
print("expected = ", expected)
|
||||
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)
|
||||
|
||||
print(all)
|
||||
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)
|
||||
|
||||
print("expected = ", expected)
|
||||
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)
|
||||
|
||||
print(all)
|
||||
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)
|
||||
|
||||
print("expected = ", expected)
|
||||
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)
|
||||
print("r = ", r)
|
||||
|
||||
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)
|
||||
print("r = ", r)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user