Post-Silicon Validation
Verify that a physical microprocessor sample behaves in accordance with its datasheet. The tool connects to a target over a debug probe, reads documented registers/memory, and reports PASS / FAIL / INDETERMINATE against datasheet-derived expectations — with a citation for every check.
v1 target: STM32F103C8T6 (Arm Cortex-M3) over ST-Link V2 / SWD, via
pyOCD. See docs/post_silicon_validation_prd.md for the full PRD.
Architecture
Four decoupled layers (PRD FR5.1) — swap any one without touching the others:
datasheets/*.yaml → Datasheet model (data, not code — FR2.1)
psv/model/ → Loader + schema (validates the YAML into typed objects)
psv/engine/ → Check engine (reads target, judges PASS/FAIL/INDETERMINATE)
psv/transport/ → Debug transport (pyOCD | mock; abstract base = Transport)
psv/report/ → Reporting (JSON + Markdown, timestamped, cited)
psv/cli.py → CLI entry point
Setup
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
Confirm the probe is seen: python -m pyocd list
Web Dashboard (Frontend + API)
The React dashboard talks to a FastAPI backend that wraps the same validation engine used by the CLI.
Start the API
.\.venv\Scripts\python.exe -m uvicorn psv.api:app --reload --port 8000
API docs: http://localhost:8000/docs
Start the frontend
In a second terminal:
cd frontend
npm install
npm run dev
Open http://localhost:5173 — the Vite dev server proxies /api to port 8000.
Copy .env.example to .env and set ANTHROPIC_API_KEY for document scan.
Active project model
Executable checks live in projects/postsiliconf1/model.yaml.
The API and dashboard read this file — not hardcoded UI data. Upload + scan produces
model.draft.yaml; activate it from the UI or POST /api/model/activate.
Real hardware workflow
- Connect ST-Link + STM32F103C8T6; verify
python -m pyocd list - Start API + frontend (below)
- Upload datasheet PDFs on Project Overview → Scan with Claude → Activate draft
- Open Peripheral Dashboard → Run Validation (uses pyOCD by default)
- Use Mock run (no hardware) only for offline dev
API endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/device |
ST-Link / SWD connection status |
| GET | /api/project |
Target metadata from active model + uploaded docs |
| GET | /api/peripherals |
Navigation derived from model groups |
| GET | /api/peripherals/{id} |
Checks, coverage from latest report |
| POST | /api/validate |
Run checks (mock: false default; optional peripheral_id) |
| POST | /api/documents |
Upload PDF/TXT/MD |
| POST | /api/documents/scan |
Claude extraction → draft model |
| POST | /api/model/activate |
Promote draft to active model |
| GET | /api/reports |
List report files |
Usage (CLI)
# Validate on real hardware (active project model or legacy path)
.\.venv\Scripts\python.exe -m psv --datasheet projects\postsiliconf1\model.yaml
# Mock transport (values derived from model expectations)
.\.venv\Scripts\python.exe -m psv --datasheet projects\postsiliconf1\model.yaml --mock
Each run prints a summary and writes timestamped reports/<part>_<ts>.json and
.md artifacts. Exit code is 0 only if every check passes (non-zero on any
FAIL/INDETERMINATE), so it drops straight into CI or a bench script.
Adding checks (no code changes — FR5.2)
Edit the datasheet YAML. A check is: an access (how to read a value), an
expect (how to judge it), and a citation.
- id: flash.size
name: Flash size register (F_SIZE)
access:
op: read16 # read8 | read16 | read32
address: 0x1FFFF7E0
shift: 0 # optional: (raw >> shift) & mask
mask: 0xFFFF # optional bitfield mask
expect:
equals: 64 # or: one_of: [..] | in_range: [min, max]
unit: KB
citation: "DS5319 — flash size register; C8 = 64 KB"
Safety
v1 is read-only (PRD NFR3). The pyOCD transport implements no writes, so no run can brick the target via flash or option-byte access.
Tests
.\.venv\Scripts\python.exe tests\test_engine.py
.\.venv\Scripts\python.exe tests\test_catalog.py
.\.venv\Scripts\python.exe tests\test_mock_memory.py
.\.venv\Scripts\python.exe tests\test_extract.py
.\.venv\Scripts\python.exe tests\smoke_api.py # API on :8000
$env:PSV_HARDWARE=1; .\.venv\Scripts\python.exe tests\test_hardware.py # optional bench
Most tests use mock transport. Set PSV_HARDWARE=1 only when ST-Link and target are connected.
Status
Active project model includes identification, flash size, RCC/GPIO/I2C reset-value checks (RM0008 / DS5319). Upload + Claude scan extends the model from your documents. Functional I2C/UART bus tests remain future work (bench wiring).
Log in or sign up for Devpost to join the conversation.