Skip to content

Commit cd23533

Browse files
mcelikxclaude
andcommitted
docs: add README, contributing guide, and validation CI
The repository had no entry point. README covers the architecture, the latency budget, the documentation map, and — prominently — that nothing here has been compiled, simulated, or run on hardware, so no reader mistakes design targets for measurements. CI gates on structural defects only. Broken links are reported but not blocking, since manual tiers 10 and 11 are knowingly incomplete; adding --ignore-category keeps that distinction explicit rather than lowering the bar globally. Verilator lint reports without gating until the tree is clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 56de423 commit cd23533

5 files changed

Lines changed: 582 additions & 2 deletions

File tree

.github/workflows/validate.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Validate
2+
3+
# Structural validation of the repository. This does NOT prove the design is
4+
# correct or fast — that needs simulation against the golden model and a
5+
# post-route timing report, neither of which runs here.
6+
#
7+
# It proves the tree is internally consistent: every module the top level
8+
# instantiates exists, the RTL obeys the coding rules in CLAUDE.md, and
9+
# cross-references resolve.
10+
11+
on:
12+
push:
13+
branches: [main]
14+
pull_request:
15+
branches: [main]
16+
workflow_dispatch:
17+
18+
permissions:
19+
contents: read
20+
21+
jobs:
22+
validate:
23+
name: Repository consistency
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: actions/checkout@v4
27+
28+
- uses: actions/setup-python@v5
29+
with:
30+
python-version: "3.11"
31+
32+
# Broken links are ignored as a build gate because manual tiers 10 and 11
33+
# are knowingly incomplete — the count is reported below so the gap stays
34+
# visible rather than being silently tolerated.
35+
- name: Validate structure
36+
run: |
37+
python3 scripts/validate.py \
38+
--quiet \
39+
--html docs/validation-report.html \
40+
--ignore-category broken-link
41+
42+
- name: Report metrics
43+
if: always()
44+
run: |
45+
python3 scripts/validate.py 2>/dev/null \
46+
| python3 scripts/ci_summary.py >> "$GITHUB_STEP_SUMMARY"
47+
48+
- name: Upload report
49+
if: always()
50+
uses: actions/upload-artifact@v4
51+
with:
52+
name: validation-report
53+
path: docs/validation-report.html
54+
retention-days: 30
55+
56+
lint:
57+
name: RTL lint
58+
runs-on: ubuntu-latest
59+
# Verilator is not yet clean across the tree — this reports rather than
60+
# gates. Flip continue-on-error off once `scripts/lint.sh` passes.
61+
continue-on-error: true
62+
steps:
63+
- uses: actions/checkout@v4
64+
65+
- name: Install Verilator
66+
run: |
67+
sudo apt-get update
68+
sudo apt-get install -y verilator
69+
verilator --version
70+
71+
- name: Lint
72+
run: ./scripts/lint.sh

CONTRIBUTING.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Contributing
2+
3+
This is a real-money trading system. The bar is higher than for most codebases, and the
4+
reasons are in [`CLAUDE.md`](CLAUDE.md) §5 and §6. Read those first.
5+
6+
---
7+
8+
## Before you write RTL
9+
10+
1. **Read the governing manual.** Every block has one; it is named in the module header.
11+
The manuals encode the constraints that make the design correct *and* fast. Skipping
12+
them produces code that synthesizes, misses timing, and blows the latency budget.
13+
2. **State the latency budget** in nanoseconds and cycles, in the module header. A block
14+
without a budget is not reviewable.
15+
3. **State the resource budget** — LUT/FF/BRAM/URAM/DSP — in the same header.
16+
17+
## Coding standard
18+
19+
Full detail in [`manuals/00-foundations/03-hdl-and-rtl-coding.md`](manuals/00-foundations/03-hdl-and-rtl-coding.md).
20+
21+
- Synthesizable **SystemVerilog IEEE 1800-2017**. `logic` only, never `reg`/`wire`.
22+
- `always_ff` / `always_comb` only. Never bare `always`. `<=` in ff, `=` in comb.
23+
- **No latches.** Default assignments open every `always_comb`; every `case` has a `default`.
24+
- Synchronous active-high `rst`. Reset control state only, never datapath registers.
25+
- Registered outputs by default; exceptions justified in a comment.
26+
- All literals sized (`8'd5`), all parameters typed (`parameter int unsigned`).
27+
- Named generate blocks. One module per file, filename == module name.
28+
- `` `default_nettype none `` at the top, `` `default_nettype wire `` at the bottom.
29+
- SVA assertions inside `` `ifndef SYNTHESIS `` on every stream interface and invariant.
30+
- **No division, no modulo, no floating point.**
31+
32+
CDC uses only the sanctioned primitives in [`rtl/common/`](rtl/common/). Hand-rolling a
33+
synchronizer is a review failure, not a style disagreement — the failure mode is a design
34+
that works for months and then corrupts one order.
35+
36+
## Before you open a PR
37+
38+
```bash
39+
python3 scripts/validate.py --ignore-category broken-link # must exit 0
40+
./scripts/lint.sh # Verilator, -Wall clean
41+
make -C scripts sim # testbenches pass
42+
```
43+
44+
- **Every fast-path module needs a testbench.** No exceptions.
45+
- Do not report "done" until place-and-route timing closes.
46+
- Quote **WNS/TNS and utilization verbatim from the report**. Never estimate them.
47+
- If a latency number was simulated, say "simulated". If measured on hardware, say
48+
"measured, N=…". These are not interchangeable and conflating them wastes everyone's time.
49+
50+
## Suppressing a validator rule
51+
52+
Rules can be suppressed, but never silently:
53+
54+
```systemverilog
55+
localparam real CLKFB_MULT_F = 12.500; // validate: allow real — vendor MMCM declares it real
56+
```
57+
58+
The justification is mandatory. A suppression without one is itself reported.
59+
60+
---
61+
62+
## 🔒 Changes that need extra care
63+
64+
These have a blast radius beyond the file you are editing.
65+
66+
| Change | Requirement |
67+
|---|---|
68+
| **Risk limits, order sizing, kill switch** | Separate commit, separate review, separate audit entry. **Never bundled with other work.** |
69+
| **`rtl/pkg/trading_pkg.sv`** | System-wide contract. Say so explicitly and update the latency budget in the same commit. |
70+
| **`rtl/fpga_top.sv`** | Holds the master latency budget. Any added cycle must be justified in the PR. |
71+
| **ITCH/OUCH field offsets** | Must be verified against the current spec PDF and the verification recorded. A wrong offset produces a decoder that corrupts *some* messages silently. |
72+
| **Anything touching a live venue** | Never. Simulated and UAT endpoints only, until conformance certification is complete. |
73+
74+
## What must never be optimized away
75+
76+
The risk gate, the kill switch, gap detection, and the error counters. Removing a check to
77+
save a cycle converts a latency problem into a solvency problem.
78+
79+
## Never commit
80+
81+
Venue credentials, comp IDs, session IDs, MPIDs, production IP addresses, or recorded
82+
exchange market data. `.gitignore` covers the common cases; it is not a substitute for
83+
looking at your diff.
84+
85+
---
86+
87+
## Commit messages
88+
89+
Conventional-Commit prefixes (`feat:`, `fix:`, `chore:`, `docs:`, `refactor:`, `test:`,
90+
`build:`), imperative mood, subject ≤ 72 chars. The body explains **why**, not a file-by-file
91+
recap — and in this codebase the *why* is usually a failure mode being prevented. Say what
92+
it is.

0 commit comments

Comments
 (0)