ripple cary subtractor
This commit is contained in:
parent
e41b4a2f2c
commit
bc0104de12
@ -18,7 +18,7 @@ class GeneralCircuit():
|
|||||||
The __init__ method fills some mandatory attributes concerning arithmetic circuit
|
The __init__ method fills some mandatory attributes concerning arithmetic circuit
|
||||||
that are later used for generation into various representations.
|
that are later used for generation into various representations.
|
||||||
"""
|
"""
|
||||||
def __init__(self, prefix: str, name: str, out_N: int, inner_component: bool = False, inputs: list = [], one_bit_circuit: bool = False, signed: bool = False, outname=None, **kwargs):
|
def __init__(self, prefix: str, name: str, out_N: int, inner_component: bool = False, inputs: list = [], one_bit_circuit: bool = False, signed: bool = False, signed_out = None, outname=None, **kwargs):
|
||||||
if prefix == "":
|
if prefix == "":
|
||||||
self.prefix = name
|
self.prefix = name
|
||||||
else:
|
else:
|
||||||
@ -41,13 +41,17 @@ class GeneralCircuit():
|
|||||||
|
|
||||||
if not outname:
|
if not outname:
|
||||||
outname = self.prefix+"_out"
|
outname = self.prefix+"_out"
|
||||||
self.out = Bus(outname, out_N, out_bus=True, signed=signed)
|
|
||||||
|
if signed_out is None:
|
||||||
|
signed_out = signed
|
||||||
|
self.out = Bus(outname, out_N, out_bus=True, signed=signed_out)
|
||||||
|
|
||||||
self.components = []
|
self.components = []
|
||||||
self._prefixes = [] # TODO rename to fullname and add distinct attr for prefix, name, suffix
|
self._prefixes = [] # TODO rename to fullname and add distinct attr for prefix, name, suffix
|
||||||
self.circuit_gates = []
|
self.circuit_gates = []
|
||||||
self.circuit_wires = []
|
self.circuit_wires = []
|
||||||
self.signed = signed
|
self.signed = signed
|
||||||
|
self.signed_out = signed_out
|
||||||
self.c_data_type = "int64_t" if self.signed is True else "uint64_t"
|
self.c_data_type = "int64_t" if self.signed is True else "uint64_t"
|
||||||
self.pyc = None # Python compiled function
|
self.pyc = None # Python compiled function
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
|
3
ariths_gen/multi_bit_circuits/subtractors/__init__.py
Normal file
3
ariths_gen/multi_bit_circuits/subtractors/__init__.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from ariths_gen.multi_bit_circuits.subtractors.ripple_carry_subtractor import (
|
||||||
|
UnsignedRippleCarrySubtractor, SignedRippleCarrySubtractor
|
||||||
|
)
|
@ -0,0 +1,139 @@
|
|||||||
|
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 (
|
||||||
|
HalfAdder,
|
||||||
|
FullAdder
|
||||||
|
)
|
||||||
|
from ariths_gen.one_bit_circuits.logic_gates import (
|
||||||
|
XorGate, NotGate
|
||||||
|
)
|
||||||
|
from ariths_gen.wire_components.wires import ConstantWireValue1
|
||||||
|
|
||||||
|
|
||||||
|
class UnsignedRippleCarrySubtractor(GeneralCircuit):
|
||||||
|
"""Class representing unsigned ripple carry adder.
|
||||||
|
|
||||||
|
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.
|
||||||
|
```
|
||||||
|
── ── ── ──
|
||||||
|
B3 A3 B2 A2 B1 A1 B0 A0
|
||||||
|
│ │ │ │ │ │ │ │
|
||||||
|
┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
||||||
|
│ │ C3│ │ C2│ │ C1│ │ 1
|
||||||
|
┌──┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │◄──
|
||||||
|
│ │ │ │ │ │ │ │ │
|
||||||
|
│ └──────┘ └──────┘ └──────┘ └──────┘
|
||||||
|
▼ ▼ ▼ ▼ ▼
|
||||||
|
Cout S3 S2 S1 S0
|
||||||
|
```
|
||||||
|
|
||||||
|
Description of the __init__ method.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
a (Bus): First input bus.
|
||||||
|
b (Bus): Second input bus.
|
||||||
|
prefix (str, optional): Prefix name of unsigned rcs. Defaults to "".
|
||||||
|
name (str, optional): Name of unsigned rcs. Defaults to "u_rcs".
|
||||||
|
"""
|
||||||
|
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_rcs", **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 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())
|
||||||
|
|
||||||
|
# invert the last carry wire
|
||||||
|
self.add_component(NotGate(obj_adder.get_carry_wire(), prefix=self.prefix+"_not_c"+str(self.N-1)))
|
||||||
|
self.out.connect(self.N, self.get_previous_component().out)
|
||||||
|
|
||||||
|
|
||||||
|
class SignedRippleCarrySubtractor(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.
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
Description of the __init__ method.
|
||||||
|
|
||||||
|
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".
|
||||||
|
"""
|
||||||
|
def __init__(self, a: Bus, b: Bus, prefix: str = "", name: str = "u_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)
|
||||||
|
|
||||||
|
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)
|
@ -44,6 +44,10 @@ from ariths_gen.multi_bit_circuits.adders import (
|
|||||||
SignedCarryIncrementAdder
|
SignedCarryIncrementAdder
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from ariths_gen.multi_bit_circuits.subtractors import (
|
||||||
|
UnsignedRippleCarrySubtractor, SignedRippleCarrySubtractor
|
||||||
|
)
|
||||||
|
|
||||||
from ariths_gen.multi_bit_circuits.multipliers import (
|
from ariths_gen.multi_bit_circuits.multipliers import (
|
||||||
UnsignedDaddaMultiplier,
|
UnsignedDaddaMultiplier,
|
||||||
UnsignedArrayMultiplier,
|
UnsignedArrayMultiplier,
|
||||||
@ -282,6 +286,23 @@ def test_unsigned_add():
|
|||||||
np.testing.assert_array_equal(expected, r)
|
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():
|
def test_signed_add():
|
||||||
""" Test signed adders """
|
""" Test signed adders """
|
||||||
N = 9
|
N = 9
|
||||||
@ -311,6 +332,20 @@ def test_signed_add():
|
|||||||
r = add(av, bv)
|
r = add(av, bv)
|
||||||
np.testing.assert_array_equal(expected, r)
|
np.testing.assert_array_equal(expected, r)
|
||||||
|
|
||||||
|
def test_signed_sub():
|
||||||
|
""" Test signed subtractor """
|
||||||
|
N = 4
|
||||||
|
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
|
||||||
|
|
||||||
|
# Non configurable multi-bit adders
|
||||||
|
for c in [SignedRippleCarrySubtractor]:
|
||||||
|
sub = c(a, b)
|
||||||
|
r = sub(av, bv)
|
||||||
|
np.testing.assert_array_equal(expected, r)
|
||||||
|
|
||||||
def test_mac():
|
def test_mac():
|
||||||
class MAC(GeneralCircuit):
|
class MAC(GeneralCircuit):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user