Skip to content

Commit 3e809fd

Browse files
committed
Formal verifier supported algebra operator (but it has trial verision yet.)
1 parent 278a6da commit 3e809fd

File tree

3 files changed

+102
-27
lines changed

3 files changed

+102
-27
lines changed

pyverilog_toolbox/testcode/fv_test.v

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module TOP(CLK);
22
input CLK;
3-
reg A,B,C,D,E,F,G;
3+
reg A,B,C,D,E,F,G,H;
44
reg [2:0] multi;
55

66
always @(posedge CLK) begin
@@ -26,6 +26,9 @@ module TOP(CLK);
2626
always @(posedge CLK) begin
2727
G <= &multi[1:0];
2828
end
29+
always @(posedge CLK) begin
30+
H <= F+G;
31+
end
2932

3033
endmodule
3134

pyverilog_toolbox/testcode/test_ra.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,7 @@ def test_comb_loop4(self):
173173
def test_formal_verifier(self):
174174
if sys.version_info[0] == 2:
175175
fv = FormalVerifier("../testcode/fv_test.v")
176-
t_table = fv.calc_truth_table('TOP.G')
177-
fv.write_back_DFmethods()
176+
t_table = fv._calc_truth_table('TOP.G')
178177
self.assertEqual(t_table["['TOP_multi__0__: False', 'TOP_multi__1__: False', 'TOP_multi__2__: False']"],
179178
False)
180179
self.assertEqual(t_table["['TOP_multi__0__: False', 'TOP_multi__1__: False', 'TOP_multi__2__: True']"],
@@ -191,6 +190,9 @@ def test_formal_verifier(self):
191190
True)
192191
self.assertEqual(t_table["['TOP_multi__0__: True', 'TOP_multi__1__: True', 'TOP_multi__2__: True']"],
193192
True)
193+
t_table = fv.calc_truth_table('TOP.H')
194+
self.assertEqual(str(t_table["['TOP_F: False', 'TOP_G: False']"]),
195+
"TOP_F_ + TOP_G_")
194196

195197
if __name__ == '__main__':
196198
unittest.main()

pyverilog_toolbox/verify_tool/formal_verifier.py

Lines changed: 94 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,35 @@ class FormalVerifier(dataflow_facade):
2525

2626
def __init__(self, code_file_name, topmodule=''):
2727
dataflow_facade.__init__(self, code_file_name, topmodule=topmodule)
28+
t_manager = term_manager()
29+
t_manager.set_scope_dict(self.binds.scope_dict)
30+
t_manager.set_terms(self.binds._terms)
2831

2932
DFBranch.tocode_org = MethodType(DFBranch.tocode, None, DFBranch)
30-
DFBranch.tocode = MethodType(DFBranch_tocode_for_sympy, None, DFBranch)
33+
DFBranch.tocode = MethodType(DFBranch_tocode, None, DFBranch)
3134
DFOperator.tocode_org = MethodType(DFOperator.tocode, None, DFOperator)
32-
DFOperator.tocode = MethodType(DFOperator_tocode_for_sympy, None, DFOperator)
35+
DFOperator.tocode = MethodType(DFOperator_tocode, None, DFOperator)
3336
DFOperator.is_reduction = MethodType(DFOperator_is_reduction, None, DFOperator)
34-
DFTerminal.scope_dict = self.binds.scope_dict
35-
DFTerminal.terms = self.binds._terms
36-
DFTerminal.get_bind = MethodType(DFTerminal_get_terms, None, DFTerminal)
37+
DFOperator.is_algebra = MethodType(DFOperator_is_algebra, None, DFOperator)
38+
DFTerminal.tocode_org = MethodType(DFTerminal.tocode, None, DFTerminal)
39+
DFTerminal.tocode = MethodType(DFTerminal_tocode, None, DFTerminal)
3740

3841
def write_back_DFmethods(self):
42+
DFTerminal.tocode = MethodType(DFTerminal.tocode_org, None, DFTerminal)
3943
DFBranch.tocode = MethodType(DFBranch.tocode_org, None, DFBranch)
4044
DFOperator.tocode = MethodType(DFOperator.tocode_org, None, DFOperator)
4145
del DFOperator.tocode_org
4246
del DFOperator.is_reduction
43-
del DFTerminal.scope_dict
44-
del DFTerminal.terms
45-
del DFTerminal.get_bind
47+
del DFOperator.is_algebra
4648

4749
def calc_truth_table(self, var_name):
50+
try:
51+
truth_table = self._calc_truth_table(var_name)
52+
finally:
53+
self.write_back_DFmethods()
54+
return truth_table
55+
56+
def _calc_truth_table(self, var_name):
4857
"""[FUNCTIONS]
4958
"""
5059
for tv, tk, bvi, bit, term_lsb in self.binds.walk_reg_each_bit():
@@ -64,12 +73,22 @@ def calc_truth_table(self, var_name):
6473
ns[symbol_name] = Symbol(symbol_name)
6574
else:
6675
for i in range(lsb, msb + 1):
67-
symbol_name_bit = get_bus_name(symbol_name, i)
76+
symbol_name_bit = term_manager().publish_new_name(symbol_name, i)
6877
ns[symbol_name_bit] = Symbol(symbol_name_bit)
6978

