Skip to content

Commit f7b03d5

Browse files
committed
change reset detection method for issue#14
1 parent 93d0304 commit f7b03d5

File tree

11 files changed

+352
-206
lines changed

11 files changed

+352
-206
lines changed

pyverilog/dataflow/bindvisitor.py

Lines changed: 165 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,10 @@ def visit_Always(self, node):
229229

230230
(clock_name, clock_edge, clock_bit,
231231
reset_name, reset_edge, reset_bit,
232-
senslist) = self._createAlwaysinfo(node, current)
232+
senslist, load_const_dict) = self._createAlwaysinfo(node, current)
233233

234234
self.frames.setAlwaysInfo(clock_name, clock_edge, clock_bit,
235-
reset_name, reset_edge, reset_bit, senslist)
235+
reset_name, reset_edge, reset_bit, senslist, load_const_dict)
236236

237237
self.generic_visit(node)
238238
self.frames.setCurrent(current)
@@ -255,11 +255,13 @@ def _createAlwaysinfo(self, node, scope):
255255
reset_edge = None
256256
reset_name = None
257257
reset_bit = None
258+
reset_sig = None
259+
is_sync_reset = True
260+
r_finder = self.reset_finder(node, self.frames.current, self.dataflow)
258261

259-
#TODO unimplemented
260-
#print('load: ' + str(self._first_lvalue_is_const(node)))
261-
#print('if_branch: ' + str(self._has_if_branch(node)))
262-
#print('reset_info: ' + str(self._get_rst_info(node)))
262+
if str(r_finder._has_if_branch(node)) and any(r_finder.load_const_dict.values()):
263+
reset_sig, reset_edge, reset_bit = r_finder.get_rst_info()
264+
reset_name = self.searchTerminal(reset_sig, scope)
263265

264266
for l in node.sens_list.list:
265267
if l.sig is None:
@@ -270,14 +272,16 @@ def _createAlwaysinfo(self, node, scope):
270272
else:
271273
signame = self._get_signal_name(l.sig)
272274
bit = 0
273-
if signaltype.isClock(signame):
275+
276+
if signame == reset_sig and bit == reset_bit:
277+
if l.type == reset_edge:
278+
is_sync_reset = False
279+
else:
280+
raise verror.FormatError('Illegal reset polarity')
281+
elif not clock_name: #First signal which is not reset is regard as clock.
274282
clock_name = self.searchTerminal(signame, scope)
275283
clock_edge = l.type
276284
clock_bit = bit
277-
elif signaltype.isReset(signame):
278-
reset_name = self.searchTerminal(signame, scope)
279-
reset_edge = l.type
280-
reset_bit = bit
281285
else:
282286
senslist.append(l)
283287

@@ -286,135 +290,10 @@ def _createAlwaysinfo(self, node, scope):
286290
if reset_edge is not None and len(senslist) > 0:
287291
raise verror.FormatError('Illegal sensitivity list')
288292

