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
|
||||
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 == "":
|
||||
self.prefix = name
|
||||
else:
|
||||
@ -41,13 +41,17 @@ class GeneralCircuit():
|
||||
|
||||
if not outname:
|
||||
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._prefixes = [] # TODO rename to fullname and add distinct attr for prefix, name, suffix
|
||||
self.circuit_gates = []
|
||||
self.circuit_wires = []
|
||||
self.signed = signed
|
||||
self.signed_out = signed_out
|
||||
self.c_data_type = "int64_t" if self.signed is True else "uint64_t"
|
||||
self.pyc = None # Python compiled function
|
||||
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
|
||||
)
|
||||
|
||||
from ariths_gen.multi_bit_circuits.subtractors import (
|
||||
UnsignedRippleCarrySubtractor, SignedRippleCarrySubtractor
|
||||
)
|
||||
|
||||
from ariths_gen.multi_bit_circuits.multipliers import (
|
||||
UnsignedDaddaMultiplier,
|
||||
UnsignedArrayMultiplier,
|
||||
@ -282,6 +286,23 @@ 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
|
||||
@ -311,6 +332,20 @@ def test_signed_add():
|
||||
r = add(av, bv)
|
||||
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():
|
||||
class MAC(GeneralCircuit):
|
||||
|
Loading…
x
Reference in New Issue
Block a user