Logic Gates Circuit Simulation Workshop in Python

2021-03-01 19:26

阅读:721

标签:help   exit   creat   put   unit   under   npoi   open   alc   

Logic Gates circuit is the foundamental structure that build up the calculation and processing of a computer. It had been believed that with proper arrangement of logic gates, any computer could be built with an increase in complexity. This article would try to demonstrate how a logic circuit workshop could be implemented using Python.

 

1, Introduction

Before we begin, we need to understand the components of a logic gate circuit

技术图片

 

 The input button, which is where the power enters the circuit.

技术图片

 

 The output button, where the power should be released from the circuit.

技术图片

 

 The NOT gate, which converts 1 into 0, and 0 into 1.

技术图片

The AND gate, which would only allow current to flow through when both attachments are powered on.

技术图片

 

 The OR gate, which would allow current to flow through as long as one of the gates are powered on.

 

2, Method

In order to complete such task, tkinter was applied for drawing. Object of the three gates were first claimed, and then drawn on canvas. A class "gate" was first applied in order to control all applications on gates.

  1 class Gate(object):
  2     #initialization
  3     def __init__(self):
  4         self.inputGates=[]
  5         self.outputGates=[]
  6         self.inputVals=None
  7         self.inputValues = []
  8         self.outputValue=None
  9         self.maxInputGates=1
 10         self.transform()
 11     #create the list of inputValues
 12     def transform(self):
 13         if(self.inputVals == None):
 14             return []
 15         self.inputValues = []
 16         for (key,val) in self.inputVals.items():
 17             if((key,val) in self.inputValues):
 18                 continue
 19             self.inputValues += [(key,val)]
 20             
 21         pass
 22     #connect two gates
 23     def connectTo(self,gate):
 24         if(len(gate.inputGates)  gate.maxInputGates):
 25             if gate not in self.outputGates: 
 26                 self.outputGates.append(gate)
 27             if self not in gate.inputGates: 
 28                 gate.inputGates.append(self)
 29             if gate.inputVals == None: gate.inputVals = dict()
 30             gate.inputVals[self] = self.outputValue
 31             if type(self) == Output:
 32                 pass
 33         self.transform()
 34     #use input to decide output
 35     def inputToOutput(self):
 36         if self.inputVals!=None:
 37             self.outputValue=False
 38         elif self.inputVals==None:
 39             self.outputValue=None
 40             return
 41         if type(self) == Or: self.orGate()
 42         elif type(self) == And: self.andGate()            
 43         elif type(self) == Not:
 44             for key in self.inputVals:
 45                 self.outputValue = not self.inputVals[key]
 46         elif type(self) == Output or type(self) == Input: 
 47             for key in self.inputVals:
 48                 self.outputValue = self.inputVals[key]
 49         self.transform()
 50         return
 51     #Or type helper function
 52     def orGate(self):
 53         if len(self.inputVals)==2:
 54             for key in self.inputVals:
 55                 if self.inputVals[key]==True:
 56                     self.outputValue=True
 57                     break
 58             #None type is more priviledged than all types
 59             for key in self.inputVals:
 60                 if self.inputVals[key] == None:
 61                     self.outputValue = None
 62                     return
 63         else:
 64             self.outputValue=None
 65         self.transform()
 66     #And type helper function
 67     def andGate(self):
 68         if len(self.inputVals)==2:
 69             for key in self.inputVals:
 70                 if self.inputVals[key]==True: self.outputValue=True
 71                 else:
 72                     self.outputValue=False
 73                     break
 74             for key in self.inputVals:
 75                 if self.inputVals[key] == None:
 76                     self.outputValue = None
 77                     return
 78         else: self.outputValue=None
 79         self.transform()
 80     #set the input values
 81     def setInputValue(self,gate,TorF):
 82         try:
 83             if self.inputVals==None:
 84                 self.inputVals=dict()
 85             self.inputVals[gate]=TorF
 86             self.inputToOutput()#generate its output
 87             for index in range(len(self.outputGates)):
 88                 self.outputGates[index].setInputValue(self,self.outputValue)
 89         
 90             self.transform()
 91         except: return
 92     #return inputgates
 93     def getInputGates(self):
 94         self.transform()
 95         return self.inputGates
 96     #return maximum numbers of inputgates
 97     def getMaxInputGates(self):
 98         self.transform()
 99         return self.maxInputGates