289-
return (clock_name, clock_edge, clock_bit, reset_name, reset_edge, reset_bit, senslist)
290-
291-
#TODO This function is implemented for https://github.com/PyHDI/Pyverilog/issues/14.
292-
#Be incorporated into formally in lator commit.
293-
def _first_lvalue_is_const(self, node):
294-
""" [FUNCTIONS]
295-
Walk until lvalue and judge whether it is constant or not.
296-
297-
ex.
298-
if(RST)
299-
reg1 <= 1'd0: //const: judged as rst branch
300-
301-
if(RST)
302-
reg1 <= {1'd0, 1'd0}: //const: judged as rst branch
303-
304-
if(RST)
305-
reg1 <= reg2: //variable: judged as not rst branch
306-
307-
if(RST)
308-
reg1 <= {1'd0, reg2}: //variable: judged as not rst branch
309-
"""
310-
if isinstance(node, Always):
311-
return self._first_lvalue_is_const(node.statement)
312-
elif isinstance(node, Block):
313-
return self._first_lvalue_is_const(node.statements[0])
314-
elif isinstance(node, IfStatement):
315-
return self._first_lvalue_is_const(node.true_statement)
316-
elif isinstance(node, NonblockingSubstitution):
317-
print(node.left.var)# for debug
318-
return self._first_lvalue_is_const(node.right)
319-
elif isinstance(node, Identifier):
320-
node_chain = self.get_scopechain(node)
321-
if node_chain in self.dataflow.terms.keys():
322-
#Parameter is regard as constant.
323-
return 'Parameter' in self.dataflow.terms[node_chain].termtype
324-
return False
325-
elif hasattr(node, 'children'):
326-
for child in node.children():
327-
if not self._first_lvalue_is_const(child):
328-
return False
329-
return True
330-
elif isinstance(node, Rvalue):
331-
return self._first_lvalue_is_const(node.var)
332-
elif hasattr(node, 'value'):
333-
return True
334-
else:
335-
raise Exception('Pyverilog unknown error')
336-
337-
def get_scopechain(self, node):
338-
assert isinstance(node, Identifier), 'Node type should be Identifier.'
339-
scope_list = self.frames.current.get_module_list() + [util.ScopeLabel(str(node)),]
340-
return util.ScopeChain(scope_list)
341-
342-
#TODO This function is implemented for https://github.com/PyHDI/Pyverilog/issues/14.
343-
#Be incorporated into formally in lator commit.
344-
def _get_rst_info(self, node, rst_name='', is_posedge=True, rst_bit=0):
345-
""" [FUNCTIONS]
346-
get reset information from first if statement.
347-
348-
ex1.
349-
always @(posedge CLK or posedge RST) begin
350-
if(RST)
351-
reg1 <= 0;
352-
else
353-
reg1 <= !reg1;
354-
end
355-
->RST is posedge RST.
356-
357-
ex2.
358-
always @(posedge CLK or posedge RST) begin
359-
if(!RSTN[1])
360-
reg1 <= 0;
361-
else
362-
reg1 <= !reg1;
363-
end
364-
->RSTN[1] is negedge RST.
365-
366-
ex3.
367-
always @(posedge CLK or posedge RST) begin
368-
if(RST && RST2)
369-
reg1 <= 0;
370-
else
371-
reg1 <= !reg1;
372-
end
373-
-> reg1 has no reset. (too complex condition)
374-
"""
375-
if isinstance(node, Always):
376-
return self._get_rst_info(node.statement, rst_name, is_posedge, rst_bit)
377-
elif isinstance(node, Block):
378-
return self._get_rst_info(node.statements[0], rst_name, is_posedge, rst_bit)
379-
elif isinstance(node, IfStatement):
380-
return self._get_rst_info(node.cond, rst_name, is_posedge, rst_bit)
381-
elif isinstance(node, pyverilog.vparser.ast.Ulnot):
382-
is_posedge = not is_posedge
383-
return self._get_rst_info(node.children()[0], rst_name, is_posedge, rst_bit)
384-
elif isinstance(node, pyverilog.vparser.ast.Pointer):
385-
#TODO if identifier
386-
if isinstance(node.ptr, Identifier):
387-
ptr_chain = self.get_scopechain(node.ptr)
388-
if 'Parameter' in self.dataflow.terms[ptr_chain].termtype:
389-
rst_bit = self.dataflow.binddict[ptr_chain][0].tree.eval()
390-
return self._get_rst_info(node.var, rst_name, is_posedge, rst_bit)
391-
else:
392-
return (None, None, None)
393-
elif hasattr(node.ptr, 'value'):
394-
return self._get_rst_info(node.var, rst_name, is_posedge, int(node.ptr.value))
395-
elif isinstance(node, pyverilog.vparser.ast.Identifier):
396-
return (node, is_posedge, rst_bit)
397-
return (None, None, None)
398-
399-
#TODO This function is implemented for https://github.com/PyHDI/Pyverilog/issues/14.
400-
#Be incorporated into formally in lator commit.
401-
def _has_if_branch(self, node):
402-
""" [FUNCTIONS]
403-
Return always block have 'if branch' or not.
404-
ex.
405-
always @(posedge CLK or posedge RST) begin
406-
reg1 <= 0;
407-
end
408-
-> reg1 has no reset. (If statement isn't exists.)
409-
"""
410-
if isinstance(node, Always):
411-
return self._has_if_branch(node.statement)
412-
elif isinstance(node, Block):
413-
return self._has_if_branch(node.statements[0])
414-
elif isinstance(node, IfStatement):
415-
return True
416-
else:
417-
return False
293+
if is_sync_reset:
294+
reset_edge = 'sync'
295+
return (clock_name, clock_edge, clock_bit, reset_name, reset_edge, reset_bit,
296+
senslist, r_finder.load_const_dict)
418297