79+
term_manager().flash_renamed_signals()
7080
f = self.to_sympy_expr(target_tree.tocode())
81+
for signal in term_manager().renamed_signals:
82+
signal = signal.replace('.','_')
83+
ns[signal] = Symbol(signal)
84+
85+
#TODO delete renamed signals
7186
expr = sympify(f, ns, convert_xor=False)
7287

88+
for signal in term_manager().renamed_signals:
89+
signal = signal.replace('.','_')
90+
ns.pop(signal)
91+
7392
truth_table = {}
7493
for result, var_state in self.walk_truth_table(ns, expr):
7594
truth_table[str(var_state)] = result
@@ -111,7 +130,7 @@ def to_sympy_expr(self, expr):
111130
expr = expr.replace(comb[0], comb[1])
112131
return expr
113132

114-
def DFBranch_tocode_for_sympy(self, dest='dest', always=''):
133+
def DFBranch_tocode(self, dest='dest', always=''):
115134
ret = '('
116135
if self.condnode is not None: ret += '(' + self.condnode.tocode(dest) + ')'
117136
ret += '& '
@@ -131,35 +150,86 @@ def DFOperator_is_reduction(self):
131150
else:
132151
return False
133152

134-
def DFOperator_tocode_for_sympy(self):
135-
if not self.is_reduction():
136-
return self.tocode_org()
153+
def DFOperator_is_algebra(self):
154+
if self.operator in ('Plus', 'Minus', 'LessThan', 'GreaterThan', 'LessEq', 'GreaterEq'):
155+
return True
156+
else:
157+
return False
158+
159+
def DFTerminal_tocode(self, dest='dest'):
160+
if term_manager().is_under_algebra:
161+
return term_manager().publish_new_name(str(self)).replace('.','_')
137162
else:
138-
if isinstance(self.nextnodes[0], DFPartselect): #TODO
163+
return self.tocode_org()
164+
165+
def DFOperator_tocode(self):
166+
if self.is_algebra(): #if operator is algebra, nextnodes aren't sweeped.
167+
term_manager().set_is_under_algebra(True)
168+
code = self.tocode_org()
169+
term_manager().set_is_under_algebra(False)
170+
return code
171+
elif self.is_reduction():
172+
if isinstance(self.nextnodes[0], DFPartselect):
139173
term = self.nextnodes[0].var
140174
msb = eval_value(self.nextnodes[0].msb)
141175
lsb = eval_value(self.nextnodes[0].lsb)
142176
elif isinstance(self.nextnodes[0], DFTerminal):
143-
term = self.nextnodes[0].get_bind()
177+
term = term_manager().get_term(str(self.nextnodes[0]))
144178
msb = eval_value(term.msb)
145179
lsb = eval_value(term.lsb)
146180
else:
147181
raise Exception('Unexpected exception.')
148182
mark = op2mark.op2mark(self.operator)
149-
return mark.join([get_bus_name(term, i).replace('.', '_') for i in range(lsb, msb + 1)])
183+
return mark.join([term_manager().publish_new_name(str(term), i).replace('.', '_') for i in range(lsb, msb + 1)])
184+
else:
185+
return self.tocode_org()
186+
187+
class term_manager(object):
188+
""" [CLASSES]
189+
Singleton class for manage terminals for DFxxx.
190+
"""
191+
_singleton = None
192+
def __new__(cls, *argc, **argv):
193+
if cls._singleton == None:
194+
cls._singleton = object.__new__(cls)
195+
cls.is_under_algebra = False
196+
cls.exclude_signals = []
197+
cls.renamed_signals = []
198+
return cls._singleton
199+
200+
def set_scope_dict(self, scope_dict):
201+
self.scope_dict = scope_dict
202+
203+
def set_terms(self, terms):
204+
self.terms = terms
205+
206+
def get_term(self, signal):
207+
scope = self.scope_dict[signal]
208+
return self.terms[scope]
209+
210+
def set_is_under_algebra(self, flag=False):
211+
self.is_under_algebra = flag
212+
213+
def publish_new_name(self, signal, bit=None):
214+
if bit is None:
215+
new_name = signal + '_'
216+
else:
217+
new_name = signal + '__' + str(bit) + '__'
218+
while(new_name in self.scope_dict.keys()):
219+
new_name += '_'
220+
if bit is None:
221+
self.renamed_signals.append(new_name)
222+
return new_name
150223

151-
def DFTerminal_get_terms(self):
152-
scope = DFTerminal.scope_dict[str(self)]
153-
return DFTerminal.terms[scope]
224+
def flash_renamed_signals(self):
225+
self.renamed_signals = []
154226

155-
def get_bus_name(signal, bit):
156-
return str(signal) + '__' + str(bit) + '__'
227+
def flash_exclude_signals(self):
228+
self.exclude_signals = []
157229

158230
if __name__ == '__main__':
159231
fv = FormalVerifier("../testcode/fv_test.v")
160232
#fv.calc_truth_table('TOP.A')
161233
#fv.calc_truth_table('TOP.C')
162234
#fv.calc_truth_table('TOP.E')
163-
a=fv.calc_truth_table('TOP.G')
164-
fv.write_back_DFmethods()
165-
pass
235+
fv.calc_truth_table('TOP.H')

0 commit comments

Comments
 (0)