100     #return outputgates
101     def getOutputGates(self):
102         self.transform()
103         return self.outputGates

 

After that, classes correcponding to different gates are declared and inherit the class of Gate.

 1 class Input(Gate):
 2     #initialization
 3     def __init__(self):
 4         self.inputGates=[]
 5         self.outputGates=[]
 6         self.inputVals=None
 7         self.outputValue=None
 8         self.inputValues = []
 9         self.maxInputGates=0
10         self.transform()
11 
12 class Output(Gate):
13     #all covered in Gate class
14     pass
15 
16 class And(Gate):
17     #initialization
18     def __init__(self):
19         self.inputGates=[]
20         self.outputGates=[]
21         self.inputVals=None
22         self.outputValue=None
23         self.inputValues = []
24         self.maxInputGates=2
25         self.transform()
26 
27 class Or(Gate):
28     #initialization
29     def __init__(self):
30         self.inputGates=[]
31         self.outputGates=[]
32         self.inputVals=None
33         self.outputValue=None
34         self.inputValues = []
35         self.maxInputGates=2
36         self.transform()
37 
38 class Not(Gate):
39     #initialization
40     def __init__(self):
41         self.inputGates=[]
42         self.outputGates=[]
43         self.inputVals=None
44         self.outputValue=None
45         self.inputValues = []
46         self.maxInputGates=1
47         self.transform()

 

