/* * test_env_resync.c — 环境重校准(受控基线更新) gcc 隔离单测 (DLD154V4B V4.31) * * 镜像 = TaskLoop.c vd1_task() 无车段 dev>0 分支 (V4.24/25/26/30/31), 逻辑与固件一致: * - 高位 dev>+4dlt: 等待确认(g_env_wait_cnt) → 满 ENV_WARN_WAIT 预判锁存 g_env_warn * - 满 ENV_RESYNC_WAIT → 进入学习 g_env_resync(高位段才计数; 压线/回摆=搁置) * - 学习: 200 样本/窗, 窗均值漂移 ≤0.1% 连续 2 窗 → env_resync_apply 原子替换 * - 预算 ENV_LEARN_MAX_TICKS 超时 → abort 不污染 * - 非高位空闲 dev>-dlt 连续 ENV_RECOVER_WAIT → 清 g_env_warn (黄灯灭) * V4.31 拍板: 预判 2s + 补偿 7s + 替换后空闲 2s 灭 * 镜像宏与固件一致(改 ENV_* 时同步此处!) */ #include #include #include #include #include /* ===== 镜像固件宏 (TaskLoop.c/TaskLoop.h 同步) ===== */ #define ENV_WARN_WAIT 200 /* V4.31: 预判 2s */ #define ENV_RECOVER_WAIT 200 /* V4.30: 替换后空闲 2s 恢复确认 */ #define ENV_RESYNC_WAIT 700 /* V4.31: 补偿(学习等待) 7s */ #define ENV_LEARN_WINDOW 200 #define ENV_LEARN_MAX_TICKS 3000 #define STABLE_ORIGIN_PPT 1 #define STABLE_SETTLE_WINDOWS 2 #define dlt_4x 192 /* dlt=48 → 4×dlt (SENS=3) */ /* ===== 镜像全局 ===== */ static uint32_t sim_Origin = 128095UL; /* A 在场基线 */ static uint32_t sim_CAPVD = 128095UL; static uint32_t g_env_wait_cnt = 0; static uint32_t g_env_recover_cnt = 0; static uint32_t g_env_resync = 0; /* 学习中 */ static uint32_t g_env_warn = 0; /* 预判锁存 */ static uint32_t g_env_tick = 0; /* 学习预算计数 */ static uint32_t g_env_sum = 0; /* 学习窗累加 */ static uint32_t g_env_cnt = 0; /* 学习窗样本数 */ static uint32_t g_env_prev = 0; /* 上一窗均值 */ static uint32_t g_env_settle = 0; /* 连续稳定窗数 */ static uint32_t sim_learn_start_cnt = 0; static uint32_t sim_applied_cnt = 0; static uint32_t sim_abort_cnt = 0; static uint32_t sim_tick_cnt = 0; static int env_warn_active(void) { return (g_env_warn != 0 || g_env_resync != 0); } /* ===== 镜像: env_resync_apply / env_resync_abort (TaskLoop.c 逻辑复刻) ===== */ static void env_resync_apply(uint32_t new_origin) { sim_Origin = new_origin; /* 空闲原子替换 */ sim_applied_cnt++; g_env_resync = 0; g_env_wait_cnt = 0; g_env_sum = 0; g_env_cnt = 0; g_env_prev = 0; g_env_settle = 0; g_env_tick = 0; g_env_recover_cnt = 0; /* 替换后重新计恢复确认 */ } static void env_resync_abort(void) { sim_abort_cnt++; g_env_resync = 0; g_env_sum = 0; g_env_cnt = 0; g_env_prev = 0; g_env_settle = 0; g_env_tick = 0; g_env_wait_cnt = 0; } /* ===== 镜像: vd1_task 无车段 dev 分支 (TaskLoop.c 复刻, V4.30) ===== */ static void vd_env_branch(void) { int32_t dev = (int32_t)sim_CAPVD - (int32_t)sim_Origin; if (dev > (int32_t)dlt_4x) { /* ── 高位: 等待确认 / 学习 ── */ if (!g_env_resync) { g_env_wait_cnt++; g_env_recover_cnt = 0; /* 高位异常中恢复确认失效 */ if (g_env_wait_cnt >= ENV_WARN_WAIT) g_env_warn = 1; /* 预判锁存 (只增不清) */ if (g_env_wait_cnt >= ENV_RESYNC_WAIT) { g_env_resync = 1; /* 补偿触发 */ g_env_wait_cnt = 0; g_env_sum = 0; g_env_cnt = 0; g_env_prev = 0; g_env_settle = 0; g_env_tick = 0; sim_learn_start_cnt++; } } else { /* ── 学习基线 B: 连续空闲窗口均值 + settle 判稳 ── */ g_env_tick++; g_env_sum += sim_CAPVD; g_env_cnt++; if (g_env_cnt >= ENV_LEARN_WINDOW) { uint32_t _m = g_env_sum / g_env_cnt; g_env_sum = 0; g_env_cnt = 0; if (g_env_prev != 0) { uint32_t _drift = (_m > g_env_prev) ? (_m - g_env_prev) : (g_env_prev - _m); uint32_t _band = _m * STABLE_ORIGIN_PPT / 1000; if (_drift <= _band) { g_env_settle++; if (g_env_settle >= STABLE_SETTLE_WINDOWS) { env_resync_apply(_m); /* 连续 2 窗稳定 → B 可信, 原子替换 */ return; } } else { g_env_settle = 0; /* 窗口不稳 → 重算 */ } } g_env_prev = _m; } if (g_env_tick >= ENV_LEARN_MAX_TICKS) env_resync_abort(); /* 预算超时 → 放弃不污染 */ } return; } /* ── 非高位: 高位累计清零 (回摆/压线/空闲); 学习中则搁置(不计数) ── */ g_env_wait_cnt = 0; if (dev < -48) { /* 目标压入进入确认区 */ g_env_recover_cnt = 0; return; } /* 空闲 (dev > -dlt): 环境恢复正常 → 恢复确认计时 → 清预判(黄灯灭) */ g_env_recover_cnt++; if (g_env_recover_cnt >= ENV_RECOVER_WAIT) { g_env_warn = 0; /* 稳定 2s → 解除预判 */ g_env_recover_cnt = 0; } } static void sim_tick(void) { sim_tick_cnt++; vd_env_branch(); } /* ===== 场景隔离 ===== */ static void reset_all(void) { sim_Origin = 128095UL; sim_CAPVD = 128095UL; g_env_wait_cnt = 0; g_env_recover_cnt = 0; g_env_resync = 0; g_env_warn = 0; g_env_tick = 0; g_env_sum = 0; g_env_cnt = 0; g_env_prev = 0; g_env_settle = 0; sim_learn_start_cnt = 0; sim_applied_cnt = 0; sim_abort_cnt = 0; sim_tick_cnt = 0; } /* ===== 场景 1: 永久变化 (A 拿走) — 2s 预判 → 7s 触发 → 3窗学完 ~13s 替换 → +2s 灭 ===== */ static void test_permanent_change_recovers(void) { int tick, warn_at = 0; int loop; reset_all(); for (loop = 0; loop < 2500; loop++) { sim_CAPVD = 128856UL; /* dev=761 恒高位 */ sim_tick(); if (!warn_at && env_warn_active()) warn_at = (int)sim_tick_cnt; if (sim_applied_cnt) break; } printf("1. 永久变化: warn_at=%d learn_start=%d applied_at=%d Origin=%u (期望 200 / 1 / ~1300 / 128856)\n", warn_at, sim_learn_start_cnt, (int)sim_tick_cnt, sim_Origin); assert(warn_at == 200); assert(sim_learn_start_cnt == 1); assert(sim_applied_cnt == 1); assert(sim_Origin == 128856UL); /* 替换后 +2s (200tick) 恢复确认 → 黄灯灭 */ for (tick = 0; tick < 200; tick++) { sim_CAPVD = 128856UL; /* dev=0 空闲稳态 */ sim_tick(); } printf(" 替换后 200tick: warn=%d resync=%d (期望 0/0 → 灭)\n", g_env_warn, g_env_resync); assert(g_env_warn == 0); assert(g_env_resync == 0); assert(sim_applied_cnt == 1); printf(" 恢复确认后黄灯灭 OK\n"); } /* ===== 场景 2: 瞬态高位 7s (<8s) 不学 + 锁存保持 + 空闲 2s 灭 ===== */ static void test_transient_keeps_warn(void) { int loop; reset_all(); for (loop = 0; loop < 600; loop++) { /* 6s 高位 */ sim_CAPVD = 128856UL; sim_tick(); } printf("2. 瞬态 6s 高位: warn=%d learn=%d (期望 1 / 0)\n", g_env_warn, sim_learn_start_cnt); assert(env_warn_active() == 1); assert(sim_learn_start_cnt == 0); sim_CAPVD = 128000UL; /* 回摆 dev=-95 (目标压入) → 锁存保持 */ sim_tick(); printf(" 回摆后: warn=%d resync=%d (期望 warn 1 保持)\n", g_env_warn, g_env_resync); assert(g_env_warn == 1); assert(g_env_resync == 0); for (loop = 0; loop < 200; loop++) { /* 空闲 2s → 恢复确认 → 灭 */ sim_CAPVD = 128095UL; sim_tick(); } printf(" 空闲 200tick: warn=%d (期望 0 → 灭)\n", g_env_warn); assert(g_env_warn == 0); assert(sim_learn_start_cnt == 0); for (loop = 0; loop < 600; loop++) { /* 再 6s 高位 → 重新锁存, 仍不学 */ sim_CAPVD = 128856UL; sim_tick(); } printf(" 二次 6s 高位: warn=%d learn=%d (期望 1 / 0)\n", g_env_warn, sim_learn_start_cnt); assert(g_env_warn == 1); assert(sim_learn_start_cnt == 0); printf("2. 瞬态高位(<7s)不学, 锁存保持, 恢复确认后灭 OK\n"); } /* ===== 场景 3: 学习期目标压线 = 搁置(不退出) → 走后再学完 → 替换 ===== */ static void test_interrupted_learn_recomputes(void) { int loop; int applied_at = 0; reset_all(); for (loop = 0; loop < 700; loop++) { /* 7s → 学习开始 */ sim_CAPVD = 128856UL; sim_tick(); } assert(sim_learn_start_cnt == 1); assert(g_env_resync == 1); for (loop = 0; loop < 100; loop++) { /* 学习 100tick (801..900) */ sim_CAPVD = 128856UL; sim_tick(); } sim_CAPVD = 128000UL; /* 目标压线 dev=-95: 学习中搁置 */ sim_tick(); printf("3. 压线打断: resync=%d tick=%u learn=%d warn=%d (期望 resync 1 保持=搁置)\n", g_env_resync, g_env_tick, sim_learn_start_cnt, g_env_warn); assert(g_env_resync == 1); /* 不退出学习 */ assert(g_env_warn == 1); for (loop = 0; loop < 1600; loop++) { /* 目标走 → 继续高位学习 → 替换 */ sim_CAPVD = 128856UL; sim_tick(); if (sim_applied_cnt) { applied_at = (int)sim_tick_cnt; break; } } printf(" 继续学后: applied_at=%d learn=%d Origin=%u (期望 ~1400 / 1 / 128856)\n", applied_at, sim_learn_start_cnt, sim_Origin); assert(sim_applied_cnt == 1); assert(sim_learn_start_cnt == 1); /* 全程仅一次学习启动 */ assert(sim_Origin == 128856UL); for (loop = 0; loop < 200; loop++) { /* +2s 恢复确认 → 灭 */ sim_CAPVD = 128856UL; sim_tick(); } assert(g_env_warn == 0); printf("3. 学习期压线=搁置, 恢复后学完替换, 灭 OK\n"); } /* ===== 场景 4: 学习窗不稳 → 预算 30s 放弃 — 不污染, 黄灯保持 ===== */ static void test_unstable_learn_gives_up(void) { int loop; int i; reset_all(); for (loop = 0; loop < 700; loop++) { sim_CAPVD = 128856UL; sim_tick(); } assert(g_env_resync == 1); assert(sim_learn_start_cnt == 1); for (i = 0; i < 3800 && !sim_abort_cnt; i++) { /* 每窗 200 样本交替 → 漂移 200 > band~129 → 恒不稳 */ sim_CAPVD = ((i / 200) & 1) ? 129256UL : 129056UL; sim_tick(); } printf("4. 不稳学习: resync=%d abort=%d applied=%d warn=%d Origin=%u (期望 0/1/0/1/128095)\n", g_env_resync, sim_abort_cnt, sim_applied_cnt, g_env_warn, sim_Origin); assert(g_env_resync == 0); assert(sim_abort_cnt >= 1); assert(sim_applied_cnt == 0); assert(sim_Origin == 128095UL); /* 不污染 */ assert(g_env_warn == 1); /* 环境仍异常 → 黄灯保持 */ printf("4. 学习放弃不污染, 黄灯保持 OK\n"); } /* ===== 场景 5: 替换后稳态无重复学习 ===== */ static void test_no_repeat_learn(void) { int loop; reset_all(); for (loop = 0; loop < 700; loop++) { sim_CAPVD = 128856UL; sim_tick(); } for (loop = 0; loop < 1000; loop++) { sim_CAPVD = 128856UL; sim_tick(); if (sim_applied_cnt) break; } printf("5. 替换后稳态: applied=%d learn=%d warn=%d Origin=%u (期望 1/1/1/128856)\n", sim_applied_cnt, sim_learn_start_cnt, g_env_warn, sim_Origin); assert(sim_applied_cnt == 1); assert(sim_learn_start_cnt == 1); assert(sim_Origin == 128856UL); assert(g_env_warn == 1); /* 替换后 warn 锁存, 待恢复确认 */ for (loop = 0; loop < 1000; loop++) { /* 空闲稳态 10s → 灭且无重复学习 */ sim_CAPVD = 128856UL; sim_tick(); } assert(sim_applied_cnt == 1); assert(sim_learn_start_cnt == 1); assert(g_env_warn == 0); printf("5. 替换后无重复学习, 恢复确认后灭 OK\n"); } int main(void) { printf("test_env_resync (V4.31: 预判2s/补偿7s/恢复2s)\n"); test_permanent_change_recovers(); test_transient_keeps_warn(); test_interrupted_learn_recomputes(); test_unstable_learn_gives_up(); test_no_repeat_learn(); printf("ALL PASS (ENV_WARN 200 / RESYNC 700 / RECOVER 200)\n"); return 0; }