X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fadd%2Fiocontrol.py;h=dfa04797ec52fe44934d1054a8d32251086f5b95;hb=caa4f0c699f07af415fd347d323d0926b08b7564;hp=a4450c80e7af3ad2855fa21ad413a6f358df65f0;hpb=791efaf24cb034d787c587f2ff349ae96a288a92;p=ieee754fpu.git diff --git a/src/add/iocontrol.py b/src/add/iocontrol.py index a4450c80..dfa04797 100644 --- a/src/add/iocontrol.py +++ b/src/add/iocontrol.py @@ -19,17 +19,26 @@ the methods of a stage instance must be as follows: - * ispec() - Input data format specification - returns an object or a list or tuple of objects, or - a Record, each object having an "eq" function which - takes responsibility for copying by assignment all - sub-objects - * ospec() - Output data format specification - requirements as for ospec - * process(m, i) - Processes an ispec-formatted object + * ispec() - Input data format specification. Takes a bit of explaining. + The requirements are: something that eventually derives from + nmigen Value must be returned *OR* an iterator or iterable + or sequence (list, tuple etc.) or generator must *yield* + thing(s) that (eventually) derive from the nmigen Value + class. Complex to state, very simple in practice: + see test_buf_pipe.py for over 25 working examples. + + * ospec() - Output data format specification. + requirements identical to ispec + + * process(m, i) - Processes an ispec-formatted object/sequence returns a combinatorial block of a result that - may be assigned to the output, by way of the "eq" - function + may be assigned to the output, by way of the "nmoperator.eq" + function. Note that what is returned here can be + extremely flexible. Even a dictionary can be returned + as long as it has fields that match precisely with the + Record into which its values is intended to be assigned. + Again: see example unit tests for details. + * setup(m, i) - Optional function for setting up submodules may be used for more complex stages, to link the input (i) to submodules. must take responsibility @@ -40,7 +49,8 @@ Both StageCls (for use with non-static classes) and Stage (for use by static classes) are abstract classes from which, for convenience and as a courtesy to other developers, anything conforming to the - Stage API may *choose* to derive. + Stage API may *choose* to derive. See Liskov Substitution Principle: + https://en.wikipedia.org/wiki/Liskov_substitution_principle StageChain: ---------- @@ -56,6 +66,11 @@ Also has an extremely useful "connect" function that can be used to connect a chain of pipelines and present the exact same prev/next ready/valid/data API. + + Note: pipelines basically do not become pipelines as such until + handed to a derivative of ControlBase. ControlBase itself is *not* + strictly considered a pipeline class. Wishbone and AXI4 (master or + slave) could be derived from ControlBase, for example. """ from nmigen import Signal, Cat, Const, Mux, Module, Value, Elaboratable @@ -90,7 +105,7 @@ class Object: raise AttributeError(e) def __iter__(self): - for x in self.fields.values(): + for x in self.fields.values(): # OrderedDict so order is preserved if isinstance(x, Iterable): yield from x else: @@ -109,7 +124,7 @@ class Object: print (res) return res - def ports(self): + def ports(self): # being called "keys" would be much better return list(self) @@ -133,13 +148,13 @@ class RecordObject(Record): self.layout.fields.update(newlayout) def __iter__(self): - for x in self.fields.values(): + for x in self.fields.values(): # remember: fields is an OrderedDict if isinstance(x, Iterable): - yield from x + yield from x # a bit like flatten (nmigen.tools) else: yield x - def ports(self): + def ports(self): # would be better being called "keys" return list(self) @@ -158,16 +173,16 @@ class PrevControl(Elaboratable): may be a multi-bit signal, where all bits are required to be asserted to indicate "valid". * ready_o: output to next stage indicating readiness to accept data - * data_i : an input - added by the user of this class + * data_i : an input - MUST be added by the USER of this class """ def __init__(self, i_width=1, stage_ctl=False): self.stage_ctl = stage_ctl self.valid_i = Signal(i_width, name="p_valid_i") # prev >>in self - self._ready_o = Signal(name="p_ready_o") # prev <