"""
Contains
========
* GATES(Base class for all the gates)
* MIGATES(Base class for multiple input gates inherits GATES)
* AND
* OR
* NOT
* XOR
* XNOR
* NAND
* NOR
"""
from BinPy.Gates.connector import *
[docs]class GATES:
'''
Base Class implementing all common functions used by Logic Gates
'''
def __init__(self, inputs):
# Clean Connections before updating new connections
self.history_active = 0 # Ignore history for first computation
self.outputType = 0 # 1->output goes to a connector class
self.result = None # To store the result
self.outputConnector = None # Valid only if outputType = 1
self.inputs = inputs[:] # Set the inputs
self.history_inputs = [] # Save a copy of the inputs
self._updateConnections(self.inputs)
self._updateHistory()
self.trigger()
# Any change in the input will trigger change in the
# output
def _updateConnections(self, inputs):
for i in inputs:
if isinstance(i, Connector):
i.tap(self, 'input')
def _updateResult(self, value):
if value is None:
self.result = None
else:
self.result = int(value) # Set True or False
if self.outputType == 1:
self.outputConnector.state = self.result
def _updateHistory(self):
for i in range(len(self.inputs)):
if isinstance(self.inputs[i], Connector):
val1 = self.inputs[i].state
else:
val1 = self.inputs[i]
if len(self.history_inputs) <= i:
self.history_inputs.append(val1)
else:
self.history_inputs[i] = val1
[docs] def setOutput(self, connector):
"""
This method sets the output of the gate. It connects
the passed connector to its output.
"""
if not isinstance(connector, Connector):
raise Exception("ERROR: Expecting a Connector Class Object")
connector.tap(self, 'output')
self.outputType = 1
self.outputConnector = connector
self.history_active = 0
self.trigger()
[docs] def output(self):
"""
This methods returns the output of the gate.
"""
self.trigger()
return self.result
def __repr__(self):
'''
Simple way to do 'print g', where g would be an instance of any gate
class. Functions returns the result of self.output() as a string.
'''
return str(self.output())
[docs] def buildStr(self, gate_name):
'''
Returns a string representation of a gate, where gate_name is the class
name For example, for an AND gate with two inputs the resulting string
would be: 'AND Gate; Output: 0; Inputs: [0, 1];'
'''
return gate_name + " Gate; Output: " + \
str(self.output()) + "; Inputs: " + \
str(self.getInputStates()) + ";"
def _compareHistory(self):
if self.history_active == 1: # Only check history if it is active
for i in range(len(self.inputs)):
if isinstance(self.inputs[i], Connector):
val1 = self.inputs[i].state
else:
val1 = self.inputs[i]
if i >= len(self.history_inputs) or self.history_inputs[i]\
!= val1:
return True
return False
return True
[docs]class MIGATES(GATES):
"""
This class makes GATES compatible with multiple inputs.
"""
def __init__(self, *inputs):
if len(inputs) < 2:
raise Exception(
"ERROR: Too few inputs given. Needs at least 2 or\
more inputs.")
GATES.__init__(self, list(inputs))
[docs]class AND(MIGATES):
"""
This class implements AND gate
Examples
========
>>> from BinPy import *
>>> gate = AND(0, 1)
>>> gate.output()
0
>>> gate.setInputs(1, 1, 1, 1)
>>> gate.output()
1
>>> conn = Connector()
>>> gate.setOutput(conn)
>>> gate2 = AND(conn, 1)
>>> gate2.output()
1
"""
def __init__(self, *inputs):
MIGATES.__init__(self, *inputs)
[docs] def trigger(self):
if self._compareHistory():
self.history_active = 1
self._updateResult(True)
self._updateHistory() # Update the inputs after a computation
val = True
for i in self.inputs:
if (isinstance(i, Connector)):
val = val and i.state
elif (isinstance(i, GATES)):
val = val and i.output()
else:
val = val and i
self._updateResult(val)
if self.outputType:
self.outputConnector.trigger()
def __str__(self):
return self.buildStr("AND")
[docs]class OR(MIGATES):
"""
This class implements OR gate
Examples
========
>>> from BinPy import *
>>> gate = OR(0, 1)
>>> gate.output()
1
>>> gate.setInputs(0, 0, 0, 0)
>>> gate.output()
0
>>> conn = Connector()
>>> gate.setOutput(conn)
>>> gate2 = AND(conn, 1)
>>> gate2.output()
0
"""
def __init__(self, *inputs):
MIGATES.__init__(self, *inputs)
[docs] def trigger(self):
if self._compareHistory():
self.history_active = 1
self._updateResult(False)
self._updateHistory() # Update the inputs after a computation
val = False
for i in self.inputs:
if (isinstance(i, Connector)):
val = val or i.state
elif (isinstance(i, GATES)):
val = val or i.output()
else:
val = val or i
self._updateResult(val)
if self.outputType:
self.outputConnector.trigger()
def __str__(self):
return self.buildStr("OR")
[docs]class NOT(GATES):
"""
This class implements NOT gate
Examples
========
>>> from BinPy import *
>>> gate = NOT(0)
>>> gate.output()
1
>>> conn = Connector()
>>> gate.setOutput(conn)
>>> gate2 = AND(conn, 1)
>>> gate2.output()
1
"""
def __init__(self, *inputs):
if len(inputs) != 1:
raise Exception("ERROR: NOT Gates takes only one input")
else:
GATES.__init__(self, list(inputs))
[docs] def trigger(self):
if self._compareHistory():
self.history_active = 1
self._updateHistory() # Update the inputs after a computation
if (isinstance(self.inputs[0], Connector)):
self._updateResult(not self.inputs[0].state)
elif (isinstance(self.inputs[0], GATES)):
self._updateResult(not self.inputs[0].output())
else:
self._updateResult(not self.inputs[0])
if self.outputType == 1:
self.outputConnector.trigger()
def __str__(self):
return self.buildStr("NOT")
[docs]class XOR(MIGATES):
"""
This class implements XOR gate
Examples
========
>>> from BinPy import *
>>> gate = XOR(0, 1)
>>> gate.output()
1
>>> gate.setInputs(1, 0, 1, 0)
>>> gate.output()
0
>>> conn = Connector()
>>> gate.setOutput(conn)
>>> gate2 = AND(conn, 1)
>>> gate2.output()
0
"""
def __init__(self, *inputs):
MIGATES.__init__(self, *inputs)
[docs] def trigger(self):
if self._compareHistory():
self.history_active = 1
self._updateResult(True)
self._updateHistory() # Update the inputs after a computation
temp = 1
for i in self.inputs:
if isinstance(i, Connector):
val = i.state
elif isinstance(i, GATES):
val = i.output()
else:
val = i
temp = (temp and not val) or (not temp and val)
temp = (temp and not 1) or (not temp and 1)
self._updateResult(temp)
if self.outputType:
self.outputConnector.trigger()
def __str__(self):
return self.buildStr("XOR")
[docs]class XNOR(MIGATES):
"""
This class implements XNOR gate
Examples
========
>>> from BinPy import *
>>> gate = XNOR(0, 1)
>>> gate.output()
0
>>> gate.setInputs(1, 0, 1, 0)
>>> gate.output()
1
>>> conn = Connector()
>>> gate.setOutput(conn)
>>> gate2 = AND(conn, 1)
>>> gate2.output()
1
"""
def __init__(self, *inputs):
MIGATES.__init__(self, *inputs)
[docs] def trigger(self):
if self._compareHistory():
self.history_active = 1
self._updateResult(True)
self._updateHistory() # Update the inputs after a computation
temp = 1
for i in self.inputs:
if (isinstance(i, Connector)):
val = i.state
elif isinstance(i, GATES):
val = i.output()
else:
val = i
temp = (temp and not val) or (not temp and val)
temp = (temp and not 1) or (not temp and 1)
self._updateResult(not temp)
if self.outputType:
self.outputConnector.trigger()
def __str__(self):
return self.buildStr("XNOR")
[docs]class NAND(MIGATES):
"""
This class implements NAND gate
Examples
========
>>> from BinPy import *
>>> gate = NAND(0, 1)
>>> gate.output()
1
"""
def __init__(self, *inputs):
MIGATES.__init__(self, *inputs)
[docs] def trigger(self):
if self._compareHistory():
self.history_active = 1
self._updateResult(False)
self._updateHistory() # Update the inputs after a computation
val = True
for i in self.inputs:
if (isinstance(i, Connector)):
val = val and i.state
elif (isinstance(i, GATES)):
val = val and i.output()
else:
val = val and i
self._updateResult(not val)
if self.outputType:
self.outputConnector.trigger()
def __str__(self):
return self.buildStr("NAND")
[docs]class NOR(MIGATES):
"""
This class implements NOR gate
Examples
========
>>> from BinPy import *
>>> gate = NOR(0, 1)
>>> gate.output()
0
"""
def __init__(self, *inputs):
MIGATES.__init__(self, *inputs)
[docs] def trigger(self):
if self._compareHistory():
self.history_active = 1
self._updateResult(True)
self._updateHistory() # Update the inputs after a computation
val = False
for i in self.inputs:
if (isinstance(i, Connector)):
val = val or i.state
elif (isinstance(i, GATES)):
val = val or i.output()
else:
val = val or i
self._updateResult(not val)
if self.outputType:
self.outputConnector.trigger()
def __str__(self):
return self.buildStr("NOR")