After that, by importing tkinter, the drawing functions would be declared.

 

  1 from tkinter import *
  2 #initialization
  3 def init(data):
  4     data.buttonDict=dict()
  5     data.button=None
  6     data.r=5 #r for radius, simplified
  7     data.unit=10
  8     data.input=0
  9     data.errorBound=10
 10     data.threadResidue=6
 11     data.inpointList=[]
 12     data.outpointList=[]
 13     data.lineList=[]
 14     data.connectLine=[]
 15     data.inputButtons=[]
 16     data.power=False
 17     data.save=False
 18     data.path="circuit.txt"
 19     data.contents=""
 20     data.read=""
 21     data.location=[]
 22     data.gate=[]
 23 #draw the Gate
 24 def drawGate(canvas,data):#draw gates based on their names
 25     d,r,l=data.unit, data.r, data.threadResidue
 26     for key in data.buttonDict:
 27         for i in range(len(data.buttonDict[key])):
 28             x=int(data.buttonDict[key][i][0])
 29             y=int(data.buttonDict[key][i][1])
 30             if key=="input":
 31                 canvas.create_oval(x-r,y-r,x+r,y+r,fill="black",outline="red")
 32                 canvas.create_line(x+r,y,x+r+l,y,fill="red")
 33             elif key=="output":
 34                 canvas.create_oval(x-r,y-r,x+r,y+r,fill="black",outline="green")
 35                 canvas.create_line(x-r-l,y,x-r,y,fill="green")
 36             elif key=="and":
 37                 canvas.create_rectangle(x-d,y-d,x+d,y+d,fill="white")
 38                 canvas.create_oval(x,y-d,x+2*d,y+d,fill="white")
 39                 canvas.create_rectangle(x-d+1,y-d+1,x+d-1,y+d-1,fill="white",
 40                     outline="white")
 41                 canvas.create_line(x-d-l,y-d+r,x-d,y-d+r, fill="green")
 42                 canvas.create_line(x-d-l,y+d-r,x-d,y+d-r, fill="green")
 43                 canvas.create_line(x+2*d,y,x+2*d+l,y,fill="red")
 44 #draw the other gate
 45 def drawGateAdd(canvas,data):
 46     d,r,l=data.unit, data.r, data.threadResidue
 47     for key in data.buttonDict:
 48         for i in range(len(data.buttonDict[key])):
 49             x=int(data.buttonDict[key][i][0])
 50             y=int(data.buttonDict[key][i][1])
 51             if key=="or":
 52                  canvas.create_polygon(x-d-r,y-d,x-d-r+l/2,y-d+l,x-d-r+l/2,
 53             y+d-l,x-d-r,y+d,x,y+d, x+d+r,y,x,y-d,fill="white",outline="black")
 54                  canvas.create_line(x-d-r-l/2,y-d+l,x-d-r+l/2,y-d+l,
 55                     fill="green")
 56                  canvas.create_line(x-d-r-l/2,y+d-l,x-d-r+l/2,y+d-l, 
 57                     fill="green")
 58                  canvas.create_line(x+d+r,y,x+d+r+l,y, fill="red")
 59             elif key=="not":
 60                 canvas.create_line(x-l-d,y,x+d+2*r,y)
 61                 canvas.create_polygon(x-d,y-d/2,x-d,y+d/2,x+d,y,fill="white",
 62                     outline="black")
 63                 canvas.create_oval(x+d,y-2,x+d+r-1,y+2,fill="white",
 64                     outline="black")
 65 
 66 #draw the power input session
 67 def drawPowerInput(canvas,data):
 68     #change the color of the input button when it has power
 69     for index in range(len(data.inputButtons)):
 70         if data.inputButtons[index][2].outputValue==True:
 71             x=int(data.inputButtons[index][0])
 72             y=int(data.inputButtons[index][1])
 73             r=data.r
 74             canvas.create_oval(x-r,y-r,x+r,y+r,fill="red",width=0)
 75 
 76 #draw the power lines
 77 def drawPowerLine(canvas,data):
 78     for index in range(len(data.lineList)):
 79         xL=int(data.lineList[index][0][0])
 80         yL=int(data.lineList[index][0][1])
 81         xR=int(data.lineList[index][1][0])
 82         yR=int(data.lineList[index][1][1])
 83         if data.lineList[index][0][2].outputValue==True:
 84             canvas.create_line(xL,yL,xR,yR,fill="red")
 85         else:
 86             canvas.create_line(xL,yL,xR,yR,fill="black")
 87 
 88 
 89 #draw top buttons and left buttons (And)
 90 def drawButtonAnd(canvas,data):
 91     r,l=data.r,data.threadResidue
 92     a,b,c,d,e=50,100,200,data.unit,data.r
 93     for index in range(1,r+1):
 94         canvas.create_rectangle(index*b,0,(index+1)*b,b,fill="white")
 95     drawSave(canvas,data)
 96     if data.power==True:
 97         canvas.create_rectangle(2*c+e,e,2*c+b-e,b-e,outline="gray",width=d)
 98     canvas.create_text(a+b,a,text="Save",font="Harrington 18")
 99     canvas.create_text(a+c,a,text="Load",font="Harrington 18")
