AOT compile target configuration for the Cortex-M backend. `cpu` selects the CPU variant. `isa` optionally overrides the cmsis_nn backend that would normally be derived from `cpu` — useful for cores with optional ISA extensions (M55 without MVE, M33 without DSP, etc.). Overrides are
| 55 | |
| 56 | @dataclass(frozen=True) |
| 57 | class CortexMTargetConfig: |
| 58 | """AOT compile target configuration for the Cortex-M backend. |
| 59 | |
| 60 | `cpu` selects the CPU variant. `isa` optionally overrides the cmsis_nn |
| 61 | backend that would normally be derived from `cpu` — useful for cores |
| 62 | with optional ISA extensions (M55 without MVE, M33 without DSP, etc.). |
| 63 | Overrides are validated against the CPU's architectural capability set |
| 64 | on construction; e.g. forcing MVE on an M0 raises ValueError. |
| 65 | """ |
| 66 | |
| 67 | cpu: CortexM |
| 68 | isa: Optional[cmsis_nn.Backend] = None |
| 69 | |
| 70 | def __post_init__(self) -> None: |
| 71 | if self.isa is None: |
| 72 | return |
| 73 | supported = _SUPPORTED_BACKENDS.get(self.cpu) |
| 74 | if supported is None or self.isa not in supported: |
| 75 | allowed = sorted(b.name for b in supported) if supported else [] |
| 76 | raise ValueError( |
| 77 | f"Backend {self.isa.name} is not supported on " |
| 78 | f"{self.cpu.name}; supported: {allowed}" |
| 79 | ) |
| 80 | |
| 81 | @property |
| 82 | def backend(self) -> cmsis_nn.Backend: |
| 83 | if self.isa is not None: |
| 84 | return self.isa |
| 85 | try: |
| 86 | cmsis_member = getattr(cmsis_nn.CortexM, self.cpu.name) |
| 87 | except AttributeError as e: |
| 88 | raise ValueError( |
| 89 | f"cmsis_nn does not yet support {self.cpu.name}; pass an " |
| 90 | f"explicit `isa=` override or wait for upstream support." |
| 91 | ) from e |
| 92 | return cmsis_nn.resolve_backend(cmsis_member) |
| 93 | |
| 94 | @classmethod |
| 95 | def from_target_string(cls, target: str) -> CortexMTargetConfig: |
| 96 | """Parse a `cortex-m<variant>` target string.""" |
| 97 | if not target.startswith("cortex-m"): |
| 98 | raise ValueError( |
| 99 | f"Cortex-M target string must start with 'cortex-m', " |
| 100 | f"got: {target!r}" |
| 101 | ) |
| 102 | enum_name = "M" + target[len("cortex-m") :].upper() |
| 103 | try: |
| 104 | cpu = CortexM[enum_name] |
| 105 | except KeyError as e: |
| 106 | raise ValueError( |
| 107 | f"Unsupported Cortex-M target string: {target!r}. " |
| 108 | f"Supported: {sorted('cortex-m' + m.name[1:].lower() for m in CortexM)}" |
| 109 | ) from e |
| 110 | return cls(cpu=cpu) |
no outgoing calls