from BinPy.Gates.gates import *
import math
[docs]class HalfAdder(GATES):
"""This Class implements Half Adder, Arithmetic sum of two bits and return its
Sum and Carry
Output: [SUM, CARRY]
Example:
>>> from BinPy import *
>>> ha = HalfAdder(0, 1)
>>> ha.output()
[1, 0]
"""
def __init__(self, input1, input2):
GATES.__init__(self, [input1, input2])
self.outputType = [0, 0]
self.outputConnector = [None, None]
self.trigger()
[docs] def trigger(self):
if isinstance(self.outputType, int):
return
S = XOR(self.inputs[0], self.inputs[1]).output()
C = AND(self.inputs[0], self.inputs[1]).output()
self._updateResult([S, C])
[docs] def setOutput(self, index, value):
if not isinstance(value, Connector):
raise Exception("ERROR: Expecting a Connector Class Object")
value.tap(self, 'output')
self.outputType[index] = 1
self.outputConnector[index] = value
self.trigger()
def _updateResult(self, value):
self.result = value
for i in range(len(value)):
if self.outputType[i] == 1:
self.outputConnector[i].state = value[i]
[docs]class FullAdder(GATES):
"""This Class implements Full Adder, Arithmetic sum of three bits and
return its Sum and Carry
Output: [SUM, CARRY]
Example:
>>> from BinPy import *
>>> fa = FullAdder(0, 1, 1)
>>> fa.output()
[0, 1]
"""
def __init__(self, input1, input2, carry):
GATES.__init__(self, [input1, input2, carry])
self.outputType = [0, 0, 0]
self.outputConnector = [None, None, None]
self.trigger()
[docs] def trigger(self):
if isinstance(self.outputType, int):
return
ha1 = HalfAdder(self.inputs[0], self.inputs[1]).output()
ha2 = HalfAdder(ha1[0], self.inputs[2]).output()
S = ha2[0]
C = OR(ha2[1], ha1[1]).output()
self._updateResult([S, C])
[docs] def setOutput(self, index, value):
if not isinstance(value, Connector):
raise Exception("ERROR: Expecting a Connector Class Object")
value.tap(self, 'output')
self.outputType[index] = 1
self.outputConnector[index] = value
self.trigger()
def _updateResult(self, value):
self.result = value
for i in range(len(value)):
if self.outputType[i] == 1:
self.outputConnector[i].state = value[i]
[docs]class BinaryAdder(GATES):
"""This Class implements Binary Adder, Arithmetic sum of two bit strings
and return its Sum and Carry
Output: [CARRY, SUM]
Example:
>>> from BinPy import *
>>> ba = BinaryAdder([0, 1], [1, 0], 0)
>>> ba.output()
[0, 1, 1]
"""
def __init__(self, input1, input2, carry):
self.carry = carry
self.size = max(len(input1), len(input2))
input1 = self.fill(input1, self.size)
input2 = self.fill(input2, self.size)
GATES.__init__(self, [input1, input2])
self.outputType = [0] * (self.size + 1)
self.outputConnector = [None] * (self.size + 1)
self.trigger()
[docs] def fill(self, arr, size):
arr = list(map(str, arr))
arr = "".join(arr)
arr = str.zfill(arr, size)
arr = list(arr)
arr = list(map(int, arr))
return arr
[docs] def trigger(self):
if isinstance(self.outputType, int):
return
result = []
carry = self.carry
for i in range(self.size - 1, -1, -1):
S, carry = FullAdder(
self.inputs[0][i], self.inputs[1][i], carry).output()
result.append(S)
result.append(carry)
result.reverse()
self._updateResult(result)
[docs] def setOutput(self, index, value):
if not isinstance(value, Connector):
raise Exception("ERROR: Expecting a Connector Class Object")
value.tap(self, 'output')
self.outputType[index] = 1
self.outputConnector[index] = value
self.trigger()
def _updateResult(self, value):
self.result = value
for i in range(len(value)):
if self.outputType[i] == 1:
self.outputConnector[i].state = value[i]
[docs]class BCDAdder(GATES):
"""This Class implements 4 bit BCD Adder,
and return its BCD Sum and Carry
Output: [SUM, CARRY]
Example:
>>> from BinPy import *
>>> ba = BCDAdder([0, 1, 1, 0], [1, 0, 1, 0], 0)
>>> ba.output()
[0, 0, 0, 0, 1]
"""
def __init__(self, input1, input2, carry):
self.carry = carry
self.size = max(len(input1), len(input2))
self.input1 = input1
self.input2 = input2
input3 = self.fill(self.input1, self.size)
input4 = self.fill(self.input2, self.size)
GATES.__init__(self, [input3, input4])
self.outputType = [0] * (self.size + 1)
self.outputConnector = [None] * (self.size + 1)
self.trigger()
[docs] def fill(self, arr, size):
arr = list(map(str, arr))
arr = "".join(arr)
arr = str.zfill(arr, size)
arr = list(arr)
arr = list(map(int, arr))
return arr
[docs] def trigger(self):
if isinstance(self.outputType, int):
return
result = BinaryAdder(self.input1, self.input2, self.carry).output()
temp = AND(result[1], result[2]).output()
temp1 = AND(result[1], result[3]).output()
temp = OR(temp1, temp).output()
temp = OR(result[0], temp).output()
self.input1[0] = 0
self.input1[1] = temp
self.input1[2] = temp
self.input1[3] = 0
self.input2[0] = result[1]
self.input2[1] = result[2]
self.input2[2] = result[3]
self.input2[3] = result[4]
self.carry = result[0]
result = BinaryAdder(self.input1, self.input2, self.carry).output()
self._updateResult(result)
[docs] def setOutput(self, index, value):
if not isinstance(value, Connector):
raise Exception("ERROR: Expecting a Connector Class Object")
value.tap(self, 'output')
self.outputType[index] = 1
self.outputConnector[index] = value
self.trigger()
def _updateResult(self, value):
self.result = value
for i in range(len(value)):
if self.outputType[i] == 1:
self.outputConnector[i].state = value[i]
[docs]class HalfSubtractor(GATES):
"""This Class implements Half Subtractor, Arithmetic difference of two bits and return its
Difference and Borrow output
Output: [DIFFERENCE, BORROW]
Example:
>>> from BinPy import *
>>> hs = HalfSubtractor(0, 1)
>>> hs.output()
[1, 1]
"""
def __init__(self, input1, input2):
GATES.__init__(self, [input1, input2])
self.outputType = [0, 0]
self.outputConnector = [None, None]
self.trigger()
[docs] def trigger(self):
if isinstance(self.outputType, int):
return
D = XOR(self.inputs[0], self.inputs[1]).output()
B = AND(NOT(self.inputs[0]), self.inputs[1]).output()
self._updateResult([D, B])
[docs] def setOutput(self, index, value):
if not isinstance(value, Connector):
raise Exception("ERROR: Expecting a Connector Class Object")
value.tap(self, 'output')
self.outputType[index] = 1
self.outputConnector[index] = value
self.trigger()
def _updateResult(self, value):
self.result = value
for i in range(len(value)):
if self.outputType[i] == 1:
self.outputConnector[i].state = value[i]
[docs]class FullSubtractor(GATES):
"""This Class implements Full Subtractor, Arithmetic difference of three bits and
return its Difference and Borrow
Output: [DIFFERENCE, BORROW]
Example:
>>> from BinPy import *
>>> fs = FullSubtractor(0, 1, 1)
>>> fs.output()
[0, 1]
"""
def __init__(self, input1, input2, borrow):
GATES.__init__(self, [input1, input2, borrow])
self.outputType = [0, 0, 0]
self.outputConnector = [None, None, None]
self.trigger()
[docs] def trigger(self):
if isinstance(self.outputType, int):
return
x = self.inputs[0]
y = self.inputs[1]
z = self.inputs[2]
D = OR(
AND(
NOT(x), NOT(y), z), AND(
NOT(x), y, NOT(z)), AND(
x, NOT(y), NOT(z)), AND(
x, y, z)).output()
B = OR(AND(NOT(x), z), AND(NOT(x), y), AND(y, z)).output()
self._updateResult([D, B])
[docs] def setOutput(self, index, value):
if not isinstance(value, Connector):
raise Exception("ERROR: Expecting a Connector Class Object")
value.tap(self, 'output')
self.outputType[index] = 1
self.outputConnector[index] = value
self.trigger()
def _updateResult(self, value):
self.result = value
for i in range(len(value)):
if self.outputType[i] == 1:
self.outputConnector[i].state = value[i]
[docs]class BinarySubtractor(GATES):
"""This Class implements Binary Subtractor, Arithmetic difference of two bit strings
and return its difference and borrow
Output: [BORROW, DIFFERENCE]
Example:
>>> from BinPy import *
>>> bs = BinarySubtractor([0, 1], [1, 0], 1)
>>> bs.output()
[1, 1, 0]
"""
def __init__(self, input1, input2, borrow):
self.borrow = borrow
self.size = max(len(input1), len(input2))
input1 = self.fill(input1, self.size)
input2 = self.fill(input2, self.size)
GATES.__init__(self, [input1, input2])
self.outputType = [0] * (self.size + 1)
self.outputConnector = [None] * (self.size + 1)
self.trigger()
[docs] def fill(self, arr, size):
arr = list(map(str, arr))
arr = "".join(arr)
arr = str.zfill(arr, size)
arr = list(arr)
arr = list(map(int, arr))
return arr
[docs] def trigger(self):
if isinstance(self.outputType, int):
return
result = []
borrow = self.borrow
for i in range(self.size - 1, -1, -1):
D, borrow = FullSubtractor(
self.inputs[0][i], self.inputs[1][i], borrow).output()
result.append(D)
result.append(borrow)
result.reverse()
self._updateResult(result)
[docs] def setOutput(self, index, value):
if not isinstance(value, Connector):
raise Exception("ERROR: Expecting a Connector Class Object")
value.tap(self, 'output')
self.outputType[index] = 1
self.outputConnector[index] = value
self.trigger()
def _updateResult(self, value):
self.result = value
for i in range(len(value)):
if self.outputType[i] == 1:
self.outputConnector[i].state = value[i]
[docs]class MUX(GATES):
"""
This class can be used to create MUX in your circuit. MUX is used to select
a single output line out of many inputs. This class can be used as any 2^n X
n Multiplexer where n is the number of select lines used to select the input
out of 2^n input lines.
INPUT: nth index has nth input value, input should be power of 2
OUTPUT: single output, 1 or 0
SELECT LINES: In binary form, select line for 4 will be 1 0 0
Example:
>>> from BinPy import *
>>> mux = MUX(0, 1) "MUX takes its 2^n inputs (digital or Connector)"
>>> mux.selectLines(0) "Put select Line"
>>> mux.output()
0
>>> mux.selectLine(0, 1) "Select line at index 0 is changed to 1"
>>> mux.output()
1
>>> mux.setInput(1, 0) "Input line at index 1 is changed to 0"
>>> mux.output()
0
"""
def __init__(self, *inputs):
if not (len(inputs) > 1 and (len(inputs) & (len(inputs) - 1) == 0)):
raise Exception("ERROR: Number inputs should be a power of 2")
self.selects = []
GATES.__init__(self, list(inputs))
[docs] def selectLines(self, *select):
if not (pow(2, len(select)) == len(self.inputs)):
raise Exception(
"ERROR: No. of Select lines are inconsistent with the inputs")
self.selects = list(select)
self._updateConnections(self.selects)
self.trigger()
[docs] def selectLine(self, index, value):
if index >= len(self.selects):
self.selects.append(value)
else:
self.selects[index] = value
if isinstance(value, Connector):
value.tap(self, 'input')
self.trigger()
[docs] def trigger(self):
if len(self.selects) == 0:
return
if not (len(self.inputs) > 1 and (len(self.inputs) & (len(self.inputs) - 1) == 0)):
raise Exception("ERROR: Number of inputs should be a power of 2")
bstr = ''
for i in self.selects:
if isinstance(i, Connector):
bstr = bstr + str(i.state)
else:
bstr = bstr + str(i)
try:
if isinstance(self.inputs[int(bstr, 2)], Connector):
self._updateResult(self.inputs[int(bstr, 2)].state)
else:
self._updateResult(self.inputs[int(bstr, 2)])
except IndexError:
raise Exception(
"Error: Select lines are inconsistent with Input lines")
if self.outputType:
self.outputConnector.trigger()
def __str__(self):
return self.buildStr("MUX")
[docs]class DEMUX(GATES):
"""
This class can be used to create DEMUX in your circuit. DEMUX is used to select
It takes single input and n select lines and decode the select lines into BCD form
base upon the input. In case of high input, it works as a decoder.
INPUT: Single Input, 1 or 0
OUTPUT: BCD form of select lines in case of high input, else low output
SELECT LINES: nth select line at nth index
Example:
>>> from BinPy import *
>>> demux = DEMUX(0) "DEMUX takes 1 input (digital or Connector)"
>>> demux.selectLines(0) "Put select Lines"
>>> demux.output()
[0, 0]
>>> demux.selectLine(0, 1) "Select line at index 0 is changed to 1"
>>> demux.output()
[0, 1]
"""
def __init__(self, *inputs):
if not (len(inputs) == 1):
raise Exception("ERROR: Input should be 0/1")
self.selects = []
GATES.__init__(self, list(inputs))
self.outputType = []
self.outputConnector = []
[docs] def selectLines(self, *select):
if not (len(select) != 0):
raise Exception(
"ERROR: Number of select lines should be greater than zero")
self.selects = list(select)
for i in range(pow(2, len(select))):
self.outputType.append(0)
self.outputConnector.append(None)
self._updateConnections(self.selects)
self.trigger()
[docs] def selectLine(self, index, value):
if index >= len(self.selects):
self.selects.append(value)
for i in range(len(self.outputType), pow(2, len(self.selects))):
self.outputType.append(0)
self.outputConnector.append(None)
else:
self.selects[index] = value
if isinstance(value, Connector):
value.tap(self, 'input')
self.trigger()
[docs] def trigger(self):
if len(self.selects) == 0:
return
out = []
for i in range(pow(2, len(self.selects))):
out.append(0)
bstr = ''
for i in self.selects:
if isinstance(i, Connector):
bstr = bstr + str(i.state)
else:
bstr = bstr + str(i)
if isinstance(self.inputs[0], Connector):
out[int(bstr, 2)] = self.inputs[0].state
self._updateResult(out)
else:
out[int(bstr, 2)] = self.inputs[0]
self._updateResult(out)
[docs] def setOutput(self, index, value):
if not isinstance(value, Connector):
raise Exception("ERROR: Expecting a Connector Class Object")
value.tap(self, 'output')
self.outputType[index] = 1
self.outputConnector[index] = value
self.trigger()
def _updateResult(self, value):
self.result = value
for i in range(len(value)):
if self.outputType[i] == 1:
self.outputConnector[i].state = value[i]
def __str__(self):
return self.buildStr("DEMUX")
[docs]class Decoder(GATES):
"""
This class can be used to create decoder in your circuit.
Input is taken as Binary String and returns the equivalent BCD form.
INPUT: n Binary inputs, nth input ant the nth index
OUTPUT: Gives equivalent BCD form
Example:
>>> decoder = Decoder(0) "Decoder with 1 input, 0"
>>> decoder.output()
[1, 0]
>>> decoder.setInputs(0, 1) "sets the new inputs to the decoder"
[0, 1, 0, 1]
"""
def __init__(self, *inputs):
if len(inputs) == 0:
raise Exception("ERROR: Input Length should be greater than zero")
GATES.__init__(self, list(inputs))
self.outputType = []
self.outputConnector = []
for i in range(pow(2, len(inputs))):
self.outputType.append(0)
self.outputConnector.append(None)
[docs] def trigger(self):
if isinstance(self.outputType, int):
return
out = []
for i in range(pow(2, len(self.inputs))):
out.append(0)
bstr = ''
for i in self.inputs:
if isinstance(i, Connector):
bstr = bstr + str(i.state)
else:
bstr = bstr + str(i)
out[int(bstr, 2)] = 1
self._updateResult(out)
[docs] def setOutput(self, index, value):
if not isinstance(value, Connector):
raise Exception("ERROR: Expecting a Connector Class Object")
value.tap(self, 'output')
self.outputType[index] = 1
self.outputConnector[index] = value
self.trigger()
def _updateResult(self, value):
self.result = value
for i in range(len(value)):
if self.outputType[i] == 1:
self.outputConnector[i].state = value[i]
def __str__(self):
return self.buildStr("Decoder")
[docs]class Encoder(GATES):
"""
This class can be used to create encoder in your circuit.
It converts the input BCD form to binary output.
It works as the inverse of the decoder
INPUT: Input in BCD form, length of input must me in power of 2
OUTPUT: Encoded Binary Form
Example:
>>> encoder = Encoder(0, 1) "Encoder with BCD input 01 "
>>> encoder.output() "Binary Form"
[1]
>>> encoder.setInputs(0, 0, 0, 1) "Sets the new inputs"
[1 , 1]
"""
def __init__(self, *inputs):
if not (len(inputs) > 1 and (len(inputs) & (len(inputs) - 1) == 0)):
raise Exception("ERROR: Number of inputs should be a power of 2")
if not (inputs.count(1) == 1 or list(x.state for x in
filter(lambda i: isinstance(i, Connector), inputs)).count(1) == 1):
raise Exception("Invalid Input")
GATES.__init__(self, list(inputs))
self.outputType = []
self.outputConnector = []
for i in range(int(math.log(len(self.inputs), 2))):
self.outputType.append(0)
self.outputConnector.append(None)
[docs] def trigger(self):
if isinstance(self.outputType, int):
return
if not (len(self.inputs) > 1 and (len(self.inputs) & (len(self.inputs) - 1) == 0)):
raise Exception("ERROR: Number of inputs should be a power of 2")
temp = self.inputs[:]
for i in range(len(temp)):
if isinstance(temp[i], Connector):
temp[i] = temp[i].state
bstr = bin(temp.index(1))[2:]
while len(bstr) < math.log(len(self.inputs), 2):
bstr = '0' + bstr
out = list(bstr)
out = map(int, out)
self._updateResult(list(out))
[docs] def setOutput(self, index, value):
if not isinstance(value, Connector):
raise Exception("ERROR: Expecting a Connector Class Object")
value.tap(self, 'output')
self.outputType[index] = 1
self.outputConnector[index] = value
self.trigger()
def _updateResult(self, value):
self.result = value
for i in range(len(value)):
if self.outputType[i] == 1:
self.outputConnector[i].state = value[i]
def __str__(self):
return self.buildStr("Encoder")