Revisión | b9f08b6a491674a1e30aef817a005ed5dd8c2815 (tree) |
---|---|
Tiempo | 2023-10-11 20:25:14 |
Autor | Albert Mietus < albert AT mietus DOT nl > |
Commiter | Albert Mietus < albert AT mietus DOT nl > |
'Port.port_no' (aka PortNo) --and auto-numbering-- is gone/unneeded. Documented reasoning
@@ -0,0 +1,102 @@ | ||
1 | +PortNumbers: not needed in the AIGR nor RPy | |
2 | +******************************************* | |
3 | + | |
4 | +Summary | |
5 | +======= | |
6 | + | |
7 | +After a successful try with (optional) *AutoNumbering*, I decided that the **port_number** *(a low int)* is an unneeded | |
8 | +leftover of the once “handCompiled-C” version. It isn't needed in general. And so, -as we don’t store/use *portNo*-- the | |
9 | +auto-numbering option is removed (but documented, as it might be convenient later). | |
10 | + | |
11 | +Background | |
12 | +---------- | |
13 | + | |
14 | +In the (handCompiled) C version, everything is stored in an C-array; and we have to use (array) indexes to find the | |
15 | +element. Therefore, those port numbers (as index) have to be unique, contiguous “low” numbers. In general, this is | |
16 | +inconvenient. When a base-component(interface) changes the number of ports, all other have to be renumbered. | |
17 | +|BR| | |
18 | +That is fine for (generated) C-code, but unwanted in e.g the AIGR-model. | |
19 | + | |
20 | +Also the *Sieve_in_rPython* variant has those index ``portNo``’s -- although with a question-mark. And thy are never | |
21 | +used. | |
22 | +|BR| | |
23 | +Arrays in (r)Python are list and can be indexed with (e.g.) a name. Such a ``nameID`` is more convenient, and the Castle | |
24 | +semantics already secures uniqueness. | |
25 | + | |
26 | +Thus,the RPy backend doesn't need to render ‘PortNo’ (see | |
27 | +file:`castle/writers/RPy/templates/parts/interface_DataStructures.jinja2`) and hence doesn't need in the AIGR either. | |
28 | + | |
29 | + | |
30 | +AutoNumbering | |
31 | +============== | |
32 | + | |
33 | +I have made a variant of :file:`castle/aigr/interfaces.py` to support automatically numbering of port. It quite simple. | |
34 | + | |
35 | +* We need to store the `port_no` in ``Port`` and with a default marker: `_AUTO_NUMBER`. | |
36 | +* In ``ComponentInterface``, in the post_init a call to ``_number_auto_ports()`` is make | |
37 | +* That method add portNo’s to the ports of that instance. After some basic checks. | |
38 | + |BR| | |
39 | + Note, the routine isn't perfect - there are complex edge cases that are ignored. | |
40 | + | |
41 | +.. code-block:: ReasonML | |
42 | + :emphasize-lines: 3,8 | |
43 | + | |
44 | + @dataclass | |
45 | + class Port(AIGR): | |
46 | + _AUTO_NUMBER=-1 | |
47 | + name: str | |
48 | + _: KW_ONLY | |
49 | + direction: PortDirection | |
50 | + type: PortType | |
51 | + port_no: int=_AUTO_NUMBER # automatically set in ComponentInterface | |
52 | + | |
53 | + | |
54 | +.. code-block:: ReasonML | |
55 | + :emphasize-lines: 4,7 | |
56 | + | |
57 | + @dataclass | |
58 | + class ComponentInterface(AIGR): | |
59 | + ... | |
60 | + def __post_init__(self): | |
61 | + self._number_auto_ports() | |
62 | + | |
63 | + def _number_auto_ports(self): | |
64 | + all_auto = all(p.port_no == Port._AUTO_NUMBER for p in self.ports) | |
65 | + if all_auto: | |
66 | + start = self.based_on._noPorts() if isinstance(self.based_on, ComponentInterface) else 0 | |
67 | + for n, p in enumerate(self.ports, start=start): | |
68 | + p.port_no = n | |
69 | + else: | |
70 | + any_auto =any(p.port_no == Port._AUTO_NUMBER for p in self.ports) | |
71 | + assert not any_auto, "Do not mix automatic port-numbering with pre-set ones. Typically, use set all!!" | |
72 | + | |
73 | +.. error:: AutoNumbering is tricky | |
74 | + | |
75 | + During the development, all kind of complex edge cases are found. As the feature is removed, those checks are | |
76 | + (mostly) ignored. And covert by statements as “do not mix”, “use with care”, and “only during development”. | |
77 | + | |
78 | + Conceptually, all (the inherited and own/defined) ports should be numbered: 0, 1, 2 ... | |
79 | + |BR| | |
80 | + Whenever a portNo can be preset, that isn’t possible. Some corner cases: | |
81 | + | |
82 | + * The pre-set numbers of two ports can be te same. | |
83 | + | |
84 | + - Ignore in auto-numbering, as it can’t be fixed (here) | |
85 | + - Idea (not realised): write a checker (plugin) for the AIGR-model | |
86 | + - As a variant: those non unique numbers can be set in anywhere in inherit tree of `Components`. | |
87 | + | |
88 | + * Some portNo’s are set, others not | |
89 | + | |
90 | + - We kind of need to find the available numbers first | |
91 | + - Is there a reason that some numbers are skipped? Than do no use them -- complex | |
92 | + - Or, just continue at the highest port-no -- more holes | |
93 | + | |
94 | + * We need all kind of auxiliary methods for ComponentInterface, to handle port-numbering | |
95 | + | |
96 | + - Not *SOLID*: code becomes hard to maintain and misleading | |
97 | + - But, putting the in ``Port`` doesn't solve it | |
98 | + | |
99 | + | |
100 | +At the end, instead of “solving” those issues, I reconsidered the portNo attribute. By abandoning that left-over, all | |
101 | +those issues are solved too. | |
102 | + |
@@ -0,0 +1,9 @@ | ||
1 | +Some notes (LOCAL only) | |
2 | +======================= | |
3 | + | |
4 | + | |
5 | +.. toctree:: | |
6 | + :glob: | |
7 | + | |
8 | + * | |
9 | + */index |