from nmigen.compat.fhdl.bitcontainer import value_bits_sign
from contextlib import contextmanager
-from singlepipe import eq, StageCls, ControlBase, BufferedPipeline
+from singlepipe import eq, StageCls, ControlBase, BufferedHandshake
from singlepipe import UnbufferedPipeline
class ObjectProxy:
- def __init__(self, m, name=None, pipemode=False):
+ def __init__(self, m, name=None, pipemode=False, syncmode=True):
self._m = m
if name is None:
name = tracer.get_var_name(default=None)
self.name = name
self._pipemode = pipemode
- self._eqs = []
+ self._syncmode = syncmode
+ self._eqs = {}
self._assigns = []
self._preg_map = {}
subobjs.append(repr(ai))
return "<OP %s>" % subobjs
+ def get_specs(self, liked=False):
+ res = []
+ for k, v in self._preg_map.items():
+ #v = like(v, k, stage._m)
+ res.append(v)
+ if isinstance(v, ObjectProxy):
+ res += v.get_specs()
+ return res
+
def eq(self, i):
print ("ObjectProxy eq", self, i)
res = []
if isinstance(a, Signal) or isinstance(a, ObjectProxy) or \
isinstance(a, Record):
res.append(a)
- print ("ObjectPorts", res)
+ #print ("ObjectPorts", res)
return res
def __getattr__(self, name):
self._preg_map[name] = new_pipereg
#object.__setattr__(self, name, new_pipereg)
if self._pipemode:
- print ("OP pipemode", new_pipereg, value)
- #self._eqs.append(value)
- #self._m.d.comb += eq(new_pipereg, value)
- pass
+ print ("OP pipemode", self._syncmode, new_pipereg, value)
+ assign = eq(new_pipereg, value)
+ if self._syncmode:
+ self._m.d.sync += assign
+ else:
+ self._m.d.comb += assign
elif self._m:
print ("OP !pipemode assign", new_pipereg, value, type(value))
self._m.d.comb += eq(new_pipereg, value)
else:
print ("OP !pipemode !m", new_pipereg, value, type(value))
self._assigns += eq(new_pipereg, value)
+ if isinstance(value, ObjectProxy):
+ print ("OP, defer assigns:", value._assigns)
+ self._assigns += value._assigns
+ self._eqs.append(value._eqs)
class PipelineStage:
def __init__(self, name, m, prev=None, pipemode=False, ispec=None):
self._m = m
self._stagename = name
- self._preg_map = {}
+ self._preg_map = {'__nextstage__': {}}
self._prev_stage = prev
self._ispec = ispec
+ if ispec:
+ self._preg_map[self._stagename] = ispec
if prev:
print ("prev", prev._stagename, prev._preg_map)
- if prev._stagename in prev._preg_map:
- m = prev._preg_map[prev._stagename]
- self._preg_map[prev._stagename] = m
- #for k, v in m.items():
- #m[k] = like(v, k, self._m)
+ #if prev._stagename in prev._preg_map:
+ # m = prev._preg_map[prev._stagename]
+ # self._preg_map[prev._stagename] = m
if '__nextstage__' in prev._preg_map:
m = prev._preg_map['__nextstage__']
+ m = likedict(m)
self._preg_map[self._stagename] = m
#for k, v in m.items():
#m[k] = like(v, k, self._m)
print ("make current", self._stagename, m)
self._pipemode = pipemode
- self._eqs = []
+ self._eqs = {}
self._assigns = []
- def __getattr__(self, name):
+ def __getattribute__(self, name):
+ if name.startswith('_'):
+ return object.__getattribute__(self, name)
+ #if name in self._preg_map['__nextstage__']:
+ # return self._preg_map['__nextstage__'][name]
try:
+ print ("getattr", name, object.__getattribute__(self, '_preg_map'))
v = self._preg_map[self._stagename][name]
return v
#return like(v, name, self._m)
if next_stage not in self._preg_map:
self._preg_map[next_stage] = {}
self._preg_map[next_stage][name] = new_pipereg
+ print ("setattr", name, value, self._preg_map)
if self._pipemode:
- self._eqs.append(value)
+ self._eqs[name] = new_pipereg
assign = eq(new_pipereg, value)
print ("pipemode: append", new_pipereg, value, assign)
if isinstance(value, ObjectProxy):
print ("OP, assigns:", value._assigns)
self._assigns += value._assigns
+ self._eqs[name]._eqs = value._eqs
#self._m.d.comb += assign
self._assigns += assign
elif self._m:
else:
print ("!pipemode !m: defer assign", new_pipereg, value)
assign = eq(new_pipereg, value)
+ self._eqs[name] = new_pipereg
self._assigns += assign
+ if isinstance(value, ObjectProxy):
+ print ("OP, defer assigns:", value._assigns)
+ self._assigns += value._assigns
+ self._eqs[name]._eqs = value._eqs
+
+def likelist(specs):
+ res = []
+ for v in specs:
+ res.append(like(v, v.name, None, pipemode=True))
+ return res
+
+def likedict(specs):
+ if not isinstance(specs, dict):
+ return like(specs, specs.name, None, pipemode=True)
+ res = {}
+ for k, v in specs.items():
+ res[k] = likedict(v)
+ return res
class AutoStage(StageCls):
self.inspecs, self.outspecs = inspecs, outspecs
self.eqs, self.assigns = eqs, assigns
#self.o = self.ospec()
- def ispec(self): return self.like(self.inspecs)
- def ospec(self): return self.like(self.outspecs)
- def like(self, specs):
- res = []
- for v in specs:
- res.append(like(v, v.name, None, pipemode=True))
- return res
+ def ispec(self): return likedict(self.inspecs)
+ def ospec(self): return likedict(self.outspecs)
def process(self, i):
print ("stage process", i)
return self.eqs
def setup(self, m, i):
- print ("stage setup", i)
+ print ("stage setup i", i, m)
+ print ("stage setup inspecs", self.inspecs)
+ print ("stage setup outspecs", self.outspecs)
+ print ("stage setup eqs", self.eqs)
+ #self.o = self.ospec()
+ m.d.comb += eq(self.inspecs, i)
+ #m.d.comb += eq(self.outspecs, self.eqs)
#m.d.comb += eq(self.o, i)
def elaborate(self, platform):
m = UnbufferedPipeline.elaborate(self, platform)
m.d.comb += self.assigns
- print ("assigns", self.assigns)
+ print ("assigns", self.assigns, m)
return m
@contextmanager
def Stage(self, name, prev=None, ispec=None):
- print ("start stage", name)
+ if ispec:
+ ispec = likedict(ispec)
+ print ("start stage", name, ispec)
stage = PipelineStage(name, None, prev, self.pipemode, ispec=ispec)
try:
yield stage, self.m #stage._m
inspecs = stage._ispec
else:
inspecs = self.get_specs(stage, name)
+ #inspecs = likedict(inspecs)
outspecs = self.get_specs(stage, '__nextstage__', liked=True)
- eqs = get_eqs(stage._eqs)
+ print ("stage inspecs", name, inspecs)
+ print ("stage outspecs", name, outspecs)
+ eqs = stage._eqs # get_eqs(stage._eqs)
assigns = get_assigns(stage._assigns)
print ("stage eqs", name, eqs)
print ("stage assigns", name, assigns)
print ("end stage", name, self.pipemode, "\n")
def get_specs(self, stage, name, liked=False):
+ return stage._preg_map[name]
if name in stage._preg_map:
res = []
for k, v in stage._preg_map[name].items():
#v = like(v, k, stage._m)
res.append(v)
+ #if isinstance(v, ObjectProxy):
+ # res += v.get_specs()
return res
- return []
+ return {}
def __enter__(self):
self.stages = []
for s in self.stages:
print ("stage specs", s, s.inspecs, s.outspecs)
if self.pipetype == 'buffered':
- p = BufferedPipeline(s)
+ p = BufferedHandshake(s)
else:
p = AutoPipe(s, s.assigns)
pipes.append(p)