@h2loop/autosar 1.2.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/agents/autosar-integrator.md +12 -0
- package/package.json +1 -1
- package/plugins/index.js +37 -30
- package/python/ecuc_engine/arxml_edit.py +163 -7
- package/python/ecuc_engine/arxml_new.py +113 -0
- package/python/ecuc_engine/cli.py +20 -2
- package/python/ecuc_engine/codegen/binding.py +41 -1
- package/python/ecuc_engine/codegen/bindings/sip_standin.json +118 -0
- package/python/ecuc_engine/codegen/modules/linif.py +53 -0
- package/python/ecuc_engine/codegen/registry.py +67 -37
- package/skills/autosar/SKILL.md +52 -0
- package/skills/autosar/references/codegen.md +18 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""LinIf: LinIf_Cfg.h / LinIf_PBcfg.c.
|
|
2
|
+
|
|
3
|
+
Def-driven (generic emitter): the LinIfGeneral switches and the TPS_ECUC_02108 / SWS_BSW_00200 symbols
|
|
4
|
+
LinIfConf_LinIfTxPdu_<Pdu> (LinIfTxPduId, the handle PduR passes to LinIf_Transmit) and
|
|
5
|
+
LinIfConf_LinIfScheduleTable_<Table> (LinIfScheduleTableIndex, used with LinIf_ScheduleRequest).
|
|
6
|
+
|
|
7
|
+
The static LinIf's own layout (frame table, one entry list per schedule table, schedule table list,
|
|
8
|
+
root config object) comes from its binding (bindings/*.json): channels, frames with their EcuC PDU
|
|
9
|
+
length and PduR handle (via the shared EcucPduCollection/Pdu), schedule entries in LinIfEntryIndex
|
|
10
|
+
order with LinIfDelay, schedule tables by LinIfScheduleTableIndex. Configuration the binding cannot
|
|
11
|
+
represent (non-unconditional frames, slave nodes, more channels than the static code has, ...) is
|
|
12
|
+
listed in the binding's `require` / `unsupported` and fails generation.
|
|
13
|
+
|
|
14
|
+
This module adds only the SWS_LinIf consistency rules that hold for any static code:
|
|
15
|
+
* a schedule entry (LinIfEntry/LinIfFrameRef) must reference a frame of the schedule table's own
|
|
16
|
+
channel (ECUC_LinIf_00016; schedule tables are per channel, ECUC_LinIf_00365);
|
|
17
|
+
* the LinIfFrameId of the unconditional frames of a channel must be unique (one publisher per
|
|
18
|
+
frame identifier on a LIN cluster).
|
|
19
|
+
"""
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
from ..registry import Generator, register
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _channel(c):
|
|
26
|
+
while c is not None and c.def_name != "LinIfChannel":
|
|
27
|
+
c = c.parent
|
|
28
|
+
return c
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@register("LinIf")
|
|
32
|
+
class LinIf(Generator):
|
|
33
|
+
std_header = "ComStack_Types.h"
|
|
34
|
+
|
|
35
|
+
def specific(self, mo):
|
|
36
|
+
for e in self.cg.instances(self.mc, "LinIfEntry"):
|
|
37
|
+
fr = self.cg.target(e.value("LinIfFrameRef"))
|
|
38
|
+
if fr is None:
|
|
39
|
+
mo.errors.append(f"{e.path}: LinIfFrameRef is not set or does not resolve to a LinIfFrame")
|
|
40
|
+
elif _channel(fr) is not _channel(e):
|
|
41
|
+
mo.errors.append(f"{e.path}: LinIfFrameRef points to {fr.path}, a frame of another channel "
|
|
42
|
+
f"(schedule tables are per channel, ECUC_LinIf_00365)")
|
|
43
|
+
for ch in self.cg.instances(self.mc, "LinIfChannel"):
|
|
44
|
+
seen: dict = {}
|
|
45
|
+
for fr in ch.sub("LinIfFrame"):
|
|
46
|
+
if (fr.text("LinIfFrameType") or "").strip() != "UNCONDITIONAL":
|
|
47
|
+
continue
|
|
48
|
+
fid = (fr.text("LinIfFrameId") or "").strip()
|
|
49
|
+
if fid in seen:
|
|
50
|
+
mo.errors.append(f"{fr.path}: LinIfFrameId {fid} is also used by {seen[fid]} on channel "
|
|
51
|
+
f"{ch.name}; unconditional frame identifiers must be unique per channel")
|
|
52
|
+
else:
|
|
53
|
+
seen[fid] = fr.name
|
|
@@ -98,10 +98,11 @@ def apply_binding(cg, mo: E.ModuleOutput, mb: dict, ext: Optional[dict] = None):
|
|
|
98
98
|
f"{', '.join('(not configured)' if x is None else str(x) for x in req['in'])}: {req.get('why', '')}")
|
|
99
99
|
for un in mb.get("unsupported", []):
|
|
100
100
|
rows = cg.instances(mo.mc, un["rows"])
|
|
101
|
-
|
|
101
|
+
mx = un.get("max", 0)
|
|
102
|
+
if len(rows) > mx:
|
|
102
103
|
mo.errors.append(f"{len(rows)} {un['rows']} container(s) configured ({', '.join(r.name for r in rows[:5])}"
|
|
103
104
|
f"{', ...' if len(rows) > 5 else ''}), which the {mb['_binding']} static code cannot "
|
|
104
|
-
f"represent: {un.get('why', '')}")
|
|
105
|
+
f"represent{f' (at most {mx})' if mx else ''}: {un.get('why', '')}")
|
|
105
106
|
for inc in mb.get("sourceIncludes", []):
|
|
106
107
|
mo.include(inc)
|
|
107
108
|
macros = []
|
|
@@ -121,41 +122,9 @@ def apply_binding(cg, mo: E.ModuleOutput, mb: dict, ext: Optional[dict] = None):
|
|
|
121
122
|
name = vs["name"].replace("{}", r.name)
|
|
122
123
|
lines.append(f"{'static ' if vs.get('static') else ''}VAR({vs['type']}, {vs['qualifier']}) {name}[{size}];")
|
|
123
124
|
pending.append(("var", ev.rank, vs.get("section", "VAR_NOINIT_UNSPECIFIED"), "\n".join(lines)))
|
|
124
|
-
for
|
|
125
|
-
ev
|
|
126
|
-
|
|
127
|
-
if t.get("order"):
|
|
128
|
-
from ..values import parse_int
|
|
129
|
-
rows.sort(key=lambda r: (parse_int(r.text(t["order"]) or "") is None, parse_int(r.text(t["order"]) or "") or 0))
|
|
130
|
-
lines, externs = [], []
|
|
131
|
-
des = t.get("designated")
|
|
132
|
-
if des:
|
|
133
|
-
_check_index(cg, mo, t, rows, des, values)
|
|
134
|
-
for r in rows:
|
|
135
|
-
vals = []
|
|
136
|
-
for f in t["fields"]:
|
|
137
|
-
v, _ = ev.field(r, f)
|
|
138
|
-
vals.append(v)
|
|
139
|
-
if f.get("extern") and v not in ("NULL_PTR", "0", "0u") and not v.startswith('"'):
|
|
140
|
-
m = re.search(r"[A-Za-z_]\w*", v)
|
|
141
|
-
if m:
|
|
142
|
-
ext_ = "extern " + f["extern"].replace("{}", m.group(0)) + ";"
|
|
143
|
-
if ext_ not in externs:
|
|
144
|
-
externs.append(ext_)
|
|
145
|
-
lead = ""
|
|
146
|
-
if des:
|
|
147
|
-
lead = f"[{des.replace('{sym}', cg.symbol(r)) if isinstance(des, str) else cg.symbol(r)}] = "
|
|
148
|
-
comment = t.get("comment", "name")
|
|
149
|
-
cm = {"name": r.name, "sym": cg.symbol(r) or r.name}.get(comment, r.name)
|
|
150
|
-
if t.get("scalar"):
|
|
151
|
-
lines.append(f" {lead}{vals[0]} /* {cm} */")
|
|
152
|
-
else:
|
|
153
|
-
lines.append(f" {lead}{{ {', '.join(vals)} }} /* {cm} */")
|
|
154
|
-
st = "static " if t.get("static") else ""
|
|
155
|
-
size = t.get("size", "")
|
|
156
|
-
body = (f"/* {t.get('doc', t['rows'])} */\n{st}CONST({t['type']}, {t['qualifier']}) {t['name']}[{size}] = {{\n" +
|
|
157
|
-
",\n".join(lines) + "\n};")
|
|
158
|
-
pending.append(("table", ev.rank, body, externs))
|
|
125
|
+
for t0 in mb.get("tables", []):
|
|
126
|
+
for t, rows in _table_instances(cg, mo, ev, t0, sets):
|
|
127
|
+
_emit_table(cg, mo, ev, t, rows, values, pending)
|
|
159
128
|
objects = mb.get("objects", [])
|
|
160
129
|
if objects:
|
|
161
130
|
# a root config object points at the (static) tables and buffers, so they all live in its file:
|
|
@@ -173,6 +142,67 @@ def apply_binding(cg, mo: E.ModuleOutput, mb: dict, ext: Optional[dict] = None):
|
|
|
173
142
|
mo.used_mips |= ev.used_mips
|
|
174
143
|
|
|
175
144
|
|
|
145
|
+
def _table_instances(cg, mo, ev, t: dict, sets: dict) -> list:
|
|
146
|
+
"""[(table spec, rows)]: one table, or one per parent instance for a "per" table."""
|
|
147
|
+
from ..values import parse_int
|
|
148
|
+
num = lambda r: parse_int(r.text(t["order"]) or "") # noqa: E731
|
|
149
|
+
out = []
|
|
150
|
+
if t.get("per"):
|
|
151
|
+
specs = []
|
|
152
|
+
for par in cg.sorted_instances(mo.mc, t["per"]):
|
|
153
|
+
rows = par.sub(t["rows"])
|
|
154
|
+
if not rows:
|
|
155
|
+
raise B.BindingError(f"{par.path}: no {t['rows']} configured; {t['name'].replace('{}', par.name)} "
|
|
156
|
+
"would be an empty array, which C does not allow")
|
|
157
|
+
specs.append((dict(t, name=t["name"].replace("{}", par.name),
|
|
158
|
+
doc=t.get("doc", t["rows"]).replace("{}", par.name)), rows))
|
|
159
|
+
else:
|
|
160
|
+
specs = [(t, ev.rows(t["rows"], sets))]
|
|
161
|
+
for spec, rows in specs:
|
|
162
|
+
if t.get("order"):
|
|
163
|
+
rows = sorted(rows, key=lambda r: (num(r) is None, num(r) or 0))
|
|
164
|
+
if t.get("contiguous"):
|
|
165
|
+
got = [num(r) for r in rows]
|
|
166
|
+
if got != list(range(len(rows))):
|
|
167
|
+
raise B.BindingError(f"{spec['name']}: {t['order']} of the {len(rows)} {t['rows']} rows must be exactly "
|
|
168
|
+
f"0..{len(rows) - 1} (table position), got {', '.join(map(str, got))}")
|
|
169
|
+
out.append((spec, rows))
|
|
170
|
+
return out
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _emit_table(cg, mo, ev, t: dict, rows: list, values: dict, pending: list):
|
|
174
|
+
ev.rank = 1
|
|
175
|
+
lines, externs = [], []
|
|
176
|
+
des = t.get("designated")
|
|
177
|
+
if des:
|
|
178
|
+
_check_index(cg, mo, t, rows, des, values)
|
|
179
|
+
for r in rows:
|
|
180
|
+
vals = []
|
|
181
|
+
for f in t["fields"]:
|
|
182
|
+
v, _ = ev.field(r, f)
|
|
183
|
+
vals.append(v)
|
|
184
|
+
if f.get("extern") and v not in ("NULL_PTR", "0", "0u") and not v.startswith('"'):
|
|
185
|
+
m = re.search(r"[A-Za-z_]\w*", v)
|
|
186
|
+
if m:
|
|
187
|
+
ext_ = "extern " + f["extern"].replace("{}", m.group(0)) + ";"
|
|
188
|
+
if ext_ not in externs:
|
|
189
|
+
externs.append(ext_)
|
|
190
|
+
lead = ""
|
|
191
|
+
if des:
|
|
192
|
+
lead = f"[{des.replace('{sym}', cg.symbol(r)) if isinstance(des, str) else cg.symbol(r)}] = "
|
|
193
|
+
comment = t.get("comment", "name")
|
|
194
|
+
cm = {"name": r.name, "sym": cg.symbol(r) or r.name}.get(comment, r.name)
|
|
195
|
+
if t.get("scalar"):
|
|
196
|
+
lines.append(f" {lead}{vals[0]} /* {cm} */")
|
|
197
|
+
else:
|
|
198
|
+
lines.append(f" {lead}{{ {', '.join(vals)} }} /* {cm} */")
|
|
199
|
+
st = "static " if t.get("static") else ""
|
|
200
|
+
size = t.get("size", "")
|
|
201
|
+
body = (f"/* {t.get('doc', t['rows'])} */\n{st}CONST({t['type']}, {t['qualifier']}) {t['name']}[{size}] = {{\n" +
|
|
202
|
+
",\n".join(lines) + "\n};")
|
|
203
|
+
pending.append(("table", ev.rank, body, externs))
|
|
204
|
+
|
|
205
|
+
|
|
176
206
|
def _check_index(cg, mo, t: dict, rows: list, des, values: dict):
|
|
177
207
|
"""A designated table is indexed by handle (minus an offset): every row must land in [0, size) exactly once,
|
|
178
208
|
or the static code's table lookup would be wrong. Reported as an error, never renumbered here."""
|
package/skills/autosar/SKILL.md
CHANGED
|
@@ -21,6 +21,8 @@ in `Output/` is derived from it; in-house code in `Source/` calls the generated
|
|
|
21
21
|
1. **Never hand-write or hand-edit ARXML** (no `write`/`edit`/`sed` on `.arxml`; the pack blocks them). Every change goes
|
|
22
22
|
through `ecuc_edit`, which picks the value element, DEFINITION-REF/DEST and VALUE-REF DEST from
|
|
23
23
|
the param defs and patches only the changed bytes. Reading raw ARXML for context is fine; prefer `ecuc_read`.
|
|
24
|
+
A **new** System-extract / SWC / interface file is started with `arxml_new` and filled with `arxml_edit` (recipe
|
|
25
|
+
below). Do not write one with Python (`autosar_data` scripts, ElementTree) or a temp file renamed to `.arxml`.
|
|
24
26
|
2. **Validate after every edit**: `ecuc_validate` (scoped with `files`/`module` if large). Fix
|
|
25
27
|
every error you introduced before moving on; report pre-existing ones separately.
|
|
26
28
|
3. **Cite** the AUTOSAR path, the DEFINITION-REF and file:line for every element you discuss or change —
|
|
@@ -60,6 +62,8 @@ in `Output/` is derived from it; in-house code in `Source/` calls the generated
|
|
|
60
62
|
| Values of a module/container | `ecuc_read path=… depth=…` |
|
|
61
63
|
| All containers matching a condition / referencing X / referenced by Y | `ecuc_find` |
|
|
62
64
|
| Cross-check one module against the extract, C types and memory | `ecuc_crosscheck module=…` |
|
|
65
|
+
| Start a NEW System extract / SWC / interface .arxml file | `arxml_new file=… packages=[…]` |
|
|
66
|
+
| Verify extract / SWC / interface files (schema + every reference + DEST) | `arxml_check` |
|
|
63
67
|
| Edit System extract / SWC / interface XML | `arxml_edit` (DEST inferred, schema-ordered, refs checked) |
|
|
64
68
|
| Add a signal end to end (ECUC + extract + DBC) | `autosar_add_signal` |
|
|
65
69
|
| What may be set/added here (types, ranges, literals, multiplicity) | `ecuc_read path=… schema=true`, or a def path `/AUTOSAR/EcucDefs/<Mod>/…` |
|
|
@@ -87,6 +91,54 @@ in `Output/` is derived from it; in-house code in `Source/` calls the generated
|
|
|
87
91
|
5. **Never conclude "no faults" from a single validate call**, and never finish with a failing validation: after
|
|
88
92
|
ANY edit run `ecuc_validate`; if it fails, fix it before answering.
|
|
89
93
|
|
|
94
|
+
## Every change: ground → decide → change → verify until clean
|
|
95
|
+
Do not decide what to change from memory or from the prompt alone. Each change goes through four steps, in order:
|
|
96
|
+
1. **Ground (facts first).** Gather every fact the change depends on from the tools, not from recall:
|
|
97
|
+
`autosar_build_context` (for a runnable), `ecuc_read … schema=true` (what may be set: types, ranges, literals,
|
|
98
|
+
multiplicity), `ecuc_find` / `autosar_config_lookup` (what already exists and references what),
|
|
99
|
+
`ecuc_crosscheck` (extract ↔ ECUC ↔ C), the spec text (`autosar_spec_id_check` for any requirement ID you cite).
|
|
100
|
+
Write the facts down in a short list with their source (file:line or tool), including the existing elements you
|
|
101
|
+
will reuse or reference.
|
|
102
|
+
2. **Decide.** From those facts only, write the plan as a todo list: every element to add/change, in dependency order
|
|
103
|
+
(reference targets first), and which tool does each. A link you could not ground (a value, an id, a target) is an
|
|
104
|
+
open question: look it up, or ask; never fill it in with a plausible guess.
|
|
105
|
+
3. **Change** with the structured tools only (`ecuc_edit`, `arxml_new` + `arxml_edit`, `autosar_add_signal`). Prefer
|
|
106
|
+
one call per coherent change; nothing is written if any op fails.
|
|
107
|
+
4. **Verify → fix → verify, until clean.** `arxml_check` (extract/SWC files) and `ecuc_validate` (ECUC), then
|
|
108
|
+
`autosar_generate` + `autosar_codegen_diff` / `autosar_build` and `autosar_verify_rte` where the project has them.
|
|
109
|
+
On any problem: read it, go back to step 1 for that fact, fix with the structured tools, verify again. Repeat until
|
|
110
|
+
every check is clean. Then re-read the request and tick each todo against the evidence. Never report done with a
|
|
111
|
+
failing or unrun check; if something cannot be made clean, say exactly what and why.
|
|
112
|
+
|
|
113
|
+
## New ARXML file (SWC, interface, data types, extract) from nothing
|
|
114
|
+
1. `arxml_new file="Input/SWC_X.arxml" packages=["/DataTypes", "/Interfaces", "/Swcs"]` — the R25-11 header and
|
|
115
|
+
empty packages, strictly checked. It refuses to overwrite; extend existing files with `arxml_edit` instead.
|
|
116
|
+
2. ONE `arxml_edit` call with the elements in dependency order (a reference target must be added earlier in the same
|
|
117
|
+
call): base type → implementation data type → interface → SWC with ports → `SWC-INTERNAL-BEHAVIOR` → runnables
|
|
118
|
+
(with data accesses) → events. Each op is `{op:"add", parent_path, element:<XML tag>, short_name, values:{...}}`;
|
|
119
|
+
references are written `"->/Path/To/Target"` and get their DEST automatically. Example (shortened):
|
|
120
|
+
```
|
|
121
|
+
{op:"add", parent_path:"/DataTypes", element:"SW-BASE-TYPE", short_name:"uint8_base",
|
|
122
|
+
values:{"CATEGORY":"FIXED_LENGTH", "BASE-TYPE-SIZE":8, "BASE-TYPE-ENCODING":"NONE"}}
|
|
123
|
+
{op:"add", parent_path:"/DataTypes", element:"IMPLEMENTATION-DATA-TYPE", short_name:"uint8",
|
|
124
|
+
values:{"CATEGORY":"VALUE", "SW-DATA-DEF-PROPS":{"SW-DATA-DEF-PROPS-VARIANTS":{"SW-DATA-DEF-PROPS-CONDITIONAL":
|
|
125
|
+
{"BASE-TYPE-REF":"->/DataTypes/uint8_base"}}}}}
|
|
126
|
+
{op:"add", parent_path:"/Interfaces", element:"SENDER-RECEIVER-INTERFACE", short_name:"If_X",
|
|
127
|
+
values:{"DATA-ELEMENTS":{"VARIABLE-DATA-PROTOTYPE":[{"SHORT-NAME":"Val", "TYPE-TREF":"->/DataTypes/uint8"}]}}}
|
|
128
|
+
{op:"add", parent_path:"/Swcs", element:"APPLICATION-SW-COMPONENT-TYPE", short_name:"X",
|
|
129
|
+
values:{"PORTS":{"P-PORT-PROTOTYPE":{"SHORT-NAME":"PpX", "PROVIDED-INTERFACE-TREF":"->/Interfaces/If_X"}}}}
|
|
130
|
+
{op:"add", parent_path:"/Swcs/X", element:"SWC-INTERNAL-BEHAVIOR", short_name:"IB"}
|
|
131
|
+
{op:"add", parent_path:"/Swcs/X/IB", element:"RUNNABLE-ENTITY", short_name:"X_Run10ms", values:{"SYMBOL":"X_Run10ms",
|
|
132
|
+
"DATA-WRITE-ACCESSS":{"VARIABLE-ACCESS":{"SHORT-NAME":"W_Val", "ACCESSED-VARIABLE":{"AUTOSAR-VARIABLE-IREF":
|
|
133
|
+
{"PORT-PROTOTYPE-REF":"->/Swcs/X/PpX", "TARGET-DATA-PROTOTYPE-REF":"->/Interfaces/If_X/Val"}}}}}}
|
|
134
|
+
{op:"add", parent_path:"/Swcs/X/IB", element:"TIMING-EVENT", short_name:"TE_10ms",
|
|
135
|
+
values:{"START-ON-EVENT-REF":"->/Swcs/X/IB/X_Run10ms", "PERIOD":0.01}}
|
|
136
|
+
```
|
|
137
|
+
3. If an op is rejected, read the error: it names the allowed sub-elements of that parent. Fix that op and resend
|
|
138
|
+
the call (nothing was written). Do not fall back to writing XML.
|
|
139
|
+
4. `arxml_check` until it says CLEAN (and `ecuc_validate` / `autosar_generate` / `autosar_build` when the project
|
|
140
|
+
has ECUC and a generator). Then tick every requested element against the file.
|
|
141
|
+
|
|
90
142
|
## The loop
|
|
91
143
|
`ecuc_read (schema) → ecuc_edit → ecuc_validate → autosar_generate → arxml_diff / inspect Output → autosar_build → autosar_trace (impact on Source/)`.
|
|
92
144
|
Details and failure handling: `references/workflow.md`.
|
|
@@ -37,12 +37,30 @@ ComUserCallback of type COM_RX_ACK / COM_TX_ACK; `call:comUserCallback`), or, fo
|
|
|
37
37
|
callbacks, the RTE's `Rte_COMCbk_<sn>()` / `Rte_COMCbkTAck_<sn>()` when the RTE's Rte_Cbk.h declares it
|
|
38
38
|
(`call:rteSignalCallback`). Nothing is bound from guesses: no declaration, no callback.
|
|
39
39
|
|
|
40
|
+
## LinIf
|
|
41
|
+
`LinIf_Cfg.h`: LinIfGeneral switches, `LinIfConf_LinIfTxPdu_*` (LinIfTxPduId, the handle PduR passes to `LinIf_Transmit`) and
|
|
42
|
+
`LinIfConf_LinIfScheduleTable_*` (LinIfScheduleTableIndex) symbols (TPS_ECUC_02108 / SWS_BSW_00200), `LINIF_NUMBER_OF_*`.
|
|
43
|
+
`LinIf_PBcfg.c` (binding): frame table in configuration order (LinIfFrameId, length from the EcuC Pdu, checksum, direction
|
|
44
|
+
from the LinIfPduDirection choice, PduR dest (Tx) / src (Rx) handle via the shared EcuC Pdu), one entry list per schedule
|
|
45
|
+
table (`per` table, LinIfEntryIndex order, which must be 0..n-1; FrameIndex = position of LinIfFrameRef's frame;
|
|
46
|
+
LinIfDelay s -> ms, a non-whole ms is an error), schedule list indexed by LinIfScheduleTableIndex, root `LinIf_Config`.
|
|
47
|
+
Tx PDU handles are laid out 0..n-1 (handleLayout; `LinIf_Transmit` range-checks them).
|
|
48
|
+
Errors, never dropped: frame types other than UNCONDITIONAL, PDU directions other than Tx/Rx, RUN_ONCE schedules, more
|
|
49
|
+
than one channel, slave nodes, substitution frames, fixed frame SDUs (stand-in binding); an entry whose frame belongs to
|
|
50
|
+
another channel, duplicate unconditional LinIfFrameIds on a channel (any binding).
|
|
51
|
+
|
|
52
|
+
Binding path/table additions used by LinIf: `child` (chosen sub-container of a choice), `def` (its def name, mapped with
|
|
53
|
+
`enum`), `count:<Def>`, field `scale`, table `per` / `contiguous`, `unsupported[].max`.
|
|
54
|
+
|
|
40
55
|
## Known differences from the sample/large fixture oracle (all explained)
|
|
41
56
|
| Item | Oracle | Ours | Why |
|
|
42
57
|
|---|---|---|---|
|
|
43
58
|
| `NvM_BlockDescriptorTable[*].RamBlockDataAddress` | `X` | `&X` (as configured) | ECUC_NvM_00482 value is the address expression; kept verbatim, same address for arrays |
|
|
44
59
|
| Rx I-PDU `TimeoutTicks` with mixed signal timeouts | largest ComTimeout | smallest non-zero | SWS_Com_00291 |
|
|
45
60
|
| `<MIP>_CFG_*` version macros, generic ComGeneral/NvMCommon/... switches, Dem/Fee tables | absent | extra | def-driven output the oracle does not emit |
|
|
61
|
+
| LinIf entry list name | `LinIf_Sched_<Table>` | `LinIf_Entries_<Table>` | `static` table, internal linkage: not part of the LinIf.h contract |
|
|
62
|
+
| `LinSMConf_LinSMSchedule_*` in `LinIf_Cfg.h` | present | absent (in `LinSM_Cfg.h`) | a `LinSMConf_` symbol belongs to the LinSM config header (SWS_BSW_00200) |
|
|
63
|
+
| `LINIF_NUMBER_OF_SCHEDULES`, LinIfGeneral switches, version macros | absent | extra | def/binding-driven output the oracle does not emit |
|
|
46
64
|
| SchM main function names | `Com_MainFunctionTx` | same | SWS_Com says `Com_MainFunctionTx_<shortName>`; the instance named like its def keeps the SIP's legacy name |
|
|
47
65
|
|
|
48
66
|
## Reading a diff
|