419298
def visit_IfStatement(self, node):
420299
if self.frames.isFunctiondef() and not self.frames.isFunctioncall(): return
@@ -495,7 +374,6 @@ def visit_CaseStatement(self, node):
495374
start_frame = self.frames.getCurrent()
496375
caseframes = []
497376
self._case(node.comp, node.caselist, caseframes)
498-
#self._case(node.comp, tuple(reversed(list(node.caselist))), caseframes)
499377
self.frames.setCurrent(start_frame)
500378
for f in caseframes:
501379
self.copyBlockingAssigns(f, start_frame)
@@ -662,15 +540,15 @@ def visit_Assign(self, node):
662540
self.addBind(node.left, node.right, bindtype='assign')
663541

664542
def visit_BlockingSubstitution(self, node):
665-
self.addBind(node.left, node.right, self.frames.getAlwaysStatus(), 'blocking')
543+
self.addBind(node.left, node.right, self.frames.getAlwaysStatus(node.left), 'blocking')
666544

667545
def visit_NonblockingSubstitution(self, node):
668546
if self.frames.isForpre() or self.frames.isForpost():
669547
raise verror.FormatError(("Non Blocking Substitution is not allowed"
670548
"in for-statement"))
671549
if self.frames.isFunctioncall():
672550
raise verror.FormatError("Non Blocking Substitution is not allowed in function")
673-
self.addBind(node.left, node.right, self.frames.getAlwaysStatus(), 'nonblocking')
551+
self.addBind(node.left, node.right, self.frames.getAlwaysStatus(node.left), 'nonblocking')
674552

