tan-cli 0.7.0__py3-none-any.whl

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.
Files changed (330) hide show
  1. tan/__init__.py +0 -0
  2. tan/__main__.py +120 -0
  3. tan/cli.py +939 -0
  4. tan/command_table.py +265 -0
  5. tan/commands/__init__.py +8 -0
  6. tan/commands/bootstrap_cmd.py +4856 -0
  7. tan/commands/bootstrap_patches.py +164 -0
  8. tan/commands/bootstrap_toolchain_fetch.py +155 -0
  9. tan/commands/bootstrap_toolchain_pin.py +36 -0
  10. tan/commands/build/__init__.py +1 -0
  11. tan/commands/build/configure_inputs.py +277 -0
  12. tan/commands/build/execute.py +1852 -0
  13. tan/commands/build/host_python.py +59 -0
  14. tan/commands/build/link_stale.py +78 -0
  15. tan/commands/build/manifest.py +428 -0
  16. tan/commands/build/materialise.py +81 -0
  17. tan/commands/build/token_substitution.py +381 -0
  18. tan/commands/build/toolchain.py +482 -0
  19. tan/commands/build/user_defines_wipe.py +115 -0
  20. tan/commands/build/workspace_patches.py +65 -0
  21. tan/commands/build_cmd.py +2236 -0
  22. tan/commands/build_output.py +331 -0
  23. tan/commands/clean_cmd.py +1183 -0
  24. tan/commands/completion_cmd.py +786 -0
  25. tan/commands/debug_config_cmd.py +2425 -0
  26. tan/commands/diff_cmd.py +940 -0
  27. tan/commands/doctor_cmd.py +4767 -0
  28. tan/commands/examples_cmd.py +644 -0
  29. tan/commands/explain_cmd.py +1319 -0
  30. tan/commands/faultdecode_cmd.py +931 -0
  31. tan/commands/flash_atoc_guard.py +240 -0
  32. tan/commands/flash_cmd.py +5731 -0
  33. tan/commands/flash_mram_guard.py +150 -0
  34. tan/commands/flash_ram.py +578 -0
  35. tan/commands/flash_raw.py +583 -0
  36. tan/commands/generate_cmd.py +1456 -0
  37. tan/commands/image_cmd.py +753 -0
  38. tan/commands/init_cmd.py +1740 -0
  39. tan/commands/inspect_cmd.py +377 -0
  40. tan/commands/kconfig_cmd.py +734 -0
  41. tan/commands/model_cmd.py +1514 -0
  42. tan/commands/model_device_cmd.py +351 -0
  43. tan/commands/model_device_live.py +234 -0
  44. tan/commands/model_host_cmd.py +430 -0
  45. tan/commands/model_zoo_cmd.py +363 -0
  46. tan/commands/monitor_actions.py +125 -0
  47. tan/commands/monitor_cmd.py +626 -0
  48. tan/commands/monitor_session.py +505 -0
  49. tan/commands/new_som_cmd.py +1522 -0
  50. tan/commands/pinmux_cmd.py +568 -0
  51. tan/commands/presets_cmd.py +1123 -0
  52. tan/commands/probe_cmd.py +421 -0
  53. tan/commands/reset_cmd.py +354 -0
  54. tan/commands/reset_confirm.py +168 -0
  55. tan/commands/run_cmd.py +637 -0
  56. tan/commands/scaffold_cmd.py +490 -0
  57. tan/commands/sdk_cmd.py +1723 -0
  58. tan/commands/size_cmd.py +1020 -0
  59. tan/commands/support_bundle_cmd.py +1073 -0
  60. tan/commands/trace_cmd.py +341 -0
  61. tan/commands/validate_cmd.py +2009 -0
  62. tan/commands/west_forward_cmd.py +736 -0
  63. tan/commands/workspace_patch_check.py +296 -0
  64. tan/core/__init__.py +1 -0
  65. tan/core/alp_conf_pregen.py +100 -0
  66. tan/core/artifact_provenance.py +240 -0
  67. tan/core/atoc_guard.py +276 -0
  68. tan/core/atoc_guard_messages.py +232 -0
  69. tan/core/atoc_replacement.py +118 -0
  70. tan/core/atomic_write.py +178 -0
  71. tan/core/board_context.py +351 -0
  72. tan/core/board_diagnostic.py +111 -0
  73. tan/core/board_files.py +221 -0
  74. tan/core/board_validator.py +542 -0
  75. tan/core/board_validator_compat.py +196 -0
  76. tan/core/board_validator_run.py +129 -0
  77. tan/core/board_validator_schema.py +186 -0
  78. tan/core/board_validator_skew.py +46 -0
  79. tan/core/board_yaml_edit.py +295 -0
  80. tan/core/board_yaml_pos.py +118 -0
  81. tan/core/bootstrap.py +2572 -0
  82. tan/core/build_plan.py +625 -0
  83. tan/core/consent.py +104 -0
  84. tan/core/console_filter.py +245 -0
  85. tan/core/debug_launch.py +1803 -0
  86. tan/core/devicetree_lint.py +168 -0
  87. tan/core/dir_removal.py +229 -0
  88. tan/core/doctor_git.py +172 -0
  89. tan/core/doctor_libraries.py +253 -0
  90. tan/core/doctor_render.py +185 -0
  91. tan/core/doctor_scope.py +66 -0
  92. tan/core/doctor_setools.py +237 -0
  93. tan/core/doctor_stale.py +180 -0
  94. tan/core/document_guards.py +723 -0
  95. tan/core/dp_id.py +97 -0
  96. tan/core/elf_load.py +63 -0
  97. tan/core/error_catalog.py +171 -0
  98. tan/core/example_catalog.py +499 -0
  99. tan/core/example_facets.py +151 -0
  100. tan/core/faultdecode.py +521 -0
  101. tan/core/flash_plan.py +2501 -0
  102. tan/core/flow_d_report.py +381 -0
  103. tan/core/flow_d_uptime.py +164 -0
  104. tan/core/fs_confine.py +130 -0
  105. tan/core/global_flags.py +230 -0
  106. tan/core/host_python.py +210 -0
  107. tan/core/image_bundle.py +247 -0
  108. tan/core/inert.py +147 -0
  109. tan/core/jlink_binary.py +128 -0
  110. tan/core/jlink_probe.py +481 -0
  111. tan/core/jsonc_splice.py +404 -0
  112. tan/core/launch_provenance.py +257 -0
  113. tan/core/link_refusal.py +76 -0
  114. tan/core/metadata_schema.py +376 -0
  115. tan/core/model_check.py +227 -0
  116. tan/core/model_device.py +449 -0
  117. tan/core/model_doctor.py +198 -0
  118. tan/core/model_host.py +48 -0
  119. tan/core/model_list.py +112 -0
  120. tan/core/model_zoo.py +353 -0
  121. tan/core/module_template.py +340 -0
  122. tan/core/mram_link.py +87 -0
  123. tan/core/new_som_ospi.py +94 -0
  124. tan/core/os_class.py +159 -0
  125. tan/core/patch_paths.py +87 -0
  126. tan/core/pending.py +40 -0
  127. tan/core/plain_zephyr_plan.py +138 -0
  128. tan/core/plan_exec.py +373 -0
  129. tan/core/plan_tokens.py +600 -0
  130. tan/core/probe.py +155 -0
  131. tan/core/probe_plan.py +237 -0
  132. tan/core/proxy.py +168 -0
  133. tan/core/publish.py +31 -0
  134. tan/core/python_floor.py +178 -0
  135. tan/core/ram_run.py +694 -0
  136. tan/core/ram_watch.py +231 -0
  137. tan/core/raw_write.py +160 -0
  138. tan/core/reset_plan.py +56 -0
  139. tan/core/run.py +161 -0
  140. tan/core/scaffold.py +2203 -0
  141. tan/core/scaffold_selftest_identity.py +225 -0
  142. tan/core/sdk_default_registry.py +565 -0
  143. tan/core/sdk_discovery.py +996 -0
  144. tan/core/sdk_removal.py +465 -0
  145. tan/core/serial_actions.py +175 -0
  146. tan/core/serial_capture.py +185 -0
  147. tan/core/serial_url.py +45 -0
  148. tan/core/setools.py +608 -0
  149. tan/core/setools_scratch.py +243 -0
  150. tan/core/shapes.py +194 -0
  151. tan/core/size.py +610 -0
  152. tan/core/som_buildability.py +204 -0
  153. tan/core/som_schema_version.py +62 -0
  154. tan/core/subprocess_env.py +201 -0
  155. tan/core/sysbuild_image.py +94 -0
  156. tan/core/system_manifest.py +827 -0
  157. tan/core/text_layout.py +73 -0
  158. tan/core/timestamp.py +182 -0
  159. tan/core/tool_lookup.py +383 -0
  160. tan/core/toolchain_pin.py +117 -0
  161. tan/core/toolchain_provision.py +1224 -0
  162. tan/core/trusted_path.py +134 -0
  163. tan/core/uboot_breakin.py +154 -0
  164. tan/core/uri_reference.py +415 -0
  165. tan/core/user_defines.py +152 -0
  166. tan/core/venv.py +332 -0
  167. tan/core/west_patches.py +143 -0
  168. tan/core/west_workspace_refusal.py +159 -0
  169. tan/core/zephyr_env.py +124 -0
  170. tan/env.py +185 -0
  171. tan/envelope.py +647 -0
  172. tan/exit_codes.py +12 -0
  173. tan/lazy_typer.py +185 -0
  174. tan/model/__init__.py +2 -0
  175. tan/model/_gen_fixture.py +132 -0
  176. tan/model/adapters/__init__.py +116 -0
  177. tan/model/adapters/cpu.py +26 -0
  178. tan/model/adapters/deepx.py +94 -0
  179. tan/model/adapters/drpai.py +242 -0
  180. tan/model/adapters/ethos_u.py +951 -0
  181. tan/model/adapters/executorch.py +55 -0
  182. tan/model/analyze.py +694 -0
  183. tan/model/build.py +304 -0
  184. tan/model/check.py +682 -0
  185. tan/model/manifest.py +625 -0
  186. tan/model/measure.py +216 -0
  187. tan/model/npu_ops_validate.py +130 -0
  188. tan/model/package.py +125 -0
  189. tan/model/perf.py +635 -0
  190. tan/model/perf_apply.py +721 -0
  191. tan/model/prep.py +193 -0
  192. tan/model/sram_fit.py +502 -0
  193. tan/model/targets.py +374 -0
  194. tan/model/tensorio.py +287 -0
  195. tan/net.py +73 -0
  196. tan/output_format.py +213 -0
  197. tan/planner/__init__.py +219 -0
  198. tan/planner/aperture.py +202 -0
  199. tan/planner/buildplan.py +1092 -0
  200. tan/planner/camera_owner.py +192 -0
  201. tan/planner/cameras.py +132 -0
  202. tan/planner/carveout.py +755 -0
  203. tan/planner/cli.py +274 -0
  204. tan/planner/headers.py +315 -0
  205. tan/planner/kconfig.py +2435 -0
  206. tan/planner/kconfig_symbols.py +473 -0
  207. tan/planner/libraries.py +677 -0
  208. tan/planner/link_target.py +237 -0
  209. tan/planner/linux_ownership.py +216 -0
  210. tan/planner/loader.py +1525 -0
  211. tan/planner/manifest.py +116 -0
  212. tan/planner/memory.py +161 -0
  213. tan/planner/memregion.py +56 -0
  214. tan/planner/models.py +533 -0
  215. tan/planner/orchestrator.py +874 -0
  216. tan/planner/ownership.py +203 -0
  217. tan/planner/partition.py +1160 -0
  218. tan/planner/paths.py +32 -0
  219. tan/planner/plain_slice.py +139 -0
  220. tan/planner/project_emit/__init__.py +60 -0
  221. tan/planner/project_emit/bom_netlist.py +375 -0
  222. tan/planner/project_emit/dts.py +580 -0
  223. tan/planner/project_emit/hw_info.py +221 -0
  224. tan/planner/project_emit/native_sim.py +136 -0
  225. tan/planner/project_emit/west_libs.py +213 -0
  226. tan/planner/project_loader.py +264 -0
  227. tan/planner/sdk_capability.py +203 -0
  228. tan/planner/sdk_compat.py +395 -0
  229. tan/planner/secure.py +350 -0
  230. tan/planner/slugs.py +394 -0
  231. tan/planner/som_metadata.py +325 -0
  232. tan/planner/strict_loaders.py +131 -0
  233. tan/planner/template.py +1037 -0
  234. tan/planner/template_pins.py +535 -0
  235. tan/planner/template_rewrite.py +714 -0
  236. tan/planner/topology.py +208 -0
  237. tan/planner/validate.py +365 -0
  238. tan/planner/whole_device_alias.py +67 -0
  239. tan/planner/zephyr_board.py +3510 -0
  240. tan/planner_cli.py +97 -0
  241. tan/planner_emit.py +617 -0
  242. tan/planner_root.py +119 -0
  243. tan/soc_ref.py +58 -0
  244. tan/templates/__init__.py +34 -0
  245. tan/templates/vendored/MANIFEST.md +1862 -0
  246. tan/templates/vendored/diagnostics/E1M-AEN801/CMakeLists.txt +8 -0
  247. tan/templates/vendored/diagnostics/E1M-AEN801/README.md +112 -0
  248. tan/templates/vendored/diagnostics/E1M-AEN801/board.yaml +38 -0
  249. tan/templates/vendored/diagnostics/E1M-AEN801/boards/native_sim_native_64.conf +11 -0
  250. tan/templates/vendored/diagnostics/E1M-AEN801/boards/native_sim_native_64.overlay +29 -0
  251. tan/templates/vendored/diagnostics/E1M-AEN801/prj.conf +5 -0
  252. tan/templates/vendored/diagnostics/E1M-AEN801/src/main.c +266 -0
  253. tan/templates/vendored/diagnostics/E1M-AEN801/testcase.yaml +53 -0
  254. tan/templates/vendored/diagnostics/E1M-V2N101/CMakeLists.txt +8 -0
  255. tan/templates/vendored/diagnostics/E1M-V2N101/README.md +112 -0
  256. tan/templates/vendored/diagnostics/E1M-V2N101/board.yaml +38 -0
  257. tan/templates/vendored/diagnostics/E1M-V2N101/boards/native_sim_native_64.conf +11 -0
  258. tan/templates/vendored/diagnostics/E1M-V2N101/boards/native_sim_native_64.overlay +29 -0
  259. tan/templates/vendored/diagnostics/E1M-V2N101/prj.conf +5 -0
  260. tan/templates/vendored/diagnostics/E1M-V2N101/src/main.c +266 -0
  261. tan/templates/vendored/diagnostics/E1M-V2N101/testcase.yaml +53 -0
  262. tan/templates/vendored/edge-ai/E1M-AEN801/CMakeLists.txt +10 -0
  263. tan/templates/vendored/edge-ai/E1M-AEN801/README.md +75 -0
  264. tan/templates/vendored/edge-ai/E1M-AEN801/board.yaml +38 -0
  265. tan/templates/vendored/edge-ai/E1M-AEN801/prj.conf +8 -0
  266. tan/templates/vendored/edge-ai/E1M-AEN801/src/cold_chain.c +371 -0
  267. tan/templates/vendored/edge-ai/E1M-AEN801/src/cold_chain.h +178 -0
  268. tan/templates/vendored/edge-ai/E1M-AEN801/src/main.c +373 -0
  269. tan/templates/vendored/edge-ai/E1M-AEN801/testcase.yaml +62 -0
  270. tan/templates/vendored/edge-ai/E1M-V2N101/CMakeLists.txt +10 -0
  271. tan/templates/vendored/edge-ai/E1M-V2N101/README.md +75 -0
  272. tan/templates/vendored/edge-ai/E1M-V2N101/board.yaml +37 -0
  273. tan/templates/vendored/edge-ai/E1M-V2N101/prj.conf +8 -0
  274. tan/templates/vendored/edge-ai/E1M-V2N101/src/cold_chain.c +371 -0
  275. tan/templates/vendored/edge-ai/E1M-V2N101/src/cold_chain.h +178 -0
  276. tan/templates/vendored/edge-ai/E1M-V2N101/src/main.c +373 -0
  277. tan/templates/vendored/edge-ai/E1M-V2N101/testcase.yaml +62 -0
  278. tan/templates/vendored/iot/E1M-AEN801/CMakeLists.txt +14 -0
  279. tan/templates/vendored/iot/E1M-AEN801/README.md +103 -0
  280. tan/templates/vendored/iot/E1M-AEN801/board.yaml +69 -0
  281. tan/templates/vendored/iot/E1M-AEN801/prj.conf +15 -0
  282. tan/templates/vendored/iot/E1M-AEN801/src/cc3501e_bridge.c +196 -0
  283. tan/templates/vendored/iot/E1M-AEN801/src/cc3501e_bridge.h +173 -0
  284. tan/templates/vendored/iot/E1M-AEN801/src/main.c +262 -0
  285. tan/templates/vendored/iot/E1M-AEN801/testcase.yaml +68 -0
  286. tan/templates/vendored/minimal/E1M-AEN801/CMakeLists.txt +8 -0
  287. tan/templates/vendored/minimal/E1M-AEN801/README.md +108 -0
  288. tan/templates/vendored/minimal/E1M-AEN801/board.yaml +32 -0
  289. tan/templates/vendored/minimal/E1M-AEN801/prj.conf +8 -0
  290. tan/templates/vendored/minimal/E1M-AEN801/src/main.c +111 -0
  291. tan/templates/vendored/minimal/E1M-AEN801/testcase.yaml +49 -0
  292. tan/templates/vendored/minimal/E1M-V2N101/CMakeLists.txt +8 -0
  293. tan/templates/vendored/minimal/E1M-V2N101/README.md +108 -0
  294. tan/templates/vendored/minimal/E1M-V2N101/board.yaml +32 -0
  295. tan/templates/vendored/minimal/E1M-V2N101/prj.conf +8 -0
  296. tan/templates/vendored/minimal/E1M-V2N101/src/main.c +111 -0
  297. tan/templates/vendored/minimal/E1M-V2N101/testcase.yaml +49 -0
  298. tan/templates/vendored/multicore-mailbox/E1M-AEN801/CMakeLists.txt +8 -0
  299. tan/templates/vendored/multicore-mailbox/E1M-AEN801/README.md +120 -0
  300. tan/templates/vendored/multicore-mailbox/E1M-AEN801/board.yaml +57 -0
  301. tan/templates/vendored/multicore-mailbox/E1M-AEN801/boards/native_sim_native_64.overlay +40 -0
  302. tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/CMakeLists.txt +13 -0
  303. tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/main.c +171 -0
  304. tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/prj.conf +17 -0
  305. tan/templates/vendored/multicore-mailbox/E1M-AEN801/peer/testcase.yaml +23 -0
  306. tan/templates/vendored/multicore-mailbox/E1M-AEN801/prj.conf +22 -0
  307. tan/templates/vendored/multicore-mailbox/E1M-AEN801/src/main.c +185 -0
  308. tan/templates/vendored/multicore-mailbox/E1M-AEN801/testcase.yaml +26 -0
  309. tan/templates/vendored/sensor/E1M-AEN801/CMakeLists.txt +8 -0
  310. tan/templates/vendored/sensor/E1M-AEN801/README.md +112 -0
  311. tan/templates/vendored/sensor/E1M-AEN801/board.yaml +57 -0
  312. tan/templates/vendored/sensor/E1M-AEN801/boards/native_sim_native_64.conf +10 -0
  313. tan/templates/vendored/sensor/E1M-AEN801/boards/native_sim_native_64.overlay +28 -0
  314. tan/templates/vendored/sensor/E1M-AEN801/prj.conf +5 -0
  315. tan/templates/vendored/sensor/E1M-AEN801/src/main.c +186 -0
  316. tan/templates/vendored/sensor/E1M-AEN801/testcase.yaml +52 -0
  317. tan/templates/vendored/sensor/E1M-V2N101/CMakeLists.txt +8 -0
  318. tan/templates/vendored/sensor/E1M-V2N101/README.md +112 -0
  319. tan/templates/vendored/sensor/E1M-V2N101/board.yaml +57 -0
  320. tan/templates/vendored/sensor/E1M-V2N101/boards/native_sim_native_64.conf +10 -0
  321. tan/templates/vendored/sensor/E1M-V2N101/boards/native_sim_native_64.overlay +28 -0
  322. tan/templates/vendored/sensor/E1M-V2N101/prj.conf +5 -0
  323. tan/templates/vendored/sensor/E1M-V2N101/src/main.c +186 -0
  324. tan/templates/vendored/sensor/E1M-V2N101/testcase.yaml +52 -0
  325. tan/version.py +102 -0
  326. tan_cli-0.7.0.dist-info/METADATA +125 -0
  327. tan_cli-0.7.0.dist-info/RECORD +330 -0
  328. tan_cli-0.7.0.dist-info/WHEEL +5 -0
  329. tan_cli-0.7.0.dist-info/entry_points.txt +2 -0
  330. tan_cli-0.7.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env python3
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ """Per-product core ownership: the ONE resolver.
4
+
5
+ `metadata/e1m_modules/<family>/core-ownership.yaml` keeps FIXED facts under
6
+ `core_ownership:` and per-product choices under `assignable:` (keyed by E1M
7
+ instance, each with `candidates`, a `default`, and references to
8
+ metadata/pinmux rows). A board.yaml `ownership: {<instance>: <core>}` block
9
+ overrides a default; `resolve_ownership` rejects an unknown instance or a core
10
+ outside `candidates`. The resolved map is what `--emit system-manifest`
11
+ projects as `ownership:`. Fixed rows are never touched by an override.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from pathlib import Path
17
+ from typing import Any, Optional
18
+
19
+ import yaml
20
+
21
+ from .models import OrchestratorError
22
+
23
+ # Core-ownership tokens -> the SoC-JSON `cores[].type` they name.
24
+ CORE_TOKEN_TYPES = {"a55": "cortex-a55", "m33": "cortex-m33"}
25
+
26
+
27
+ def _ownership_doc_path(metadata_root: Path, family_dir: Optional[str]) -> Optional[tuple[Path, str]]:
28
+ """(on-disk path under `metadata_root`, repo-relative spelling) of the
29
+ family's core-ownership.yaml (the V2M family `v2n-m1` shares the V2N
30
+ file), or None. The repo-relative string is only for `src=` comments."""
31
+ if not family_dir:
32
+ return None
33
+ for fam in (family_dir, "v2n" if family_dir.startswith("v2n") else None):
34
+ p = metadata_root / "e1m_modules" / fam / "core-ownership.yaml" if fam else None
35
+ if p and p.is_file():
36
+ return p, f"metadata/e1m_modules/{fam}/core-ownership.yaml"
37
+ return None
38
+
39
+
40
+ def ownership_doc_rel(metadata_root: Path, family_dir: Optional[str]) -> Optional[str]:
41
+ """Repo-relative path of the family's core-ownership.yaml, or None."""
42
+ found = _ownership_doc_path(metadata_root, family_dir)
43
+ return found[1] if found else None
44
+
45
+
46
+ def load_ownership_doc(metadata_root: Path, family_dir: Optional[str]) -> Optional[dict]:
47
+ """The family's core-ownership.yaml (read from `metadata_root`, whatever
48
+ that directory is called), or None."""
49
+ found = _ownership_doc_path(metadata_root, family_dir)
50
+ return yaml.safe_load(found[0].read_text(encoding="utf-8")) if found else None
51
+
52
+
53
+ def resolve_ownership(doc: Optional[dict],
54
+ overrides: Optional[dict[str, str]] = None,
55
+ declared_core_types: Optional[set[str]] = None) -> dict[str, str]:
56
+ """{instance: core} = assignable defaults + validated overrides.
57
+
58
+ An override may differ from the SoM default only where both cores' trees
59
+ can follow it (candidates include m33 and an `m33:` block exists; the
60
+ Linux side is `--emit linux-ownership-dts`); handing a node to a55 also
61
+ needs `linux_enable`. `hw_blocked` instances reject with their reason.
62
+
63
+ Fixed `core_ownership` rows are not in the result and cannot be
64
+ overridden (they are not instances). `declared_core_types` (SoC core
65
+ types of the project's `cores:` keys; None = skip) rejects an override
66
+ naming a core the project does not declare. Raises OrchestratorError.
67
+ """
68
+ assignable = (doc or {}).get("assignable") or {}
69
+ out = {inst: e["default"] for inst, e in assignable.items()}
70
+ for inst, core in (overrides or {}).items():
71
+ if inst not in assignable:
72
+ raise OrchestratorError(
73
+ f"board.yaml ownership: unknown instance {inst!r}; "
74
+ f"assignable instances: {sorted(assignable) or 'none for this SoM'}")
75
+ cands = assignable[inst]["candidates"]
76
+ if core not in cands:
77
+ raise OrchestratorError(
78
+ f"board.yaml ownership: {inst} cannot be owned by {core!r}; "
79
+ f"allowed cores: {cands}")
80
+ blocked = assignable[inst].get("hw_blocked")
81
+ if blocked and core != assignable[inst]["default"]:
82
+ raise OrchestratorError(
83
+ f"board.yaml ownership: {inst} is hardware-blocked on every core: "
84
+ f"{blocked['reason']}")
85
+ if (declared_core_types is not None
86
+ and CORE_TOKEN_TYPES[core] not in declared_core_types):
87
+ raise OrchestratorError(
88
+ f"board.yaml ownership: {inst} is assigned to {core!r} but "
89
+ f"board.yaml `cores:` does not declare a {CORE_TOKEN_TYPES[core]} core")
90
+ e = assignable[inst]
91
+ default = e["default"]
92
+ if core != default:
93
+ # A non-default owner needs BOTH sides to follow: the CM33 board
94
+ # tree/Kconfig (an `m33:` block) and the per-project Linux
95
+ # fragment (`--emit linux-ownership-dts`). Handing a node TO
96
+ # Linux additionally needs `linux_enable` (bench-evidenced).
97
+ if "m33" not in cands or not e.get("m33"):
98
+ raise OrchestratorError(
99
+ f"board.yaml ownership: {inst}: {core!r} differs from the SoM default "
100
+ f"{default!r} but metadata/e1m_modules/<family>/core-ownership.yaml "
101
+ f"carries no `m33:` devicetree block (and an m33 candidate) for it, so "
102
+ f"only one core's tree could follow")
103
+ if core == "a55" and not e.get("linux_enable"):
104
+ raise OrchestratorError(
105
+ f"board.yaml ownership: {inst}: Linux enablement is not bench-evidenced "
106
+ f"(`linux_enable` unset in core-ownership.yaml); it cannot be handed to "
107
+ f"'a55'")
108
+ out[inst] = core
109
+ return out
110
+
111
+
112
+ def pad_pfc(pad: str, func: int) -> tuple[str, int, int]:
113
+ """("P50", 1) -> ("PORT_05", 0, 1): the RZ/V2N PFC (port, pin, func) of a
114
+ `P<port><pin>` pad. The function code is a silicon fact from the SoC
115
+ JSON `linux_dt[soc_instance].pinmux`; only the pad spelling is parsed."""
116
+ if len(pad) != 3 or pad[0] != "P" or not pad[1].isdigit() or not pad[2].isdigit():
117
+ raise OrchestratorError(
118
+ f"pad {pad!r} is not a P<digit port><pin> pad (letter ports are not mapped "
119
+ "to a PORT_xx token: no source for it in this tree)")
120
+ return f"PORT_0{pad[1]}", int(pad[2]), func
121
+
122
+
123
+ def instance_pfc(soc: dict, entry: dict) -> list[tuple[dict, Optional[tuple[str, int, int]]]]:
124
+ """[(row, (port, pin, func) | None)] for an assignable entry; None where
125
+ the SoC `linux_dt` carries no function code for the row (never guessed)."""
126
+ pinmux = ((soc.get("linux_dt") or {}).get(entry.get("soc_instance")) or {}).get("pinmux") or {}
127
+ return [(r, pad_pfc(r["pad"], pinmux[r["peripheral"]]) if r["peripheral"] in pinmux else None)
128
+ for r in entry["rows"]]
129
+
130
+
131
+ def validate_assignable(doc: dict, pinmux_pairs: set[tuple[str, str]],
132
+ soc_core_types: set[str],
133
+ linux_dt: Optional[dict] = None) -> list[str]:
134
+ """Metadata cross-checks: rows exist in pinmux, are not also FIXED rows,
135
+ default is a candidate, candidates exist on the SoM, `soc_instance`
136
+ resolves in the SoC `linux_dt` (when given), an `m33:` block has a PFC
137
+ function for every row."""
138
+ msgs: list[str] = []
139
+ fixed = {(r["peripheral"], r["pad"]) for r in doc.get("core_ownership") or []}
140
+ seen: dict[tuple[str, str], str] = {}
141
+ for inst, e in (doc.get("assignable") or {}).items():
142
+ if e.get("hw_blocked") and e["default"] != "a55":
143
+ msgs.append(f"assignable.{inst}: hw_blocked instance must default to a55 (Linux leaves it disabled)")
144
+ if e["default"] not in e["candidates"]:
145
+ msgs.append(f"assignable.{inst}: default {e['default']!r} not in candidates {e['candidates']}")
146
+ for c in e["candidates"]:
147
+ if CORE_TOKEN_TYPES.get(c) not in soc_core_types:
148
+ msgs.append(f"assignable.{inst}: candidate {c!r} is not a core of this SoM")
149
+ for r in e["rows"]:
150
+ k = (r["peripheral"], r["pad"])
151
+ if k not in pinmux_pairs:
152
+ msgs.append(f"assignable.{inst}: row {k} matches no owner=renesas row in metadata/pinmux")
153
+ if k in fixed:
154
+ msgs.append(f"assignable.{inst}: row {k} is also a FIXED core_ownership row")
155
+ if k in seen:
156
+ msgs.append(f"assignable.{inst}: row {k} already assigned to {seen[k]}")
157
+ seen[k] = inst
158
+ if linux_dt is not None:
159
+ if e.get("soc_instance") not in linux_dt:
160
+ msgs.append(f"assignable.{inst}: soc_instance {e.get('soc_instance')!r} is not a key of the SoC linux_dt")
161
+ elif "m33" in e:
162
+ missing = [r["peripheral"] for r, p in instance_pfc({"linux_dt": linux_dt}, e) if p is None]
163
+ if missing:
164
+ msgs.append(f"assignable.{inst}: has an m33: block but linux_dt.{e['soc_instance']}.pinmux has no function for {missing}")
165
+ return msgs
166
+
167
+
168
+ def m33_overlay(doc: Optional[dict], ownership: dict[str, str]) -> tuple[list[str], list[str]]:
169
+ """(dts lines, Kconfig lines) enabling every assignable instance this
170
+ project assigned to `m33`. The board tree (gen_zephyr_board.py) carries
171
+ those nodes `disabled`; only an owning project turns them on. An
172
+ m33-owned instance with no `m33:` devicetree block is an error, not a
173
+ silent no-op."""
174
+ assignable = (doc or {}).get("assignable") or {}
175
+ dts: list[str] = []
176
+ kconfig: list[str] = []
177
+ for inst, core in sorted(ownership.items()):
178
+ if core != "m33":
179
+ continue
180
+ blocked = assignable[inst].get("hw_blocked")
181
+ if blocked:
182
+ raise OrchestratorError(
183
+ f"board.yaml ownership: {inst} is hardware-blocked on every core: {blocked['reason']}")
184
+ b = assignable[inst].get("m33")
185
+ if not b:
186
+ raise OrchestratorError(
187
+ f"board.yaml ownership: {inst} is assigned to 'm33' but core-ownership.yaml "
188
+ f"carries no `m33:` devicetree block for it (the CM33 node, pinctrl and PFC "
189
+ f"data are not in metadata yet)")
190
+ dts += [f"&{b['dt_label']} {{", ' status = "okay";', "};",
191
+ "/ {", " aliases {", f" {b['alias']} = &{b['dt_label']};", " };", "};"]
192
+ kconfig += b.get("kconfig") or []
193
+ return dts, kconfig
194
+
195
+
196
+ def project_m33_overlay(project, core_id: Optional[str]) -> tuple[list[str], list[str]]:
197
+ """`m33_overlay` for a loaded project, scoped to a Cortex-M33 core id
198
+ (`core_id` None = any M33 core of the project)."""
199
+ from .loader import _sku_family_dir
200
+ if not project.ownership or not (core_id or "m33").startswith("m33"):
201
+ return [], []
202
+ doc = load_ownership_doc(project.effective_metadata_root(), _sku_family_dir(project.sku))
203
+ return m33_overlay(doc, project.ownership)