Skip to content

生产环境部署:C代码“蒸馏”策略 (Code Distillation Strategy)

状态: 概念规划阶段 (Future Architecture Roadmap) 背景: 当前的 FCC-Dynamics-C 项目在开发期采用了高度抽象的函数式编程范式(Symmetric RWS Monad, Free Monad AST, C++20 Templates)。这种架构赋予了系统极高的数学确定性、测试便利性和解耦能力。然而,在面对传统航天/军工领域的嵌入式部署要求时(如 DO-178C 认证、MISRA C 标准、严苛的硬实时要求、禁止堆内存分配等),这种“高傲”且现代的 C++ 架构极易遭受传统嵌入式工程师的抵触和质疑,且确实存在不可控的缓存未命中(Cache Miss)和模板展开开销。

为了彻底解决这一痛点,我们提出**“蒸馏(Distillation)”策略**:将开发期的高维抽象作为“脚手架”和“验证引擎”,在生产部署时,将其彻底压平为最朴素的纯 C 语言(C99/C11)代码。


1. 核心理念:隐藏“高傲”,输出“降维打击”

我们不需要说服保守的硬件工程师去学习 Haskell 或 Monad。我们将复杂的模板系统和 AST 留在实验室的服务器上。

最终交付给底层飞控硬件的,将是一个极其扁平、没有一处虚函数调用、没有一行 malloc/new 的纯 C 函数。

这是一种“特洛伊木马”式的降维打击:用最先进的函数式思想保证逻辑的绝对正确与清晰,用最原始的 C 语言保证硬件运行的绝对高效与合规。


2. 蒸馏管线设计 (Distillation Pipeline)

部署流程将分为以下四个阶段:

阶段一:高维开发与语义验证 (当前阶段)

  • 工具: C++20, Free Monad, RWS Pipeline, Google Test.
  • 目标: 算法工程师使用重载算子(|, >>=)和 DSL 快速拼接飞行逻辑。通过 L1-L4 TDD 测试网格,确保物理计算和状态机流转在数学上绝对正确无误。

阶段二:配置冻结与 AST 提取

  • 工具: 内部解析器 / Visitor.
  • 目标: 针对某次特定的真实发射任务,YAML 配置(Schedule, Stage 等)被冻结。C++ 的 Free Monad 解释器不再执行真正的 RWS 状态更新,而是执行一次“空跑 (Dry-Run)”,遍历整棵 AST(抽象语法树),记录下所有将会执行的算子序列和条件跳转。

阶段三:C 代码生成 (Code Generation)

  • 工具: Python 脚本或定制的 C++ 后端代码生成器 (Generator Visitor)。
  • 目标: 将提取出的 AST 操作序列,一对一映射为预先验证过的纯 C 算子库。
    • 例如,RunGuidance{mode="Ascent"} 被映射为调用 guidance_ascent_step(&fcc_env, &fcc_state);
    • 将 RWS 的 Reader 和 State 映射为 C 语言中的 const struct 指针和普通的 struct 指针。

阶段四:裸机编译与部署 (Bare-metal Deployment)

  • 目标: 生成的 C 代码直接交由嵌入式交叉编译器(如 GCC-ARM, Keil, 甚至 FPGA HLS)编译。

3. 蒸馏后的代码形态 (示意)

开发期的代码 (C++20, Free Monad):

cpp
auto flight_program = 
    read_imu() |
    run_navigation() >>
    check_stage() |
    run_guidance() |
    output_controls();

蒸馏后的生产代码 (Pure C):

c
/* 自动生成代码:禁止手动修改 (Auto-generated code: DO NOT EDIT) */
#include "fcc_c_api.h"

void fcc_distilled_step(
    const FccEnv_t* env,       /* Reader: 只读环境与配置 */
    FccState_t* state,         /* State: 可读写内部状态 */
    const FccInFrame_t* in,    /* Input: 总线输入 */
    FccOutFrame_t* out         /* Output/Writer: 总线输出与指令 */
) {
    /* 1. Read IMU */
    fcc_algo_read_imu(state, in);
    
    /* 2. Navigation */
    fcc_algo_nav_step(env, state);
    
    /* 3. Stage Check (展开后的状态机判断) */
    if (state->altitude > env->stage_1_sep_alt) {
        state->current_stage = STAGE_2;
    }
    
    /* 4. Guidance (根据状态静态分发) */
    switch(state->current_stage) {
        case STAGE_1: fcc_algo_guidance_ascent(env, state); break;
        case STAGE_2: fcc_algo_guidance_coast(env, state); break;
    }
    
    /* 5. Output Controls */
    fcc_algo_output_controls(state, out);
}

4. 蒸馏方案的巨大优势

  1. 绝对的性能与确定性:蒸馏后的 C 代码完全在栈(Stack)或静态内存(BSS/Data)上运行。Cache 命中率达到理论极限,执行时间抖动(Jitter)降至最低。
  2. 极简认证:生成的 C 结构极其扁平,非常容易通过诸如 MISRA C:2012 静态代码扫描,以及 DO-178C 航空器软件标准的适航认证。
  3. 消除文化冲突:底层的驱动工程师和飞控硬件专家只需审查和对接最终生成的 C 语言头文件和函数指针,无需理解 Monad、Template 或 RWS,极大地降低了跨部门沟通成本和被“老派工程师”否决的风险。

5. 后续待办 (TODO)

  • [ ] 稳定当前的 C++ DSL 语义,确保所有的 FccOp 都有与之对应的纯 C/C++ 扁平化数学实现原型。
  • [ ] 开发 FccCGenVisitor:编写一个特殊的 Free Monad 解释器,其副作用不是修改状态,而是输出 C 语言字符串。
  • [ ] 建立纯 C 版本的核心算子库 (fcc_c_api.h),作为代码生成器的 Target Backend。