675553
def visit_SystemCall(self, node):
676554
print("Warning: Isolated system call is not supported: %s" % node.syscall)
@@ -1646,3 +1524,147 @@ def appendBranchTree(self, base, pos, tree):
16461524
base.condnode,
16471525
base.truenode,
16481526
self.appendBranchTree(base.falsenode, pos[1:], tree))
1527+
1528+
class reset_finder(object):
1529+
def __init__(self, node, current, dataflow):
1530+
self.current = current
1531+
self.dataflow = dataflow
1532+
self.is_posedge = 'posedge'
1533+
self.rst_bit = 0
1534+
self.rst_name = None
1535+
self.load_const_dict = {}
1536+
self._walk_in_first_ifbranch(node)
1537+
self._make_rst_info(node)
1538+
1539+
def _walk_in_first_ifbranch(self, node):
1540+
""" [FUNCTIONS]
1541+
Walk until lvalue and judge whether it is constant or not.
1542+
1543+
ex.
1544+
if(RST)
1545+
reg1 <= 1'd0: //const: judged as rst branch
1546+
1547+
if(RST)
1548+
reg1 <= {1'd0, 1'd0}: //const: judged as rst branch
1549+
1550+
if(RST)
1551+
reg1 <= reg2: //variable: judged as not rst branch
1552+
1553+
if(RST)
1554+
reg1 <= {1'd0, reg2}: //variable: judged as not rst branch
1555+
"""
1556+
if isinstance(node, Always):
1557+
self._walk_in_first_ifbranch(node.statement)
1558+
elif isinstance(node, Block):
1559+
for statement in node.statements:
1560+
self._walk_in_first_ifbranch(statement)
1561+
elif isinstance(node, IfStatement):
1562+
self._walk_in_first_ifbranch(node.true_statement)
1563+
elif isinstance(node, NonblockingSubstitution):
1564+
self.load_const_dict[node.left] = self.is_const(node.right)
1565+
else:
1566+
raise Exception('Pyverilog unknown error')
1567+
1568+
def is_const(self, node):
1569+
if isinstance(node, Identifier):
1570+
node_chain = self.get_scopechain(node)
1571+
if node_chain in self.dataflow.terms.keys():
1572+
#Parameter is regard as constant.
1573+
return 'Parameter' in self.dataflow.terms[node_chain].termtype
1574+
elif hasattr(node, 'children'):
1575+
for child in node.children():
1576+
if not self.is_const(child):
1577+
return False
1578+
else:
1579+
return True
1580+
elif isinstance(node, Rvalue):
1581+
self.is_const(node.var)
1582+
elif hasattr(node, 'value'):
1583+
return True
1584+
else:
1585+
raise Exception('Pyverilog unknown error')
1586+
1587+
def get_is_const_subed(self):
1588+
return self.const_substituted
1589+
1590+
def get_scopechain(self, node):
1591+
assert isinstance(node, Identifier), 'Node type should be Identifier.'
1592+
scope_list = self.current.get_module_list() + [util.ScopeLabel(str(node)),]
1593+
return util.ScopeChain(scope_list)
1594+
1595+
def _make_rst_info(self, node):
1596+
""" [FUNCTIONS]
1597+
get reset information from first if statement.
1598+
1599+
ex1.
1600+
always @(posedge CLK or posedge RST) begin
1601+
if(RST)
1602+
reg1 <= 0;
1603+
else
1604+
reg1 <= !reg1;
1605+
end
1606+
->RST is posedge RST.
1607+
1608+
ex2.
1609+
always @(posedge CLK or posedge RST) begin
1610+
if(!RSTN[1])
1611+
reg1 <= 0;
1612+
else
1613+
reg1 <= !reg1;
1614+
end
1615+
->RSTN[1] is negedge RST.
1616+
1617+
ex3.
1618+
always @(posedge CLK or posedge RST) begin
1619+
if(RST && RST2)
1620+
reg1 <= 0;
1621+
else
1622+
reg1 <= !reg1;
1623+
end
1624+
-> reg1 has no reset. (too complex condition)
1625+
"""
1626+
if isinstance(node, Always):
1627+
self._make_rst_info(node.statement)
1628+
elif isinstance(node, Block):
1629+
self._make_rst_info(node.statements[0])
1630+
elif isinstance(node, IfStatement):
1631+
self._make_rst_info(node.cond)
1632+
elif isinstance(node, Ulnot):
1633+
self.is_posedge = 'negedge' if self.is_posedge == 'posedge' else 'posedge'
1634+
self._make_rst_info(node.children()[0])
1635+
elif isinstance(node, Pointer):
1636+
if isinstance(node.ptr, Identifier):
1637+
ptr_chain = self.get_scopechain(node.ptr)
1638+
if 'Parameter' in self.dataflow.terms[ptr_chain].termtype:
1639+
self.rst_bit = self.dataflow.binddict[ptr_chain][0].tree.eval()
1640+
self._make_rst_info(node.var)
1641+
else:
1642+
self.is_posedge = None
1643+
self.rst_name = None
1644+
self.rst_bit = None
1645+
elif hasattr(node.ptr, 'value'):
1646+
self.rst_bit = int(node.ptr.value)
1647+
self._make_rst_info(node.var)
1648+
elif isinstance(node, pyverilog.vparser.ast.Identifier):
1649+
self.rst_name = str(node)
1650+
1651+
def _has_if_branch(self, node):
1652+
""" [FUNCTIONS]
1653+
Return always block have 'if branch' or not.
1654+
ex.
1655+
always @(posedge CLK or posedge RST) begin
1656+
reg1 <= 0;
1657+
end
1658+
-> reg1 has no reset. (If statement isn't exists.)
1659+
"""
1660+
if isinstance(node, Always):
1661+
return self._has_if_branch(node.statement)
1662+
elif isinstance(node, Block):
1663+
return self._has_if_branch(node.statements[0])
1664+
elif isinstance(node, IfStatement):
1665+
return True
1666+
else:
1667+
return False
1668+
1669+
def get_rst_info(self):
1670+
return self.rst_name, self.is_posedge, self.rst_bit

0 commit comments

Comments
 (0)