100     canvas.create_text(a+b+c,a,text="Clear",font="Harrington 18")
101     canvas.create_text(a+2*c,a,text="Power",font="Harrington 18")
102     canvas.create_text(a+2*c+b,a-d,text="Tianyuan Du",font="Harrington 12 bold")
103     canvas.create_text(a+2*c+b,a+d,text="tianyuad",font="Harrington 12")
104 
105 #draw left button (Or)
106 def drawButtonOr(canvas,data):
107     r,l=data.r,data.threadResidue
108     a,b,c,d=50,100,200,data.unit
109     canvas.create_rectangle(b+l,b+l,2*c+2*b,2*c+2*b,fill="wheat",outline="blue")
110     canvas.create_line(b,b,b,2*b+2*c)
111     canvas.create_line(0,b,b,b)
112     canvas.create_oval(a-r,a+b-r,a+r,a+b+r,fill="black",outline="red")
113     canvas.create_line(a+r,a+b,a+r+l,a+b,fill="red",width=2)
114     canvas.create_text(a,a+b+2*d,text="input", font="Time 12 bold")
115     canvas.create_line(0,c,b,c)
116     canvas.create_oval(a-r,a+c-r,a+r,a+c+r,fill="black", outline="green")
117     canvas.create_line(a-r-l,a+c,a-r,a+c,fill="green",width=2)
118     canvas.create_text(a,a+c+2*d,text="output", font="Time 12 bold")
119     canvas.create_line(0,b+c,b,b+c)
120     canvas.create_line(a-l-d,a+b+c,a+d+2*r,a+b+c)
121     canvas.create_polygon(a-d,a+b+c-d/2,a-d,a+b+c+d/2,a+d,a+b+c,fill="white",
122         outline="black")
123     canvas.create_oval(a+d,a+b+c-2,a+d+4,a+b+c+2,fill="white", outline="black")
124     canvas.create_text(a,a+b+c+2*d,text="not", font="Time 12 bold")
125     canvas.create_line(0,2*c,b,2*c)
126 
127 #draw left button (Not)
128 def drawButtonNot(canvas,data):
129     r,l=data.r,data.threadResidue
130     a,b,c,d=50,100,200,data.unit
131     canvas.create_rectangle(a-d,a+2*c-d,a+d,a+2*c+d, fill="white")
132     canvas.create_oval(a,a+2*c-d,a+2*d,a+2*c+d,fill="white")
133     canvas.create_rectangle(a-d+1,a+2*c-d+1,a+d-1,a+2*c+d-1, fill="white",
134         outline="white")
135     canvas.create_line(a-d-l,a+2*c-d+r,a-d,a+2*c-d+r,fill="green")
136     canvas.create_line(a-d-l,a+2*c+d-r,a-d,a+2*c+d-r,fill="green")
137     canvas.create_line(a+2*d,a+2*c,a+2*d+l,a+2*c,fill="red")
138     canvas.create_text(a,a+2*c+2*d,text="and", font="Time 12 bold")
139     canvas.create_line(0,2*c+b,b,2*c+b)
140     canvas.create_polygon(a-d-r,a+b+2*c-d,a-d-r+l/2,a+b+2*c-d+l,a-d-r+l/2,
141         a+b+2*c+d-l,a-d-r,a+b+2*c+d,a,a+b+2*c+d,a+d+r,a+b+2*c,a,a+b+2*c-d,
142         fill="white",outline="black")
143     canvas.create_line(a-d-r-l/2,a+b+2*c-d+l,a-d-r+l/2,a+b+2*c-d+l,fill="green")
144     canvas.create_line(a-d-r-l/2,a+b+2*c+d-l,a-d-r+l/2,a+b+2*c+d-l,fill="green")
145     canvas.create_line(a+d+r,a+b+2*c,a+d+r+l,a+b+2*c, fill="red")
146     canvas.create_text(a,a+b+2*c+2*d,text="or", font="Time 12 bold")

