22import os
33import sys
44import collections
5- import functools
5+ from functools import reduce
66sys .path .insert (0 , os .path .dirname (os .path .dirname (os .path .abspath (__file__ ))))
77
88import vtypes
@@ -322,9 +322,12 @@ def prev(self, index, initval=0):
322322
323323 return p
324324
325- def output (self , data , valid = None , ready = None ):
325+ def output (self , data , valid = None , ready = None , nobuf = False ):
326326 # Inserting output stage register
327- ovar = self .pipe (self )
327+ if nobuf :
328+ ovar = self
329+ else :
330+ ovar = self .pipe .stage (self )
328331
329332 if not isinstance (data , (vtypes .Wire , vtypes .Output )):
330333 raise TypeError ('Data signal must be Wire, not %s' % str (type (data )))
@@ -385,10 +388,25 @@ def visit__PipelineVariable(self, node):
385388
386389 def visit__BinaryOperator (self , node ):
387390 raise NotImplementedError ('visit__BinaryOperator() must be implemented' )
388-
391+
389392 def visit__UnaryOperator (self , node ):
390393 raise NotImplementedError ('visit__UnaryOperator() must be implemented' )
391394
395+ def visit_Pointer (self , node ):
396+ raise NotImplementedError ('visit_Pointer() must be implemented' )
397+
398+ def visit_Slice (self , node ):
399+ raise NotImplementedError ('visit_Slice() must be implemented' )
400+
401+ def visit_Cat (self , node ):
402+ raise NotImplementedError ('visit_Cat() must be implemented' )
403+
404+ def visit_Repeat (self , node ):
405+ raise NotImplementedError ('visit_Repeat() must be implemented' )
406+
407+ def visit_Cond (self , node ):
408+ raise NotImplementedError ('visit_Cond() must be implemented' )
409+
392410 def visit__Variable (self , node ):
393411 raise NotImplementedError ('visit__Variable() must be implemented' )
394412
@@ -426,38 +444,14 @@ def pack_valid(self, lvalid, rvalid):
426444 def pack_ready (self , lready , rready ):
427445 return lready + rready
428446
429- def make_valid (self , valid , ready ):
430- if ready is not None and valid is not None :
431- next_valid = vtypes .AndList (valid , ready )
432- elif ready is not None :
433- next_valid = ready
434- elif valid is not None :
435- next_valid = valid
436- else :
437- next_valid = None
438- return next_valid
439-
440- def visit__PipelineVariable (self , node ):
441- ready = [] if node .ready is None else [ node .ready ]
442- valid = self .make_valid (node .valid , node .ready )
443- return (node .stage_id , node .data , valid , ready )
444-
445- def visit__Variable (self , node ):
446- return (None , node , None , [])
447-
448- def visit__Constant (self , node ):
449- return (None , node , None , [])
450-
451- def visit__BinaryOperator (self , node ):
452- rstage , rdata , rvalid , rready = self .visit (node .right )
453- lstage , ldata , lvalid , lready = self .visit (node .left )
454-
455- cls = type (node )
456- data = cls (ldata , rdata )
447+ def pack (self , left , right ):
448+ rstage , rdata , rvalid , rready = self .visit (right )
449+ lstage , ldata , lvalid , lready = self .visit (left )
457450
451+ data = [ ldata , rdata ]
458452 valid = self .pack_valid (lvalid , rvalid )
459453 ready = self .pack_ready (lready , rready )
460-
454+
461455 if rstage is None and lstage is None :
462456 return (None , data , valid , ready )
463457 if rstage is None :
@@ -467,33 +461,127 @@ def visit__BinaryOperator(self, node):
467461
468462 if lstage > rstage :
469463 diff = lstage - rstage
470- p = node . right
464+ p = right
471465 for i in range (diff ):
472466 width = rdata .bit_length ()
473467 p = self .pipe .stage (p , width = width )
474- data = cls ( ldata , p .data )
468+ data = [ ldata , p .data ]
475469 valid = self .pack_valid (lvalid , p .valid )
476470 rready = [] if p .ready is None else [ p .ready ]
477471 ready = self .pack_ready (lready , rready )
478472 return (max (lstage , rstage ), data , valid , ready )
479473
480474 if lstage < rstage :
481475 diff = rstage - lstage
482- p = node . left
476+ p = left
483477 for i in range (diff ):
484478 width = ldata .bit_length ()
485479 p = self .pipe .stage (p , width = width )
486- data = cls ( p .data , rdata )
480+ data = [ p .data , rdata ]
487481 valid = self .pack_valid (p .valid , rvalid )
488482 lready = [] if p .ready is None else [ p .ready ]
489483 ready = self .pack_ready (lready , rready )
490484 return (max (lstage , rstage ), data , valid , ready )
491485
492486 return (max (lstage , rstage ), data , valid , ready )
493487
488+ def pack_multi (self , * args ):
489+ rslts = [ self .visit (arg ) for arg in args ]
490+ all_stage_none = reduce (lambda t ,x :t and x is None , [ rslt [0 ] for rslt in rslts ], True )
491+
492+ if all_stage_none :
493+ data = [ rslt [1 ] for rslt in rslts ]
494+ valid = reduce (self .pack_valid , [ rslt [2 ] for rslt in rslts ], None )
495+ ready = reduce (self .pack_ready , [ rslt [3 ] for rslt in rslts ], [])
496+ return (None , data , valid , ready )
497+
498+ max_stage = reduce (lambda x ,y :
499+ None if x is None and y is None else
500+ x if x is not None and y is None else
501+ y if y is not None and x is None else
502+ max (x , y ), [ rslt [0 ] for rslt in rslts ], None )
503+
504+ new_args = []
505+ for rslt , arg in zip (rslts , args ):
506+ stage = rslt [0 ]
507+ if stage is None :
508+ new_args .append (arg )
509+ continue
510+ if stage == max_stage :
511+ new_args .append (arg )
512+ continue
513+
514+ diff = max_stage - stage
515+ p = arg
516+ for i in range (diff ):
517+ width = rslt [1 ].bit_length ()
518+ p = self .pipe .stage (p , width = width )
519+
520+ new_args .append (p )
521+
522+ new_rslts = [ self .visit (arg ) for arg in new_args ]
523+ data = [ rslt [1 ] for rslt in new_rslts ]
524+ valid = reduce (self .pack_valid , [ rslt [2 ] for rslt in new_rslts ], None )
525+ ready = reduce (self .pack_ready , [ rslt [3 ] for rslt in new_rslts ], [])
526+
527+ return (max_stage , data , valid , ready )
528+
529+ def make_valid (self , valid , ready ):
530+ if ready is not None and valid is not None :
531+ next_valid = vtypes .AndList (valid , ready )
532+ elif ready is not None :
533+ next_valid = ready
534+ elif valid is not None :
535+ next_valid = valid
536+ else :
537+ next_valid = None
538+ return next_valid
539+
540+ def visit__PipelineVariable (self , node ):
541+ ready = [] if node .ready is None else [ node .ready ]
542+ valid = self .make_valid (node .valid , node .ready )
543+ return (node .stage_id , node .data , valid , ready )
544+
545+ def visit__Variable (self , node ):
546+ return (None , node , None , [])
547+
548+ def visit__Constant (self , node ):
549+ return (None , node , None , [])
550+
551+ def visit__BinaryOperator (self , node ):
552+ stage , data , valid , ready = self .pack_multi (node .left , node .right )
553+ cls = type (node )
554+ return stage , cls (* data ), valid , ready
555+
494556 def visit__UnaryOperator (self , node ):
495557 return self .visit (node .right )
496558
559+ def visit_Pointer (self , node ):
560+ stage , data , valid , ready = self .pack_multi (node .var , node .pos )
561+ cls = type (node )
562+ return stage , cls (* data ), valid , ready
563+
564+ def visit_Slice (self , node ):
565+ stage , data , valid , ready = self .pack_multi (node .var , node .msb , node .lsb )
566+ cls = type (node )
567+ return stage , cls (* data ), valid , ready
568+
569+ def visit_Cat (self , node ):
570+ stage , data , valid , ready = self .pack_multi (* node .vars )
571+ cls = type (node )
572+ return stage , cls (* data ), valid , ready
573+
574+ def visit_Repeat (self , node ):
575+ stage , data , valid , ready = self .pack_multi (node .var , node .times )
576+ cls = type (node )
577+ return stage , cls (* data ), valid , ready
578+
579+ def visit_Cond (self , node ):
580+ stage , data , valid , ready = self .pack_multi (node .condition ,
581+ node .true_value , node .false_value )
582+ cls = type (node )
583+ return stage , cls (* data ), valid , ready
584+
497585 def visit_bool (self , node ):
498586 if node : return (None , vtypes .Int (1 ), None , [])
499587 return (None , vtypes .Int (0 ), None , [])
0 commit comments