fix(pps): align firmware TOW with current RTL
This commit is contained in:
@@ -49,9 +49,9 @@ The default command executes the diagnostic matrix:
|
||||
|
||||
```text
|
||||
scenario bits correction reference error DUT - trusted PPS
|
||||
current-rtl/180ms 9 180 ms -0.000032 ms +0.000032 ms
|
||||
current-rtl/160ms 9 160 ms -20.000032 ms +20.000032 ms
|
||||
current-bit/160ms 8 160 ms -0.000032 ms +0.000032 ms
|
||||
current-rtl/180ms 9 180 ms -0.000032 ms +0.000032 ms
|
||||
```
|
||||
|
||||
Positive `DUT - trusted PPS` means the project output is late. The default
|
||||
@@ -110,7 +110,8 @@ jitter assertion or synthetic run cannot certify it.
|
||||
The sweep includes the current coefficients, quieter/faster precision loops,
|
||||
a robust-noise guard, a larger Doppler-drift gain, and a quality-scheduled
|
||||
candidate. The generated report contains the current numerical comparison.
|
||||
No production constants are changed by the analysis.
|
||||
The stability analysis does not alter loop constants. Production firmware now
|
||||
uses the current-RTL-compatible 180 ms epoch correction described below.
|
||||
|
||||
## 20 ms diagnosis
|
||||
|
||||
@@ -124,15 +125,18 @@ The implemented interface is consequently:
|
||||
|
||||
```text
|
||||
current RTL delivery 9 * 20 ms = 180 ms
|
||||
firmware POSTPONE_TOW 8 * 20 ms = 160 ms
|
||||
signed epoch mismatch 20 ms
|
||||
production POSTPONE_TOW 9 * 20 ms = 180 ms
|
||||
signed epoch mismatch 0 ms
|
||||
|
||||
former firmware value 8 * 20 ms = 160 ms
|
||||
former signed mismatch 20 ms
|
||||
```
|
||||
|
||||
With the current bitstream, `POSTPONE_TOW=0.180` is a firmware-only workaround
|
||||
and must be used consistently by both satellite-state and PPS calculations.
|
||||
It is 180 ms, not 190 ms. The preferred permanent correction is to validate a
|
||||
candidate window containing the current eighth bit and retain the intended
|
||||
160 ms firmware compensation.
|
||||
Production firmware now uses `POSTPONE_TOW=0.180` as the current-RTL-compatible
|
||||
correction, consistently in both satellite-state and PPS calculations. It is
|
||||
180 ms, not 190 ms. If RTL is later changed to validate a candidate window
|
||||
containing the current eighth bit, firmware must return to 160 ms in the same
|
||||
coordinated release.
|
||||
|
||||
The validation intentionally does not modify production RTL or firmware.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ This report is generated by `stability_analysis.py`. The absolute LNAV epoch pat
|
||||
- Current RTL delivered the validated subframe after 9 following bits.
|
||||
- With 180 ms postponement, reference error was -0.000032 ms.
|
||||
- DUT minus trusted PPS was 32.01 ns. That remainder is the model's configured four-PCLK capture pipeline, not a measured board delay.
|
||||
- The production source still defines `POSTPONE_TOW` as 160 ms; this analysis uses the requested 180 ms candidate configuration.
|
||||
- Production firmware and this analysis both define `POSTPONE_TOW` as 180 ms for the current RTL delivery semantics.
|
||||
|
||||
## Repository hardware data
|
||||
|
||||
|
||||
@@ -589,7 +589,7 @@ def simulate_pps_core(
|
||||
@dataclass(frozen=True)
|
||||
class EndToEndConfig:
|
||||
decoder_mode: DecoderMode = DecoderMode.CURRENT_RTL
|
||||
postpone_tow_s: float = 0.160
|
||||
postpone_tow_s: float = 0.180
|
||||
nav_solve_period_bits: int = 10
|
||||
propagation_s: float = 0.070
|
||||
pps_capture_pipeline_ticks: int = 4
|
||||
@@ -790,14 +790,14 @@ def default_comparison() -> tuple[EndToEndResult, ...]:
|
||||
run_end_to_end(EndToEndConfig()),
|
||||
run_end_to_end(
|
||||
EndToEndConfig(
|
||||
decoder_mode=DecoderMode.CURRENT_BIT,
|
||||
decoder_mode=DecoderMode.CURRENT_RTL,
|
||||
postpone_tow_s=0.160,
|
||||
)
|
||||
),
|
||||
run_end_to_end(
|
||||
EndToEndConfig(
|
||||
decoder_mode=DecoderMode.CURRENT_RTL,
|
||||
postpone_tow_s=0.180,
|
||||
decoder_mode=DecoderMode.CURRENT_BIT,
|
||||
postpone_tow_s=0.160,
|
||||
)
|
||||
),
|
||||
)
|
||||
@@ -838,7 +838,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
||||
default="matrix",
|
||||
help="run the three-way diagnosis matrix or one decoder mode",
|
||||
)
|
||||
parser.add_argument("--postpone-ms", type=float, default=160.0)
|
||||
parser.add_argument("--postpone-ms", type=float, default=180.0)
|
||||
parser.add_argument("--propagation-ms", type=float, default=70.0)
|
||||
parser.add_argument("--capture-pipeline-ticks", type=int, default=4)
|
||||
parser.add_argument("--compute-delay-ms", type=float, default=10.0)
|
||||
|
||||
@@ -597,8 +597,8 @@ def write_report(
|
||||
f"{epoch_result.pps.edges[0].dut_minus_trusted_s * 1.0e9:.2f} ns. "
|
||||
"That remainder is the model's configured four-PCLK capture pipeline, "
|
||||
"not a measured board delay.",
|
||||
"- The production source still defines `POSTPONE_TOW` as 160 ms; this "
|
||||
"analysis uses the requested 180 ms candidate configuration.",
|
||||
"- Production firmware and this analysis both define `POSTPONE_TOW` "
|
||||
"as 180 ms for the current RTL delivery semantics.",
|
||||
"",
|
||||
"## Repository hardware data",
|
||||
"",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import re
|
||||
import unittest
|
||||
|
||||
from pps_end_to_end_validation.pps_end_to_end import (
|
||||
@@ -50,6 +52,22 @@ class LnavDecoderTests(unittest.TestCase):
|
||||
|
||||
|
||||
class PpsEndToEndTests(unittest.TestCase):
|
||||
def test_model_default_matches_production_firmware_postpone_tow(self):
|
||||
header = (
|
||||
Path(__file__).resolve().parents[1]
|
||||
/ "gps_system/header/gps/gps_ip_defines.h"
|
||||
).read_text(encoding="utf-8")
|
||||
match = re.search(
|
||||
r"#define\s+POSTPONE_TOW\s+\(double\)\(([0-9.]+)\)",
|
||||
header,
|
||||
)
|
||||
self.assertIsNotNone(match)
|
||||
self.assertAlmostEqual(float(match.group(1)), 0.180)
|
||||
self.assertAlmostEqual(
|
||||
EndToEndConfig().postpone_tow_s,
|
||||
float(match.group(1)),
|
||||
)
|
||||
|
||||
def test_bit_generator_recreates_50bps_stream_and_registered_sample_lag(self):
|
||||
result = run_end_to_end(EndToEndConfig())
|
||||
self.assertEqual(result.bit_valid_events, 2 + 3 * 300)
|
||||
@@ -76,7 +94,7 @@ class PpsEndToEndTests(unittest.TestCase):
|
||||
self.assertGreater(result.firmware_rejected_nav_solves, 0)
|
||||
|
||||
def test_current_rtl_and_160ms_correction_make_pps_20ms_late(self):
|
||||
result = run_end_to_end(EndToEndConfig())
|
||||
result = run_end_to_end(EndToEndConfig(postpone_tow_s=0.160))
|
||||
offset_s = result.pps.edges[0].dut_minus_trusted_s
|
||||
self.assertAlmostEqual(result.expected_semantic_offset_ms, 20.0, places=9)
|
||||
self.assertGreater(offset_s, 0.019999)
|
||||
@@ -86,17 +104,18 @@ class PpsEndToEndTests(unittest.TestCase):
|
||||
|
||||
def test_current_bit_validation_and_160ms_remove_lnav_bit_error(self):
|
||||
result = run_end_to_end(
|
||||
EndToEndConfig(decoder_mode=DecoderMode.CURRENT_BIT)
|
||||
EndToEndConfig(
|
||||
decoder_mode=DecoderMode.CURRENT_BIT,
|
||||
postpone_tow_s=0.160,
|
||||
)
|
||||
)
|
||||
self.assertEqual(result.first_subframe_readout_bits, 8)
|
||||
self.assertEqual(result.first_nav_solve_bit, 18)
|
||||
self.assertAlmostEqual(result.expected_semantic_offset_ms, 0.0, places=9)
|
||||
self.assertLess(abs(result.pps.edges[0].dut_minus_trusted_s), 100.0e-9)
|
||||
|
||||
def test_180ms_firmware_workaround_matches_current_rtl(self):
|
||||
result = run_end_to_end(
|
||||
EndToEndConfig(postpone_tow_s=0.180)
|
||||
)
|
||||
def test_180ms_production_firmware_matches_current_rtl(self):
|
||||
result = run_end_to_end(EndToEndConfig())
|
||||
self.assertEqual(result.first_subframe_readout_bits, 9)
|
||||
self.assertAlmostEqual(result.expected_semantic_offset_ms, 0.0, places=9)
|
||||
self.assertLess(abs(result.pps.edges[0].dut_minus_trusted_s), 100.0e-9)
|
||||
@@ -119,12 +138,16 @@ class PpsEndToEndTests(unittest.TestCase):
|
||||
result = run_end_to_end(
|
||||
EndToEndConfig(
|
||||
decoder_mode=DecoderMode.CURRENT_BIT,
|
||||
postpone_tow_s=0.160,
|
||||
dut_output_delay_s=12.0e-9,
|
||||
trusted_output_delay_s=35.0e-9,
|
||||
)
|
||||
)
|
||||
baseline = run_end_to_end(
|
||||
EndToEndConfig(decoder_mode=DecoderMode.CURRENT_BIT)
|
||||
EndToEndConfig(
|
||||
decoder_mode=DecoderMode.CURRENT_BIT,
|
||||
postpone_tow_s=0.160,
|
||||
)
|
||||
)
|
||||
delta = (
|
||||
result.pps.edges[0].dut_minus_trusted_s
|
||||
|
||||
Reference in New Issue
Block a user