Given the static codes are implemented, the interface control codes could take advantage of them.

  1 #draw phenomenon when buttons are pressed
  2 def drawButtonPressed(canvas,data):
  3     r,l=data.r,data.threadResidue
  4     a,b,c,d=50,100,200,data.unit
  5     if data.button=="input":canvas.create_rectangle(d/2,b+d/2,b-d/2,c-d/2,
  6                                     fill="white",outline="gray",width=d)
  7     elif data.button=="output": canvas.create_rectangle(d/2,c+d/2,b-d/2,b+c-d/2,
  8                                     fill="white",outline="gray",width=d)
  9     elif data.button=="not": canvas.create_rectangle(d/2,b+c+d/2,b-d/2,2*c-d/2,
 10                                     fill="white",outline="gray",width=d)
 11     elif data.button=="and": canvas.create_rectangle(d/2,2*c+d/2,b-d/2,2*c+b-d/2
 12                                 ,fill="white",outline="gray",width=d)
 13     elif data.button=="or": canvas.create_rectangle(d/2,2*c+b+d/2,b-d/2,
 14                                 2*c+2*b-d/2,fill="white",outline="gray",width=d)
 15     
 16 #draw if press Save
 17 def drawSave(canvas,data):
 18     a,b,c,d=50,100,200,data.unit
 19     if data.save==True:
 20         canvas.create_rectangle(b+d/2,d/2,c-d/2,b-d/2,fill="white",
 21             outline="gray",width=d)
 22         
 23 #helper function of save pressed
 24 def drawSaveAdd(canvas,data):
 25     if data.save==True:
 26         a,b,c=50,100,200
 27         canvas.create_text(a+b+c,a+b+c,text="Saved!!", font="Time 40 bold")
 28 
 29 #location of buttons
 30 def buttonPoint(data,x,y):
 31     #set r,l,d to calculate their position in a small area
 32     r,l,d=data.r,data.threadResidue,data.unit
 33     #append four elements in the list
 34     if data.button=="input":
 35         input1=Input()
 36         data.outpointList.append([x+r+l,y,input1,"input"])
 37         data.inputButtons.append([x,y,input1,"input"])
 38     elif data.button=="output": 
 39         data.inpointList.append([x-r-l,y,Output(),"output"])
 40     elif data.button=="and":
 41         and1=And()
 42         data.inpointList.append([x-d-l,y-d+r,and1,"and"])
 43         data.inpointList.append([x-d-l,y+d-r,and1,"and"])
 44         data.outpointList.append([x+2*d+l,y,and1,"and"])
 45     else: buttonPointAdd(data,x,y)
 46 #other buttons stored
 47 def buttonPointAdd(data,x,y):
 48     r,l,d=data.r,data.threadResidue,data.unit
 49     if data.button=="or":
 50         or1=Or()
 51         data.inpointList.append([x-d-r-l/2,y-d+l,or1,"or"])
 52         data.inpointList.append([x-d-r-l/2,y+d-l,or1,"or"])
 53         data.outpointList.append([x+d+r+l,y,or1,"or"])
 54     elif data.button=="not":
 55         not1=Not()
 56         data.inpointList.append([x-l-d,y,not1,"not"])
 57         data.outpointList.append([x+d+2*r,y,not1,"not"])
 58 #helper function gets distance
 59 def distance(a,b):
 60     return ((a[0]-b[0])**2+(a[1]-b[1])**2)**(0.5)
 61 
 62 #mouse pressed to select gates
 63 def mousePressedLeftButton(event,data):
 64     a,b,c,d=50,100,200,data.unit
 65     if event.y >b and event.yc:
 66         data.button = "input"
 67     elif event.y> c and event.yc:
 68         data.button = "output"
 69     elif event.y>b+c and event.y c:
 70         data.button = "not"
 71     elif event.y>2*c and event.yb:
 72         data.button="and"
 73     elif event.y>2*c+b and event.yb:
 74         data.button="or"
 75 
 76 #mouse pressed to set gates
 77 def mousePressedSetGates(event,data):
 78     if data.button in data.buttonDict:
 79         data.buttonDict[data.button].append((event.x, event.y))
 80     else:
 81         data.buttonDict[data.button]=[(event.x,event.y)]
 82     buttonPoint(data,event.x,event.y)
 83     data.button=None
 84 
 85 #line connection
 86 def connectLine(event,data):
 87     a,b,c,d=50,100,200,data.unit
 88     minDistance=b*data.unit
 89     if data.connectLine==[]:          
 90         for point in data.outpointList:
 91             if distance([(point[0]),(point[1])],[event.x,event.y])minDistance:
 92                 minDistance=distance([(point[0]),(point[1])],[event.x,event.y])
 93                 minPoint=point
 94         if minDistancedata.errorBound: data.connectLine.append(minPoint)
 95     else:
 96         for point in data.inpointList:
 97             if distance(point,[event.x,event.y])minDistance:
 98                 minDistance=distance(point,[event.x,event.y])
 99                 minPoint=point
