Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions .github/workflows/rtl-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# rtl-lint — Verilator --lint-only gate for the RTL coding-style conventions.
# Implements convention #4 of docs/rtl_conventions.md: the style guide is
# ENFORCED, not just documented. atalla had the guide but not the gate.
#
# ── POSTURE: SOFT (advisory) initially ────────────────────────────────────
# This gate is ADDITIVE and starts NON-BLOCKING so it cannot red-wall the
# existing, timing-closed blocks (which predate these conventions and are not
# yet lint-clean). It lints every per-top `.f` filelist it can find — today
# that is the worked template; it grows automatically as blocks adopt `.f`
# filelists (convention #3). Nothing here reorganizes or fails a proven block.
#
# ── HOW TO FLIP IT TO BLOCKING (do this once the RTL is lint-clean) ────────
# 1. delete the `continue-on-error: true` line on the `lint` job below, and
# 2. set LINT_BLOCKING: "1" in the env: block below (turns the soft
# per-filelist failures into a non-zero job exit).
# Until both are done, a lint failure is reported (annotations + summary) but
# the check stays green.

name: rtl-lint

on:
pull_request:
branches: [rev0, main]
paths:
- "**/*.sv"
- "**/*.svh"
- "**/*.v"
- "**/*.f"
- "docs/rtl_conventions*/**"
- ".github/workflows/rtl-lint.yml"
push:
branches: [rev0]
workflow_dispatch: {}

concurrency:
group: rtl-lint-${{ github.ref }}
cancel-in-progress: true

jobs:
lint:
runs-on: ubuntu-latest
# SOFT GATE: remove this line to make Verilator lint blocking (see header).
continue-on-error: true
env:
# "0" = soft (report, never fail the job). "1" = fail the job on any lint error.
LINT_BLOCKING: "0"
steps:
- uses: actions/checkout@v4

- name: Install Verilator
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends verilator
verilator --version

- name: Lint every per-top .f filelist
shell: bash
run: |
set -uo pipefail
# Discover all per-top filelists. `.f` files are the convention-#3
# ordered lists that BOTH sim and hardening consume, so they define
# the lintable design set. Skip vendored/build dirs.
mapfile -t FLISTS < <(git ls-files '*.f' | grep -vE '(^|/)(sim_build|node_modules)/' || true)

if [ "${#FLISTS[@]}" -eq 0 ]; then
echo "No .f filelists found — nothing to lint yet (expected until blocks adopt convention #3)."
exit 0
fi

rc=0
for f in "${FLISTS[@]}"; do
dir=$(dirname "$f") # filelists/ lives beside include/ rtl/
base=$(basename "$f" .f) # <top> name == filelist stem
root=$(dirname "$dir") # the module tree root (…/ above filelists/)
echo "::group::verilator --lint-only $f (top=$base)"
# Run from the tree root so the .f's relative paths resolve.
( cd "$root" && verilator --lint-only -Wall --top-module "$base" \
-f "filelists/$base.f" ) || {
echo "::error file=$f::verilator lint failed for top '$base'"
rc=1
}
echo "::endgroup::"
done

if [ "$rc" -ne 0 ]; then
echo "### rtl-lint: Verilator reported lint errors" >> "$GITHUB_STEP_SUMMARY"
echo "Gate is currently **soft** (LINT_BLOCKING=$LINT_BLOCKING). See docs/rtl_conventions.md §4." >> "$GITHUB_STEP_SUMMARY"
else
echo "### rtl-lint: all filelists lint-clean ✅" >> "$GITHUB_STEP_SUMMARY"
fi

if [ "$LINT_BLOCKING" = "1" ]; then
exit "$rc"
fi
exit 0

- name: Advisory RTL-conventions structure scan
# Never fails; mirrors the local `make`-side advisory. Pure signal for reviewers.
run: |
python3 scripts/check_block_structure.py --check-rtl-conventions || true
15 changes: 15 additions & 0 deletions DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@

# DECISIONS — chip-wide (do not re-litigate unless the premise changed)

- **RTL-organization conventions adopted (mirrored tree + interface taxonomy + ordered `.f` +
lint-gated style)** · borrowed/trimmed from the peer teaching-tapeout repo Purdue-SoCET/atalla to
make the repo legible for the incoming cohort: (1) mirrored `include↔rtl↔tb` trees sharing a
per-module subpath so ONE generic target (`make {lint,test} MOD=<mod>`) builds any module by name;
(2) SV interface taxonomy — `<mod>_if.sv` + shared `<block>_pkg` + `<mod>_params.svh`, `modport
<a>_<b>` named for the two modules it connects; (3) one ordered per-top `.f` consumed by BOTH sim
and LibreLane so they never disagree on compile order; (4) a SHALL/SHOULD/MAY style guide ENFORCED
by a Verilator `--lint-only` CI gate (the enforcement is the point — atalla had the guide, not the
gate). **ADDITIVE ONLY:** no existing block was reorganized; conventions apply to NEW modules and
are the migration target for existing ones. Spec + runnable template (`make test MOD=regadd` passes
under iverilog 12 + cocotb 2.0.1) in `docs/rtl_conventions.md` + `docs/rtl_conventions_template/`;
structure check gains opt-in advisory `--check-rtl-conventions`; lint CI
(`.github/workflows/rtl-lint.yml`) ships SOFT (non-blocking) so it can't red-wall proven blocks.
Migrating existing blocks to the mirrored tree is proposed but deliberately NOT done here. ·
2026-08-01.
- **RAMP (arXiv 2603.17891) evaluated and REJECTED for Lambda** · both of its ideas fail once
measured against the chip's real quant. (1) Per-layer weight bit allocation: Qwen2-1.5B layers
are near-uniform in weight sensitivity (spread 1.17×) → only ~1.6% gain, and it costs +34% MAC
Expand Down
Loading
Loading