Skip to content

Commit 4086835

Browse files
committed
pack_multiple() is added for replacement of pack()
1 parent 7e1b35e commit 4086835

File tree

1 file changed

+125
-37
lines changed

1 file changed

+125
-37
lines changed

veriloggen/lib/pipeline.py

Lines changed: 125 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import os
33
import sys
44
import collections
5-
import functools
5+
from functools import reduce
66
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
77

88
import 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

Comments
 (0)