100         if minDistancedata.errorBound:
101             data.connectLine.append(minPoint)
102             data.inpointList.remove(minPoint)
103             data.lineList.append(data.connectLine)
104             data.connectLine[0][2].connectTo(data.connectLine[1][2])
105             data.connectLine=[]
106             
107 #switch the power state as user click power.
108 def powerSwitch(event,data):
109     if data.power==False:#not gate works
110         for index in range(len(data.inputButtons)):
111             data.inputButtons[index][2].setInputValue(None,False)
112     else:
113         for index in range(len(data.inpointList)):
114             data.inpointList[index][2].inputVals=None
115             data.inpointList[index][2].outputValue=None
116         for index in range(len(data.outpointList)):
117             data.outpointList[index][2].inputVals=None
118             data.outpointList[index][2].outputValue=None
119     data.power= not data.power #switch the power state
120 
121 #control when power is get
122 def powerGet(event,data):
123     b=100
124     minDistance=b*data.unit
125     for index in range(len(data.inputButtons)): 
126         xi,yi=int(data.inputButtons[index][0]),int(data.inputButtons[index][1])
127         if distance([xi,yi],[event.x,event.y])minDistance:
128             minDistance=distance([xi,yi],[event.x,event.y])
129             minPoint=data.inputButtons[index]
130     if minDistancedata.errorBound:
131         minPoint[2].setInputValue(None,not minPoint[2].outputValue)
132 #control when mouse is pressed
133 def mousePressed(event, data):
134     a,b,c,d=50,100,200,data.unit
135     if event.x and data.power==False: mousePressedLeftButton(event,data)  
136     elif event.x>b and event.xand event.y>b and data.power==False:
137         if data.button!=None: mousePressedSetGates(event,data)
138         else:connectLine(event,data)
139     elif event.x>b+c and event.xand event.yb: 
140         clear(data)
141     elif event.x>2*c and event.xand event.yb: 
142         powerSwitch(event,data)
143     else:
144         if data.power==True:
145             #when power is on
146             if event.x>b and event.xand event.y>b:
147                 powerGet(event,data)
148         elif event.x>c and event.xand event.yb: 
149             init(data)
150             load(data)
151         elif event.x>b and event.xand event.yb: 
152             printFile(data,data.path,data.contents)
153             printFile(data,data.path,data.contents)

 

When application functions are set, there could be functions that deal with the save/delete, which are loading functions.

  1 #clear out the data
  2 def clear(data):
  3     init(data)
  4 
  5 #load the files
  6 def readFile(data):
  7     with open(data.path, "rt") as f:
  8         data.read=f.read()
  9         return
 10 #load data
 11 def load(data):
 12     readFile(data)
 13     loadinput(data)
 14     loadInpoint(data)
 15     loadOutpointList(data)
 16     loadlineList(data)
 17     loaddict(data)
 18 #helper function gets the gate
 19 def getGate(name):
 20     gate = None
 21     if(name == "input"):
 22         gate = Input()
 23     elif(name == "output"):
 24         gate = Output()
 25     elif(name == "and"):
 26         gate = And()
 27     elif(name == "or"):
 28         gate = Or()
 29     elif(name == "not"):
 30         gate = Not()#create a new object in the list data.gate
 31     return gate
 32 #load input
 33 def loadinput(data):
 34     length=len("#below are inputButtons\n")
 35     startPoint=data.read.find("#below are inputButtons\n")+length
 36     endPoint=data.read.find("#below are inpointList")
 37     inputStr=data.read[startPoint:endPoint]
 38     for lines in inputStr.splitlines():
 39         inputs=lines.split(",")
 40         inputs[0],inputs[1]=int(inputs[0]),int(inputs[1])
 41         if inputs[2] not in data.location:
 42             data.location.append(inputs[2])
 43             k=(inputs[-1][1:])#inputs[-1][1:] is actually the "input"
 44             gate = getGate(k)
 45             data.gate.append(gate)
 46         index=data.location.index(inputs[2])
 47         inputs[2]=data.gate[index]
 48         data.inputButtons.append(inputs)#recover the inputButton list
 49 #below are similar to the first function
 50 def loadInpoint(data):
 51     length=len("#below are inpointList\n")
 52     startPoint=data.read.find("#below are inpointList\n")+length
 53


评论


亲,登录后才可以留言!