-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlogic_sim.py
187 lines (152 loc) · 5.59 KB
/
logic_sim.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
from itertools import product
import pandas as pd
class notgate:
"""custom class for NOT gate node"""
def __init__(self, a, y):
self.a = a
self.y = y
def __repr__(self):
return "NOT Gate"
def ready(self, nets):
"""check if inputs are available"""
return (nets[self.a] != 'u')
def evaluate(self, nets):
"""evaluate NOT gate node"""
if nets[self.a] == 1:
nets[self.y] = 0
else:
nets[self.y] = 1
class andgate:
"""custom class for AND gate node"""
def __init__(self, a, b, y):
self.a = a
self.b = b
self.y = y
def __repr__(self):
return "AND Gate"
def ready(self, nets):
"""check if inputs are available"""
return (nets[self.a] != 'u' and nets[self.b] != 'u')
def evaluate(self, nets):
"""evaluate AND gate node"""
if(nets[self.a] and nets[self.b]):
nets[self.y] = 1
else:
nets[self.y] = 0
class orgate:
"""custom class for OR gate node"""
def __init__(self, a, b, y):
self.a = a
self.b = b
self.y = y
def __repr__(self):
return "OR Gate"
def ready(self, nets):
"""check if inputs are available"""
return (nets[self.a] != 'u' and nets[self.b] != 'u')
def evaluate(self, nets):
"""evaluate OR gate node"""
if(nets[self.a] or nets[self.b]):
nets[self.y] = 1
else:
nets[self.y] = 0
def get_input_output_nodes(filename):
"""returns the input and output nodes for the circuit netlist in ./filename as a tuple"""
inputs = []
outputs = []
with open(filename, 'r') as t:
gate_number = 0
m = [x.split() for x in t.readlines()]
for i in m:
if(len(i) == 0):
pass
elif(i[0] == 'inp'):
inputs = i[1:]
elif(i[0] == 'outp'):
outputs = i[1:]
else:
pass
return (inputs, outputs)
def simulate(filename, testvector):
"""simulates the circuit stored at ./filename for an input of testvector and returns output vector"""
inputs = []
outputs = []
nets = {}
gates = {}
# we will store all nets/nodes in hashable nets for fast lookup (make sure the nets are named differently and are not and, or, inv as gates named that way)
# we will store all gates hashed by increasing numbers from 0 to no of gates - 1 for fast lookup
with open(filename, 'r') as t:
gate_number = 0
m = [x.split() for x in t.readlines()]
for i in m:
if(len(i) == 0):
pass
elif(i[0] == 'inp'):
inputs = i[1:]
elif(i[0] == 'outp'):
outputs = i[1:]
elif(i[0] == 'and'):
for j in range(1,4):
if(i[j] not in nets.keys()):
nets[i[j]] = 'u'
# instantiate the gate
gates[gate_number] = andgate(i[1], i[2], i[3])
gate_number += 1
elif(i[0] == 'or'):
for j in range(1,4):
if(i[j] not in nets.keys()):
nets[i[j]] = 'u'
# instantiate the gate
gates[gate_number] = orgate(i[1], i[2], i[3])
gate_number += 1
elif(i[0] == 'inv'):
for j in range(1,3):
if(i[j] not in nets.keys()):
nets[i[j]] = 'u'
# instantiate the gate
gates[gate_number] = notgate(i[1], i[2])
gate_number += 1
else:
pass
# assign the testvector to input nets
for i in range(len(testvector)):
nets[inputs[i]] = testvector[i]
# create a list of hash_keys of all gates which are yet to be simulated
left_over_gates = list(range(len(gates.keys())))
while(len(left_over_gates) > 0):
# keep performing until no left over gates
completed = []
for i in left_over_gates:
#check if a gate is ready to be evaluated if so add it to completed
if(gates[i].ready(nets)):
completed.append(i)
for i in completed:
# evaluate all gates in completed and remove them from left over gates
gates[i].evaluate(nets)
left_over_gates.remove(i)
output_testvector = []
for i in outputs:
# perform a hash lookup for the output nodes to get the output corresponding to that net
output_testvector.append(nets[i])
#return the output vector
return output_testvector
if __name__ == '__main__':
inputs, outputs = get_input_output_nodes('circuit.txt')
# make a dict to store truth table
truthtable = {}
for j in range(len(inputs)):
truthtable[inputs[j]] = []
for j in range(len(outputs)):
truthtable[outputs[j]] = []
# list performs cartesian product no of input number of times to provide inputs of generic n variable truth table in order
testvectors = list(product((0, 1), repeat=len(inputs)))
for i in testvectors:
for j in range(len(i)):
truthtable[inputs[j]].append(i[j])
# simulate the ith truthtable entry
v = simulate('circuit.txt', i)
for j in range(len(v)):
truthtable[outputs[j]].append(v[j])
# use pandas to convert to csv and store
truthtable = pd.DataFrame(truthtable)
truthtable.to_csv("truthtable.csv", index=False)