X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fadd%2Fpipeline.py;h=afcee743982175e31a833a208067bf59ec2c3978;hb=6bff1a997f3846872cf489c24b5c01426c4dc97c;hp=1b0a745894c4d3309a64147c020e34aea80b5538;hpb=07eb674cf9e13ffaa3f3c037dc46c12f423ff4cc;p=ieee754fpu.git diff --git a/src/add/pipeline.py b/src/add/pipeline.py index 1b0a7458..afcee743 100644 --- a/src/add/pipeline.py +++ b/src/add/pipeline.py @@ -8,7 +8,8 @@ from nmigen import tracer from nmigen.compat.fhdl.bitcontainer import value_bits_sign from contextlib import contextmanager -from singlepipe import eq, StageCls, ControlBase, BufferedPipeline +from nmoperator import eq +from singlepipe import StageCls, ControlBase, BufferedHandshake from singlepipe import UnbufferedPipeline @@ -28,6 +29,16 @@ def like(value, rname, pipe, pipemode=False): reset_less=True) return Signal.like(value, name=rname, reset_less=True) +def get_assigns(_assigns): + assigns = [] + for e in _assigns: + if isinstance(e, ObjectProxy): + assigns += get_assigns(e._assigns) + else: + assigns.append(e) + return assigns + + def get_eqs(_eqs): eqs = [] for e in _eqs: @@ -39,13 +50,15 @@ def get_eqs(_eqs): 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 = {} @classmethod @@ -70,6 +83,15 @@ class ObjectProxy: subobjs.append(repr(ai)) return "" % 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 = [] @@ -85,7 +107,7 @@ class ObjectProxy: 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): @@ -109,13 +131,22 @@ class ObjectProxy: 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)) + #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: @@ -125,27 +156,34 @@ 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) @@ -166,36 +204,79 @@ class PipelineStage: 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) - print ("pipemode: append", new_pipereg, 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 - else: + self._assigns += assign + elif self._m: print ("!pipemode: assign", new_pipereg, value) assign = eq(new_pipereg, value) self._m.d.sync += assign + 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): - def __init__(self, inspecs, outspecs, eqs): - self.inspecs, self.outspecs, self.eqs = inspecs, outspecs, eqs - 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 __init__(self, inspecs, outspecs, eqs, assigns): + self.inspecs, self.outspecs = inspecs, outspecs + self.eqs, self.assigns = eqs, assigns + #self.o = self.ospec() + def ispec(self): return likedict(self.inspecs) + def ospec(self): return likedict(self.outspecs) def process(self, i): print ("stage process", i) - return self.o + return self.eqs def setup(self, m, i): - print ("stage setup", i) - m.d.sync += eq(i, self.eqs) - m.d.comb += eq(self.o, 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) + + +class AutoPipe(UnbufferedPipeline): + def __init__(self, stage, assigns): + UnbufferedPipeline.__init__(self, stage) + self.assigns = assigns + + def elaborate(self, platform): + m = UnbufferedPipeline.elaborate(self, platform) + m.d.comb += self.assigns + print ("assigns", self.assigns, m) + return m class PipeManager: @@ -206,10 +287,12 @@ class PipeManager: @contextmanager def Stage(self, name, prev=None, ispec=None): - print ("start stage", name) - stage = PipelineStage(name, self.m, prev, self.pipemode, ispec=ispec) + if ispec: + ispec = likedict(ispec) + print ("start stage", name, ispec) + stage = PipelineStage(name, None, prev, self.pipemode, ispec=ispec) try: - yield stage, stage._m + yield stage, self.m #stage._m finally: pass if self.pipemode: @@ -218,21 +301,29 @@ class PipeManager: 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) - s = AutoStage(inspecs, outspecs, eqs) + print ("stage assigns", name, assigns) + s = AutoStage(inspecs, outspecs, eqs, assigns) self.stages.append(s) - print ("end stage", name, "\n") + 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 = [] @@ -245,9 +336,9 @@ class PipeManager: 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 = UnbufferedPipeline(s) + p = AutoPipe(s, s.assigns) pipes.append(p) self.m.submodules += p