Djinious
Génération de code embarquéMéthodes d’ingénierie

Modèle → firmware Rust

De la conception orientée modèle au code déployable, à la manière Rust d’abord — un pilote automatique conçu sous forme de schémas-blocs, généré en code Rust #![no_std], prouvé équivalent au modèle, compilé de manière croisée pour une cible Cortex-M, et attesté en provenance.

DjiniousLab
Trois graphiques logiciel-dans-la-boucle — altitude, attitude et position — où le firmware Rust généré (pointillé) suit le modèle DjiniousLab (plein) à une fraction de pourcent près
cascade de pilote automatique → Rust
3 bouclescascade de pilote automatique → Rust
écart firmware/modèle
< 1.2%écart firmware/modèle
embarquable, calcul via libm
#![no_std]embarquable, calcul via libm
compilation croisée vérifiée
Cortex-M4Fcompilation croisée vérifiée
attestation de provenance
in-totoattestation de provenance
Rust, pas C
sûr en mémoireRust, pas C

Le modèle devient le firmware. En Rust.

Simuler un système, c’est la moitié du travail ; le livrer en est l’autre moitié. DjiniousLab génère le code d’un contrôleur que vous avez conçu sous forme de schéma-bloc en une crate Rust autonome et sûre en mémoire — prouvée équivalente au modèle, compilée de manière croisée pour un microcontrôleur, et attestée cryptographiquement. C’est ce que fait Embedded Coder de Simulink, sauf que l’artefact généré est du Rust, pas du C — la différence qui compte quand le code va quelque part de critique pour la sécurité.

Une seule commande du schéma-bloc à la crate.

Une boucle de commande écrite comme un schéma-bloc .djl s’abaisse en une représentation intermédiaire plate, et `djinious codegen` la transforme en crate Cargo : une struct State, un constructeur de conditions initiales, et une fonction `pub fn step(state, inputs, t, dt) -> Outputs` qui fait avancer le contrôleur d’un tick. Ajoutez `--no-std` et elle émet un firmware embarquable utilisant libm pour le calcul au lieu de la bibliothèque standard. Les trois mêmes boucles de pilote automatique Djinborn T4 — altitude, attitude, position — que le programme quadricoptère fait voler en simulation se génèrent directement en Rust.

DjiniousLab
Le code source Rust no_std généré pour le contrôleur d’attitude : une struct State, un constructeur initial(), et une fonction step() lisant l’état puis calculant la loi de commande en cascade
Pas du pseudocode — le véritable contrôleur d’attitude `#![no_std]` généré. Chaque état d’intégrateur est lu en haut (comme une source sans dépendance), la loi en cascade attitude externe / vitesse interne se calcule au milieu, et les mises à jour d’état sont différées en bas. Lisible, déterministe, et libre de toute bibliothèque standard.

Des boucles fermées, pas seulement des chaînes en anticipation.

Un contrôleur est une boucle de rétroaction — la sortie de l’intégrateur reboucle sur l’erreur. La génération de code émettait auparavant les blocs dans l’ordre de déclaration, si bien que la sortie d’un intégrateur rebouclé pouvait être référencée avant d’être liée : du Rust qui ne compile pas. La correction émet les liaisons de sortie dans l’ordre topologique, en traitant les sorties d’intégrateurs et de retards comme des sources sans dépendance (leur sortie lit un état stocké), ce qui brise le cycle ; les mises à jour d’état sont différées à la fin du pas. Une boucle de rétroaction sans élément d’état pour la briser est une véritable boucle algébrique, et génère désormais honnêtement une erreur au lieu de produire du code cassé. La suite complète de tests de génération de code — 765 tests unitaires plus 523 allers-retours compilation-exécution — reste au vert.

DjiniousLab
Trois graphiques logiciel-dans-la-boucle où la trajectoire du firmware Rust généré se superpose à la trajectoire du modèle pour les boucles d’altitude, d’attitude et de position
Preuve logiciel-dans-la-boucle : chaque boucle exécutée à travers le solveur de modèle précis (plein) et à travers le firmware généré à pas fixe (pointillé), alignés et différenciés. Le firmware reproduit chaque dépassement, temps d’établissement et état stationnaire — écart maximal de 0,09 % / 1,18 % / 0,24 % de la plage. La génération de code est exacte ; le résidu n’est que la discrétisation à pas fixe.

Le code généré fait la différence.

Sûr en mémoire par construction

Pas de débordement de tampon, pas d’utilisation après libération, pas de comportement indéfini — les classes de bugs que les normes de sécurité passent des pages entières à essayer d’exclure du C généré sont absentes de Rust grâce aux garanties propres du langage.

Embarquable, no_std

Les crates sont `#![no_std]` avec libm pour le calcul transcendant — pas d’allocateur, pas de système d’exploitation. Elles se compilent de manière croisée pour une cible bare-metal Cortex-M4F (STM32F4) comme vérifié ici, prêtes pour un HAL de carte et un ISR de minuteur.

Provenance attestée

`djinious attest` lie le modèle au SHA-256 du firmware dans une Statement in-toto ; `djinious sign` la signe avec cosign. Le lien de chaîne d’approvisionnement de « ce modèle » à « ce binaire » que la certification exige.

Équivalence prouvée

Un banc logiciel-dans-la-boucle exécute le modèle et le firmware côte à côte et les différencie — le code généré est conditionné à correspondre à la référence, pas simplement supposé le faire.

Chaque affirmation est une commande que vous pouvez réexécuter.

L’ensemble du pipeline est fait d’artefacts réels — abaissement, génération de code, compilation, exécution, comparaison, compilation croisée, attestation — pas une démonstration de diapositives.

Étape

  • Boucles générées et compilées : 3 / 3
  • Écart SIL (firmware vs modèle) : < 1,2 %
  • Compilation croisée embarquée : thumbv7em
  • Provenance : in-toto v1
  • Suite de tests de génération de code : au vert

Résultat

  • Boucles générées et compilées : altitude · attitude · position
  • Écart SIL (firmware vs modèle) : de la plage, les trois
  • Compilation croisée embarquée : rlib Cortex-M4F
  • Provenance : empreinte modèle → firmware
  • Suite de tests de génération de code : 765 + 523 allers-retours

Génération de code par flux de signaux, de qualité embarquée.

Le code généré est en Euler explicite à pas fixe — la norme embarquée — sur la palette de blocs de signaux du catalogue (constante, somme, gain, intégrateur, saturation, oscilloscope et consorts), qui est exactement ce dont un contrôleur est constitué. Les composants DJL non linéaires personnalisés ne se génèrent pas encore en code ; ils s’exécutent dans le worker Julia. Flasher sur une carte spécifique nécessite une crate HAL et un point d’entrée `cortex-m-rt`, et `sign` / `verify` nécessitent un cosign local — l’intégration de carte et la signature CI dépassent le cadre de ce programme. Ce qu’il livre, c’est l’épine dorsale de la conception orientée modèle faite en Rust : concevoir, simuler, générer, prouver l’équivalence et tracer — de bout en bout, sur un seul outil.