make Stage.process optional
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 29 Apr 2019 02:28:52 +0000 (03:28 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 29 Apr 2019 02:28:52 +0000 (03:28 +0100)
src/add/iocontrol.py
src/add/singlepipe.py

index ea5bc43e4f24950b45e49f7d737e5cae25488e32..874d16c3d36a817f0c8a5b1714ffcd1b73e38491 100644 (file)
     stage requires compliance with a strict API that may be
     implemented in several means, including as a static class.
 
+    Stages do not HOLD data, and they definitely do not contain
+    signalling (ready/valid).  They do however specify the FORMAT
+    of the incoming and outgoing data, and they provide a means to
+    PROCESS that data (from incoming format to outgoing format).
+
     Stage Blocks really must be combinatorial blocks.  It would be ok
     to have input come in from sync'd sources (clock-driven) however by
     doing so they would no longer be deterministic, and chaining such
                 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.
+                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 worked examples.
 
     * ospec() - Output data format specification.
-                requirements identical to ispec
+                format requirements identical to ispec.
 
-    * process(m, i) - Processes an ispec-formatted object/sequence
+    * process(m, i) - Optional function for processing ispec-formatted data.
                 returns a combinatorial block of a result that
                 may be assigned to the output, by way of the "nmoperator.eq"
                 function.  Note that what is returned here can be
@@ -39,7 +45,7 @@
                 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
+    * 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
                 for adding those submodules to the module (m).
@@ -321,8 +327,8 @@ class StageCls(metaclass=ABCMeta):
     def ospec(self): pass       # REQUIRED
     #@abstractmethod
     #def setup(self, m, i): pass # OPTIONAL
-    @abstractmethod
-    def process(self, i): pass  # REQUIRED
+    #@abstractmethod
+    #def process(self, i): pass  # REQUIRED
 
 
 class Stage(metaclass=ABCMeta):
@@ -345,9 +351,9 @@ class Stage(metaclass=ABCMeta):
     #@abstractmethod
     #def setup(m, i): pass
 
-    @staticmethod
-    @abstractmethod
-    def process(i): pass
+    #@staticmethod
+    #@abstractmethod
+    #def process(i): pass
 
 
 class StageChain(StageCls):
@@ -544,7 +550,9 @@ class ControlBase(Elaboratable):
 
     @property
     def data_r(self):
-        return self.stage.process(self.p.data_i)
+        if self.stage and hasattr(self.stage, "process"):
+            return self.stage.process(self.p.data_i)
+        return self.p.data_i
 
     def _postprocess(self, i): # XXX DISABLED
         return i # RETURNS INPUT
index 5f7dc66ba23679ddb5b783ac395d99782bfbc7b2..5808d8a9a730c8eed7c688384dd723812ce0060a 100644 (file)
@@ -500,11 +500,9 @@ class PassThroughStage(StageCls):
         (many APIs would potentially use a static "wrap" method in e.g.
          StageCls to achieve a similar effect)
     """
-    def __init__(self, iospecfn):
-        self.iospecfn = iospecfn
+    def __init__(self, iospecfn): self.iospecfn = iospecfn
     def ispec(self): return self.iospecfn()
     def ospec(self): return self.iospecfn()
-    def process(self, i): return i
 
 
 class PassThroughHandshake(ControlBase):