@@ -256,6 +256,11 @@ def _createAlwaysinfo(self, node, scope):
256256 reset_name = None
257257 reset_bit = None
258258
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)))
263+
259264 for l in node .sens_list .list :
260265 if l .sig is None :
261266 continue
@@ -283,6 +288,134 @@ def _createAlwaysinfo(self, node, scope):
283288
284289 return (clock_name , clock_edge , clock_bit , reset_name , reset_edge , reset_bit , senslist )
285290
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
418+
286419 def visit_IfStatement (self , node ):
287420 if self .frames .isFunctiondef () and not self .frames .isFunctioncall (): return
288421 if self .frames .isTaskdef () and not self .frames .isTaskcall (): return
@@ -828,7 +961,7 @@ def addTerm(self, node, rscope=None):
828961 else :
829962 msb = DFIntConst ('0' ) if node .width is None else self .makeDFTree (node .width .msb , scope )
830963 lsb = DFIntConst ('0' ) if node .width is None else self .makeDFTree (node .width .lsb , scope )
831-
964+
832965 lenmsb = None
833966 lenlsb = None
834967 if isinstance (node , RegArray ) or isinstance (node , WireArray ):
0 commit comments