Every spacecraft program we visit has the same scripts folder: hundreds of Python files, half of them written by engineers who left two years ago, each wrapping a slightly different flavor of CAN, 1553, or SpaceWire. The team always apologizes for it. They should not, the folder is not the problem.
The graveyard pattern is universal. A telecom satellite group will keep three sets of Simulink harnesses for the same payload because the harnesses encode three slightly different message definitions, and nobody is sure which one matches the version the vendor shipped. A defense prime will pay a contractor to rebuild the SIL bench every program because the previous one is too coupled to a previous bus revision to port. The standard explanation, in conferences and in our discovery calls, is that simulation is hard.
Simulation is not hard. The automotive industry has been running software-in-the-loop on engine ECUs for thirty years. dSPACE and Speedgoat run real-time SIL on commodity x86 boxes with eye-watering determinism. What is hard is feeding a simulator a credible model of the interfaces being simulated, when those interfaces live in twelve different PDFs, two Excel sheets, and one engineer's head.
The pipeline is downstream of the interface
The SIL framework is a function of the interface model. If the team's authoritative description of the bus is a Word document with a table of message IDs, then somebody has to translate that table into struct definitions for the simulator, into header files for the flight software, and into checker assertions for the bench. Three translations, three places to drift, and the drift only surfaces when the integration manager finally sits everyone down with a real harness.
When you write a custom SIL framework on top of that, you are not building infrastructure. You are paving over a missing data layer. The pipeline ends up bespoke because each subsystem reinvented its own translation. We have seen this twice in the last quarter on programs that share two-thirds of their bus topology with a previous program at the same company.
A worked example: telemetry on a 1553 bus
Take a smallsat with MIL-STD-1553B as its primary command-and-data bus. The standard gives you the wire format. It does not give you the message catalog: which Remote Terminal owns which subaddress, what the bit layout of each command is, which words are scaled by 2^-15 and which are raw counts. That catalog is the ICD, and on most programs we see, it lives as a spreadsheet maintained by one person in avionics.
Now build a SIL bench. The flight software team needs C structs for the bus messages. The hardware-in-the-loop bench needs the same definitions in whatever the bench framework uses, often a custom DSL. The test team needs assertions in pytest that check telemetry against expected values. The simulation team building a digital twin needs JSON or YAML for whatever Modelica or Simulink wrapper they prefer.
If the spreadsheet is the source, every one of those representations is hand-typed. If somebody changes the scale factor on a battery voltage telemetry word and updates the spreadsheet, the C struct still has the old scale. The bench still has the old scale. The pytest assertion still has the old scale. We have watched a program lose four weeks of integration time to exactly this scenario, and the postmortem blamed the test bench.
The bench was not the cause. The bench was the only place where the divergence was finally observable.
Why teams reach for the wrong fix
The visible failure happens in the simulator, so the budget goes to the simulator. We have read enough RFPs to recognize the pattern: programs ask for a more powerful SIL platform, a higher-fidelity digital twin, a faster integration bench. They almost never ask for a better way to define interfaces, because nobody gets paid to build a slightly better interface registry. Interfaces are scope-zero on most programs, assumed to exist, never resourced.
The result is a market full of beautiful simulation tooling fed by hand-typed message definitions. dSPACE, Speedgoat, NI VeriStand, Simulink Real-Time, GMSEC — all impressive, all assuming you have already solved the upstream problem. Most teams have not. The upstream problem is unglamorous, and that is exactly where the work pays off.
A simulator is downstream infrastructure. If the pipeline became a graveyard of scripts, the interface was never crisp enough to drive it generically.
What changes when the ICD is code
We treat this as the central technical claim of our company, so let's make it concretely. If the bus is described in a single, machine-readable schema (and that schema is generated, versioned, and diffed like any other code artifact) then the C structs, the bench DSL, the pytest assertions, and the simulation models all derive from one source. A change to the scale factor on a telemetry word becomes a single commit. The bench tests fail in CI within minutes, not at integration in months.
This is not hypothetical. It is roughly what the embedded automotive world does with AUTOSAR ARXML, what the FreeRTOS-on-MCU teams already do for memory-mapped registers, and what CCSDS Mission Operations services have been pushing toward for years. The space community knows the pattern. It has not adopted it broadly because the up-front cost of moving the bus definition into a versioned schema feels larger than the cost of one more bespoke SIL build. Until you have absorbed three of those bespoke builds, that math looks right.
Implication
The next time a program lead asks for budget to modernize the simulation pipeline, the right counter-question is the upstream one: where does the bus definition live, and how many places does it have to be hand-translated to before it can be simulated? Answer that first, and the SIL pipeline stops being a graveyard. Answer it second, and you build another one.
The teams that catch integration problems three months earlier on the next program are not the teams with the best simulators. They are the teams that stopped letting the spreadsheet be the source of truth. The simulator was the easy part all along.




