diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed3fa1d..232f01f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -143,7 +143,7 @@ jobs: cargo run --release --features metal --bin jacquard -- sim \ tests/timing_test/inv_chain_pnr/inv_chain.v \ tests/timing_test/inv_chain_pnr/inv_chain_stimulus.vcd \ - tests/timing_test/inv_chain_pnr/loom_timed_output.vcd \ + tests/timing_test/inv_chain_pnr/jacquard_timed_output.vcd \ 1 \ --sdf tests/timing_test/inv_chain_pnr/inv_chain_test_ps.sdf \ --sdf-corner typ \ @@ -158,7 +158,7 @@ jobs: path: | tests/timing_test/ci_output.vcd tests/timing_test/ci_xprop_output.vcd - tests/timing_test/inv_chain_pnr/loom_timed_output.vcd + tests/timing_test/inv_chain_pnr/jacquard_timed_output.vcd metal_timing.txt metal_xprop.txt metal_timed.txt @@ -540,7 +540,7 @@ jobs: --sdf tests/mcu_soc/data/6_final_stripped.sdf \ --sdf-corner typ \ --stimulus-vcd tests/mcu_soc/stimulus.vcd \ - --timing-vcd tests/mcu_soc/loom_timed_mcu.vcd \ + --timing-vcd tests/mcu_soc/jacquard_timed_mcu.vcd \ 2>&1 | tee cosim_stimulus.txt - name: Replay stimulus (non-timed, for CVC comparison) @@ -550,7 +550,7 @@ jobs: cargo run --release --features metal --bin jacquard -- sim \ tests/mcu_soc/data/6_final.v \ tests/mcu_soc/stimulus.vcd \ - tests/mcu_soc/loom_replay_mcu.vcd \ + tests/mcu_soc/jacquard_replay_mcu.vcd \ 1 \ --top-module top \ --max-cycles 10000 \ @@ -589,8 +589,8 @@ jobs: metal_mcu_replay.txt tests/mcu_soc/sim_config.json tests/mcu_soc/stimulus.vcd - tests/mcu_soc/loom_replay_mcu.vcd - tests/mcu_soc/loom_timed_mcu.vcd + tests/mcu_soc/jacquard_replay_mcu.vcd + tests/mcu_soc/jacquard_timed_mcu.vcd # Build documentation (cargo doc + mdbook) and deploy to GitHub Pages docs: @@ -742,9 +742,9 @@ jobs: tests/timing_test/inv_chain_pnr/cvc_output.log tests/timing_test/inv_chain_pnr/cvc_inv_chain_output.vcd - # Compare timing results between CVC (event-driven) and Loom (GPU) + # Compare timing results between CVC (event-driven) and Jacquard (GPU) timing-comparison: - name: Timing Comparison (CVC vs Loom) + name: Timing Comparison (CVC vs Jacquard) runs-on: ubuntu-latest needs: [metal, cvc-reference] if: always() && needs.metal.result == 'success' && needs.cvc-reference.result == 'success' @@ -770,7 +770,7 @@ jobs: uv run scripts/compare_timing.py \ --cvc-log cvc-results/tests/timing_test/inv_chain_pnr/cvc_output.log \ --cvc-vcd cvc-results/tests/timing_test/inv_chain_pnr/cvc_inv_chain_output.vcd \ - --loom-vcd metal-results/tests/timing_test/inv_chain_pnr/loom_timed_output.vcd \ + --jacquard-vcd metal-results/tests/timing_test/inv_chain_pnr/jacquard_timed_output.vcd \ --clock-period-ps 10000 \ --clock-signal CLK \ --output-signal Q \ @@ -781,7 +781,7 @@ jobs: if: always() run: | { - echo "## Timing Comparison (CVC vs Loom)" + echo "## Timing Comparison (CVC vs Jacquard)" echo "" echo "\`\`\`" cat comparison.txt 2>/dev/null || echo "No comparison output" @@ -894,7 +894,7 @@ jobs: tests/mcu_soc/cvc/cvc_sim.log tests/mcu_soc/cvc/cvc_output.vcd - # Compare MCU SoC results between CVC (event-driven) and Loom (GPU) + # Compare MCU SoC results between CVC (event-driven) and Jacquard (GPU) mcu-soc-comparison: name: MCU SoC Functional Comparison runs-on: ubuntu-latest @@ -917,25 +917,25 @@ jobs: name: mcu-soc-cvc-results path: cvc-results/ - - name: Compare outputs (non-timed Loom vs CVC) + - name: Compare outputs (non-timed Jacquard vs CVC) run: | - LOOM_VCD="metal-results/tests/mcu_soc/loom_replay_mcu.vcd" + JACQUARD_VCD="metal-results/tests/mcu_soc/jacquard_replay_mcu.vcd" CVC_VCD="cvc-results/cvc_output.vcd" - if [ ! -f "$LOOM_VCD" ]; then - echo "SKIP: Loom replay VCD not found" | tee mcu_comparison.txt + if [ ! -f "$JACQUARD_VCD" ]; then + echo "SKIP: Jacquard replay VCD not found" | tee mcu_comparison.txt exit 0 fi if [ ! -f "$CVC_VCD" ]; then echo "SKIP: CVC output VCD not found (CVC simulation may have failed)" | tee mcu_comparison.txt exit 0 fi - LOOM_TIMING_VCD="metal-results/tests/mcu_soc/loom_timed_mcu.vcd" + JACQUARD_TIMING_VCD="metal-results/tests/mcu_soc/jacquard_timed_mcu.vcd" TIMING_ARGS="" - if [ -f "$LOOM_TIMING_VCD" ]; then - TIMING_ARGS="--loom-timing-vcd $LOOM_TIMING_VCD" + if [ -f "$JACQUARD_TIMING_VCD" ]; then + TIMING_ARGS="--jacquard-timing-vcd $JACQUARD_TIMING_VCD" fi uv run tests/mcu_soc/cvc/compare_simulation.py \ - "$LOOM_VCD" "$CVC_VCD" \ + "$JACQUARD_VCD" "$CVC_VCD" \ --skip-cycles 5 \ --num-cycles 10000 \ --skip-bits 0-5 \ @@ -947,7 +947,7 @@ jobs: if: always() run: | { - echo "## MCU SoC Simulation Comparison (CVC vs Loom)" + echo "## MCU SoC Simulation Comparison (CVC vs Jacquard)" echo "" echo "\`\`\`" cat mcu_comparison.txt 2>/dev/null || echo "No comparison output" diff --git a/docs/cosim-timing-support.md b/docs/cosim-timing-support.md index 3677611..d20e0cc 100644 --- a/docs/cosim-timing-support.md +++ b/docs/cosim-timing-support.md @@ -2,17 +2,17 @@ **Status**: Implementation plan for Goal step 8 (final step) -**Objective**: Enable arrival time readback in cosim mode so timing-annotated VCD can be produced without a separate `loom sim` replay. Completes timing validation feature parity with `loom sim`. +**Objective**: Enable arrival time readback in cosim mode so timing-annotated VCD can be produced without a separate `jacquard sim` replay. Completes timing validation feature parity with `jacquard sim`. ## Current State -### loom sim ✅ (Complete) +### jacquard sim ✅ (Complete) - Metal: `--timing-vcd` fully functional with arrival time readback - CUDA/HIP: In progress (step 7 - kernel FFI bindings) - Produces timing-annotated VCD with arrival times for all signals - Validated against CVC reference simulator -### loom cosim ❌ (No timing support) +### jacquard cosim ❌ (No timing support) - Supports co-simulation with external testbenches (via Verilog VCD) - **Does NOT support** `--timing-vcd` flag currently - CPU-GPU synchronized stepping; peripheral models run on CPU @@ -23,16 +23,16 @@ **Current workflow** (suboptimal): ```bash # Step 1: Run cosim to get functional outputs -loom cosim --input stimulus.vcd --output functional.vcd +jacquard cosim --input stimulus.vcd --output functional.vcd # Step 2: Run again with timing to get arrival times (slow!) -loom sim --input stimulus.vcd --output timed.vcd --sdf design.sdf --timing-vcd +jacquard sim --input stimulus.vcd --output timed.vcd --sdf design.sdf --timing-vcd ``` **Desired workflow** (step 8): ```bash # Single command produces both functional + timing outputs -loom cosim --input stimulus.vcd --output timed.vcd \ +jacquard cosim --input stimulus.vcd --output timed.vcd \ --sdf design.sdf --timing-vcd ``` diff --git a/docs/simulation-architecture.md b/docs/simulation-architecture.md index b26d14b..efe10b0 100644 --- a/docs/simulation-architecture.md +++ b/docs/simulation-architecture.md @@ -283,7 +283,7 @@ WARN (GATESIM_VCDI_MISSING_PI) Primary input port (HierName(), "reset", None) no ### 3. No Latch or Asynchronous Sequential Logic Support -**Issue**: Loom only supports edge-triggered D flip-flops (DFFs) as sequential elements. Latch-based designs (SR latches, transparent latches, master-slave latch pairs) and asynchronous sequential logic are not supported. +**Issue**: Jacquard only supports edge-triggered D flip-flops (DFFs) as sequential elements. Latch-based designs (SR latches, transparent latches, master-slave latch pairs) and asynchronous sequential logic are not supported. **Impact**: Designs using latches will either: - Fail during AIG conversion (unrecognized cell type) @@ -291,7 +291,7 @@ WARN (GATESIM_VCDI_MISSING_PI) Primary input port (HierName(), "reset", None) no **What this means in practice**: - Gate-level netlists must be synthesized to a DFF-only cell library (AIGPDK or SKY130) -- CVC's built-in test suite (`tests_and_examples/install.test/`) uses NAND-latch flip-flops (e.g., `dfpsetd.v`, `sdfia04.v`) and cannot be used as Loom reference tests +- CVC's built-in test suite (`tests_and_examples/install.test/`) uses NAND-latch flip-flops (e.g., `dfpsetd.v`, `sdfia04.v`) and cannot be used as Jacquard reference tests - Self-timed designs with internal clock generation (e.g., CVC's `das_lfsr` benchmark) are also unsupported **What would be needed to support latches**: @@ -304,7 +304,7 @@ WARN (GATESIM_VCDI_MISSING_PI) Primary input port (HierName(), "reset", None) no **Complexity estimate**: Moderate-to-high. The main challenge is the evaluation model change — DFF-only simulation is a clean "capture at edge" model, while latches require iterative evaluation within clock phases. -**Status**: Not planned. Loom targets synthesis flows that produce DFF-only netlists. +**Status**: Not planned. Jacquard targets synthesis flows that produce DFF-only netlists. ### 4. Format String Preservation **Issue**: Yosys synthesis may not preserve `gem_format` attributes diff --git a/docs/timing-simulation.md b/docs/timing-simulation.md index a629ccf..d4b901f 100644 --- a/docs/timing-simulation.md +++ b/docs/timing-simulation.md @@ -290,7 +290,7 @@ This is feasible but significantly increases memory pressure and computation. ## Conservative Timing Model: Sources of Overestimation -Loom's GPU timing is intentionally conservative — it may over-estimate arrival times +Jacquard's GPU timing is intentionally conservative — it may over-estimate arrival times but will never under-estimate them. This is important for setup violation detection: false positives are safe, false negatives would miss real bugs. @@ -309,7 +309,7 @@ delay = max(gate_delays[pin].rise_ps, gate_delays[pin].fall_ps) **Impact**: For the SKY130 inv_chain test (16 inverters), rise delays average ~10ps larger than fall delays. In a real inverter chain, transitions alternate (rise→fall→rise), -so half the cells use the smaller fall delay. Loom uses the larger rise delay for all. +so half the cells use the smaller fall delay. Jacquard uses the larger rise delay for all. **Measured**: 80ps overestimate on 1235ps (6.5%) for 16 inverters with ~10ps rise/fall asymmetry per cell. @@ -317,7 +317,7 @@ asymmetry per cell. ### Source 2: max wire delay across all input pins For multi-input cells (AND gates, MUXes), INTERCONNECT delays to different input pins -may differ significantly. Loom takes the maximum across all input pins: +may differ significantly. Jacquard takes the maximum across all input pins: ```rust // wire_delays_per_cell: dest_cellid → max(all input wire delays) @@ -326,7 +326,7 @@ entry.fall_ps = entry.fall_ps.max(ic.delay.fall_ps); ``` **Impact**: If an AND gate has input A arriving via a 10ps wire and input B via a -200ps wire, Loom assigns 200ps to the cell regardless of which input is on the +200ps wire, Jacquard assigns 200ps to the cell regardless of which input is on the critical path. An event-driven simulator would correctly propagate the 10ps arrival on input A independently. @@ -336,7 +336,7 @@ delays to multi-input cells. ### Source 3: max arrival across 32 packed signals per thread -Each thread position holds 32 independent Boolean signals. Loom tracks one arrival +Each thread position holds 32 independent Boolean signals. Jacquard tracks one arrival per thread position (the maximum across all 32 signals): ``` @@ -373,7 +373,7 @@ The inv_chain design (2 DFFs + 16 SKY130 inverters) was validated against CVC ``` CVC: clk_to_q=350ps chain=885ps total=1235ps (transition-accurate) -Loom: clk_to_q=350ps chain=973ps total=1323ps (conservative max) +Jacquard: clk_to_q=350ps chain=973ps total=1323ps (conservative max) Difference: 88ps (7.1% overestimate) ``` diff --git a/docs/timing-validation.md b/docs/timing-validation.md index b9a2a94..cd30370 100644 --- a/docs/timing-validation.md +++ b/docs/timing-validation.md @@ -24,7 +24,7 @@ GEM's timing simulation (`--timing-vcd` and `--enable-timing` flags) must be val ```bash # Example: MCU SoC functional comparison uv run tests/mcu_soc/cvc/compare_outputs.py \ - loom_output.vcd cvc_output.vcd \ + jacquard_output.vcd cvc_output.vcd \ --skip-cycles 5 # Skip first 5 cycles (reset/initialization) ``` @@ -75,7 +75,7 @@ cargo run -r --features metal --bin jacquard -- sim \ ``` **Expected results**: -- Loom Q arrival ≈ CVC total_delay (within ±5%) +- Jacquard Q arrival ≈ CVC total_delay (within ±5%) - Both simulators show monotonic delay increase with each inverter stage ### MCU SoC post-layout (Complex Case) @@ -95,11 +95,11 @@ uv run tests/mcu_soc/cvc/strip_sdf_checks.py \ tests/mcu_soc/data/6_final.sdf \ tests/mcu_soc/data/6_final_stripped.sdf -# 2. Generate Loom timing VCD +# 2. Generate Jacquard timing VCD cargo run -r --features metal --bin jacquard -- sim \ tests/mcu_soc/data/6_final.v \ tests/mcu_soc/stimulus.vcd \ - tests/mcu_soc/loom_timed_mcu.vcd 1 \ + tests/mcu_soc/jacquard_timed_mcu.vcd 1 \ --sdf tests/mcu_soc/data/6_final_stripped.sdf \ --sdf-corner typ \ --timing-vcd \ @@ -114,14 +114,14 @@ cvc64 +typdelays tests/mcu_soc/cvc/tb_cvc.v \ # 4. Compare functional outputs uv run tests/mcu_soc/cvc/compare_outputs.py \ - tests/mcu_soc/loom_timed_mcu.vcd \ + tests/mcu_soc/jacquard_timed_mcu.vcd \ tests/mcu_soc/cvc/cvc_output.vcd \ --skip-cycles 5 ``` **Expected results**: - Functional output: Exact match (or documented difference with explanation) -- Arrival times: Loom values ≥ CVC due to conservative path accumulation +- Arrival times: Jacquard values ≥ CVC due to conservative path accumulation - CI: Comparison completes without errors ### Pre-layout Library Timing @@ -151,19 +151,19 @@ python3 gen_liberty_sdf.py logic_cone.v cvc64 +typdelays tb_inv_chain.v inv_chain.v 2>&1 | tee cvc.log ./cvcsim -# Run Loom GPU simulation +# Run Jacquard GPU simulation cargo run -r --features metal --bin jacquard -- sim \ - inv_chain.v stimulus.vcd loom_output.vcd 1 \ + inv_chain.v stimulus.vcd jacquard_output.vcd 1 \ --sdf inv_chain.sdf \ --timing-vcd # Compare outputs -uv run ../../mcu_soc/cvc/compare_outputs.py loom_output.vcd cvc_output.vcd +uv run ../../mcu_soc/cvc/compare_outputs.py jacquard_output.vcd cvc_output.vcd ``` **Expected results**: - Functional output: Exact match (logic correctness) -- Arrival times: Loom ≥ CVC (conservative accumulation expected) +- Arrival times: Jacquard ≥ CVC (conservative accumulation expected) - No SDF parsing errors or malformed delays **Purpose**: Pre-layout tests catch timing issues early without P&R turnaround (30+ min). Library-only delays provide floor (lower bound); post-layout adds routing parasitics for final validation. @@ -174,9 +174,9 @@ uv run ../../mcu_soc/cvc/compare_outputs.py loom_output.vcd cvc_output.vcd The main CI pipeline (`.github/workflows/ci.yml`) includes: -1. **mcu-soc-metal job**: Generates Loom timing VCD +1. **mcu-soc-metal job**: Generates Jacquard timing VCD - Includes SDF stripping step (strip_sdf_checks.py) - - Produces loom_timed_mcu.vcd with arrival time annotations + - Produces jacquard_timed_mcu.vcd with arrival time annotations 2. **mcu-soc-cvc job**: Generates CVC reference output - Uses stripped SDF (6_final_nocheck.sdf) @@ -237,7 +237,7 @@ Post-layout designs include routing delays and P&R context: **Why**: Boomerang architecture evaluates in hierarchical stages. To know Q arrival, you sum delays from all stages. -**Mitigation**: Compare Loom Q arrival against CVC RESULT: total_delay (if available), or accept that arrival times differ but functional output matches. +**Mitigation**: Compare Jacquard Q arrival against CVC RESULT: total_delay (if available), or accept that arrival times differ but functional output matches. ### 2. SDF Parser Robustness @@ -274,7 +274,7 @@ Post-layout designs include routing delays and P&R context: - Compare first 5-10 cycles after reset - Verify reset logic is synchronized -4. **Compare against Loom non-timed version**: +4. **Compare against Jacquard non-timed version**: ```bash # Run without timing VCD cargo run -r --features metal --bin jacquard -- sim \ diff --git a/scripts/chipflow_harness/README.md b/scripts/chipflow_harness/README.md index 0ecf12e..3f36ad5 100644 --- a/scripts/chipflow_harness/README.md +++ b/scripts/chipflow_harness/README.md @@ -5,7 +5,7 @@ VCD stimulus generator for ChipFlow post-synthesis simulation using GEM. ## Overview This tool converts ChipFlow's `input.json` test format into VCD waveforms suitable -for gate-level simulation with Loom. +for gate-level simulation with Jacquard. ## Installation @@ -122,7 +122,7 @@ uv run --extra dev pytest tests/ -v │ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ -│ netlist.v │───►│ loom sim │───►│ events.json │ +│ netlist.v │───►│ jacquard sim│───►│ events.json │ │ │ │ / cosim │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ ``` diff --git a/scripts/compare_timing.py b/scripts/compare_timing.py index 08a22b1..7631d9a 100644 --- a/scripts/compare_timing.py +++ b/scripts/compare_timing.py @@ -2,27 +2,27 @@ # requires-python = ">=3.10" # dependencies = [] # /// -"""Compare timing results between CVC (event-driven) and Loom (GPU) simulators. +"""Compare timing results between CVC (event-driven) and Jacquard (GPU) simulators. -Parses CVC's RESULT: lines and Loom's timed VCD to compare signal arrival -times. The primary comparison is Loom's Q arrival (full path from CLK edge +Parses CVC's RESULT: lines and Jacquard's timed VCD to compare signal arrival +times. The primary comparison is Jacquard's Q arrival (full path from CLK edge through combo logic to output register Q) vs CVC's total_delay RESULT (CLK -> dff_out.D path measured by the CVC testbench). Timing model differences: - CVC VCD: Q transitions at CLK + dff_out_CLK_to_Q (~360ps) because CVC is - event-driven and models DFF capture/output separately. - Loom VCD: Q transitions at CLK + full_combo_path (~1323ps) because Loom - propagates arrival times through the entire combinational path. + CVC VCD: Q transitions at CLK + dff_out_CLK_to_Q (~360ps) because CVC is + event-driven and models DFF capture/output separately. + Jacquard VCD: Q transitions at CLK + full_combo_path (~1323ps) because Jacquard + propagates arrival times through the entire combinational path. -So the meaningful comparison is Loom Q arrival vs CVC total_delay, NOT -Loom Q arrival vs CVC Q arrival from VCD. +So the meaningful comparison is Jacquard Q arrival vs CVC total_delay, NOT +Jacquard Q arrival vs CVC Q arrival from VCD. Usage: uv run scripts/compare_timing.py \ --cvc-log cvc_output.log \ --cvc-vcd cvc_inv_chain_output.vcd \ - --loom-vcd loom_timed_output.vcd \ + --jacquard-vcd jacquard_timed_output.vcd \ --clock-period-ps 10000 \ --clock-signal CLK \ --output-signal Q @@ -302,10 +302,10 @@ def measure_arrivals_no_clock( @dataclass class MetricComparison: - """One comparison between a CVC reference value and Loom measured value.""" + """One comparison between a CVC reference value and Jacquard measured value.""" name: str cvc_ps: int - loom_ps: int + jacquard_ps: int diff_ps: int diff_pct: float status: str # PASS, WARN, FAIL @@ -319,9 +319,9 @@ def compute_status( ) -> str: """Determine PASS/WARN/FAIL status for a timing comparison.""" if diff_ps < 0 and abs(diff_pct) > max_optimistic_pct: - return "FAIL" # Loom is optimistic (underestimates delay) + return "FAIL" # Jacquard is optimistic (underestimates delay) if diff_pct > max_conservative_pct: - return "WARN" # Loom is too conservative + return "WARN" # Jacquard is too conservative return "PASS" @@ -329,13 +329,13 @@ def format_report( cvc_results: dict[str, int], metric_comparisons: list[MetricComparison], cvc_vcd_arrivals: list[tuple[int, int, str]], - loom_vcd_arrivals: list[tuple[int, int, str]], + jacquard_vcd_arrivals: list[tuple[int, int, str]], clock_signal: str, output_signal: str, ) -> str: """Format the comparison report.""" lines: list[str] = [] - lines.append("=== Timing Comparison: CVC vs Loom (inv_chain_pnr) ===") + lines.append("=== Timing Comparison: CVC vs Jacquard (inv_chain_pnr) ===") lines.append("") # CVC reference values @@ -349,16 +349,16 @@ def format_report( lines.append("") # Primary comparison: structural metrics - lines.append("Primary Comparison (Loom Q arrival vs CVC total_delay):") - lines.append(" Loom's timed VCD propagates the full combo path delay to Q,") - lines.append(" so Loom's Q arrival corresponds to CVC's total_delay metric.") + lines.append("Primary Comparison (Jacquard Q arrival vs CVC total_delay):") + lines.append(" Jacquard's timed VCD propagates the full combo path delay to Q,") + lines.append(" so Jacquard's Q arrival corresponds to CVC's total_delay metric.") lines.append("") if metric_comparisons: - lines.append(f" | {'Metric':>20} | {'CVC (ps)':>8} | {'Loom (ps)':>9} | {'Diff (ps)':>9} | {'Diff (%)':>8} | {'Status':>6} |") - lines.append(f" |{'-'*22}|{'-'*10}|{'-'*11}|{'-'*11}|{'-'*10}|{'-'*8}|") + lines.append(f" | {'Metric':>20} | {'CVC (ps)':>8} | {'Jacquard (ps)':>13} | {'Diff (ps)':>9} | {'Diff (%)':>8} | {'Status':>6} |") + lines.append(f" |{'-'*22}|{'-'*10}|{'-'*15}|{'-'*11}|{'-'*10}|{'-'*8}|") for mc in metric_comparisons: lines.append( - f" | {mc.name:>20} | {mc.cvc_ps:>8} | {mc.loom_ps:>9} " + f" | {mc.name:>20} | {mc.cvc_ps:>8} | {mc.jacquard_ps:>13} " f"| {mc.diff_ps:>+9d} | {mc.diff_pct:>+7.1f}% | {mc.status:>6} |" ) else: @@ -370,14 +370,14 @@ def format_report( if cvc_vcd_arrivals: # Deduplicate to show unique arrival values cvc_unique = sorted(set(a for _, a, _ in cvc_vcd_arrivals)) - lines.append(f" CVC (dff_out CLK->Q only): {cvc_unique} ps") + lines.append(f" CVC (dff_out CLK->Q only): {cvc_unique} ps") else: lines.append(" CVC: (no arrivals measured)") - if loom_vcd_arrivals: - loom_unique = sorted(set(a for _, a, _ in loom_vcd_arrivals)) - lines.append(f" Loom (full combo path): {loom_unique} ps") + if jacquard_vcd_arrivals: + jq_unique = sorted(set(a for _, a, _ in jacquard_vcd_arrivals)) + lines.append(f" Jacquard (full combo path): {jq_unique} ps") else: - lines.append(" Loom: (no arrivals measured)") + lines.append(" Jacquard: (no arrivals measured)") lines.append("") # Not yet comparable @@ -385,9 +385,9 @@ def format_report( clk_to_q = cvc_results.get("clk_to_q") chain = cvc_results.get("chain_delay") if clk_to_q is not None: - lines.append(f" clk_to_q (dff_in CLK->Q): CVC={clk_to_q}ps, Loom=N/A") + lines.append(f" clk_to_q (dff_in CLK->Q): CVC={clk_to_q}ps, Jacquard=N/A") if chain is not None: - lines.append(f" chain_delay (q1->c[15]): CVC={chain}ps, Loom=N/A") + lines.append(f" chain_delay (q1->c[15]): CVC={chain}ps, Jacquard=N/A") lines.append("") # Overall result @@ -415,13 +415,13 @@ def format_report( # --------------------------------------------------------------------------- def main() -> int: - parser = argparse.ArgumentParser(description="Compare CVC vs Loom timing results") + parser = argparse.ArgumentParser(description="Compare CVC vs Jacquard timing results") parser.add_argument("--cvc-log", type=Path, required=True, help="CVC stdout log with RESULT: lines") parser.add_argument("--cvc-vcd", type=Path, required=True, help="CVC output VCD") - parser.add_argument("--loom-vcd", type=Path, required=True, - help="Loom --timing-vcd output") + parser.add_argument("--jacquard-vcd", "--loom-vcd", type=Path, required=True, + help="Jacquard --timing-vcd output") parser.add_argument("--clock-period-ps", type=int, required=True, help="Clock period in picoseconds") parser.add_argument("--clock-signal", default="CLK", @@ -442,12 +442,12 @@ def main() -> int: # Parse VCDs cvc_vcd = parse_vcd(args.cvc_vcd) - loom_vcd = parse_vcd(args.loom_vcd) + jq_vcd = parse_vcd(args.jacquard_vcd) log.info("CVC VCD: %d signals, timescale=%.0f ps", len(cvc_vcd.signals), cvc_vcd.timescale_ps) - log.info("Loom VCD: %d signals, timescale=%.0f ps", - len(loom_vcd.signals), loom_vcd.timescale_ps) + log.info("Jacquard VCD: %d signals, timescale=%.0f ps", + len(jq_vcd.signals), jq_vcd.timescale_ps) # Measure arrivals from VCDs cvc_clock = find_signal(cvc_vcd, args.clock_signal) @@ -459,38 +459,38 @@ def main() -> int: cvc_arrivals = measure_arrivals_no_clock( cvc_vcd, args.output_signal, args.clock_period_ps) - loom_clock = find_signal(loom_vcd, args.clock_signal) - if loom_clock: - loom_arrivals = measure_arrivals( - loom_vcd, args.clock_signal, args.output_signal, args.clock_period_ps) + jq_clock = find_signal(jq_vcd, args.clock_signal) + if jq_clock: + jq_arrivals = measure_arrivals( + jq_vcd, args.clock_signal, args.output_signal, args.clock_period_ps) else: - log.info("Loom VCD has no clock signal; inferring edges from period") - loom_arrivals = measure_arrivals_no_clock( - loom_vcd, args.output_signal, args.clock_period_ps) + log.info("Jacquard VCD has no clock signal; inferring edges from period") + jq_arrivals = measure_arrivals_no_clock( + jq_vcd, args.output_signal, args.clock_period_ps) log.info("CVC VCD Q arrivals: %s", cvc_arrivals) - log.info("Loom VCD Q arrivals: %s", loom_arrivals) + log.info("Jacquard VCD Q arrivals: %s", jq_arrivals) - # Primary comparison: Loom's steady-state Q arrival vs CVC total_delay - # Loom's Q arrival includes the full combo path, matching CVC's total_delay. + # Primary comparison: Jacquard's steady-state Q arrival vs CVC total_delay + # Jacquard's Q arrival includes the full combo path, matching CVC's total_delay. metric_comparisons: list[MetricComparison] = [] - # Get Loom's steady-state arrival (skip cycle 0 which may be initial state) - loom_steady = [a for c, a, _ in loom_arrivals if c > 0] - if not loom_steady: - loom_steady = [a for _, a, _ in loom_arrivals] + # Get Jacquard's steady-state arrival (skip cycle 0 which may be initial state) + jq_steady = [a for c, a, _ in jq_arrivals if c > 0] + if not jq_steady: + jq_steady = [a for _, a, _ in jq_arrivals] - if loom_steady and "total_delay" in cvc_results: - # Use the most common (modal) Loom arrival as the representative value - loom_representative = max(set(loom_steady), key=loom_steady.count) + if jq_steady and "total_delay" in cvc_results: + # Use the most common (modal) Jacquard arrival as the representative value + jq_representative = max(set(jq_steady), key=jq_steady.count) cvc_total = cvc_results["total_delay"] - diff_ps = loom_representative - cvc_total + diff_ps = jq_representative - cvc_total diff_pct = (diff_ps / cvc_total * 100) if cvc_total > 0 else 0.0 metric_comparisons.append(MetricComparison( name="Q arrival (full path)", cvc_ps=cvc_total, - loom_ps=loom_representative, + jacquard_ps=jq_representative, diff_ps=diff_ps, diff_pct=diff_pct, status=compute_status(diff_ps, diff_pct, @@ -499,7 +499,7 @@ def main() -> int: # Report report = format_report( - cvc_results, metric_comparisons, cvc_arrivals, loom_arrivals, + cvc_results, metric_comparisons, cvc_arrivals, jq_arrivals, args.clock_signal, args.output_signal) print(report) @@ -507,9 +507,9 @@ def main() -> int: if args.output_json: json_data = { "cvc_results": cvc_results, - "loom_vcd_arrivals": [ + "jacquard_vcd_arrivals": [ {"cycle": c, "arrival_ps": a, "value": v} - for c, a, v in loom_arrivals + for c, a, v in jq_arrivals ], "cvc_vcd_arrivals": [ {"cycle": c, "arrival_ps": a, "value": v} @@ -519,7 +519,7 @@ def main() -> int: { "name": mc.name, "cvc_ps": mc.cvc_ps, - "loom_ps": mc.loom_ps, + "jacquard_ps": mc.jacquard_ps, "diff_ps": mc.diff_ps, "diff_pct": mc.diff_pct, "status": mc.status, diff --git a/tests/mcu_soc/cvc/compare_simulation.py b/tests/mcu_soc/cvc/compare_simulation.py index f33687a..b8c8736 100644 --- a/tests/mcu_soc/cvc/compare_simulation.py +++ b/tests/mcu_soc/cvc/compare_simulation.py @@ -2,14 +2,14 @@ # requires-python = ">=3.10" # dependencies = [] # /// -"""Compare Loom and CVC simulation outputs for MCU SoC validation. +"""Compare Jacquard and CVC simulation outputs for MCU SoC validation. Functional comparison: Reads both VCDs, extracts gpio_out signals at each clock edge, and reports differences. Handles format differences: - - Loom: individual 1-bit signals with multi-char VCD codes (e.g., %-) + - Jacquard: individual 1-bit signals with multi-char VCD codes (e.g., %-) - CVC: 44-bit bus gpio_out[43:0] with potential X values -Timing comparison (optional): When --loom-timing-vcd is provided, compares +Timing comparison (optional): When --jacquard-timing-vcd is provided, compares sub-cycle arrival times between Jacquard and CVC, reporting statistics and identifying timing-critical transitions near clock edges. @@ -18,8 +18,8 @@ back to gpio_out[N] indices. Usage: - python3 compare_simulation.py [--skip-cycles N] [--config ] [--skip-bits 0-5] - python3 compare_simulation.py --loom-timing-vcd [...] + python3 compare_simulation.py [--skip-cycles N] [--config ] [--skip-bits 0-5] + python3 compare_simulation.py --jacquard-timing-vcd [...] """ import json @@ -53,14 +53,14 @@ def build_output_port_mapping(config_path: Path) -> dict[str, int]: return mapping -def parse_loom_vcd( +def parse_jacquard_vcd( path: Path, width: int = 44, output_port_map: dict[str, int] | None = None, ) -> VCDResult: - """Parse Loom VCD and return gpio_out value changes + last timestamp. + """Parse Jacquard VCD and return gpio_out value changes + last timestamp. - Loom VCD has individual 1-bit signals. In traditional mode: + Jacquard VCD has individual 1-bit signals. In traditional mode: $var wire 1 %- gpio_out[1] $end In port-mapped mode (Jacquard internal names): $var wire 1 %- io$soc_gpio_0_gpio$o [0] $end @@ -184,13 +184,13 @@ class BitTransition: arrival_ps: int # offset from preceding rising clock edge -def parse_loom_timing_transitions( +def parse_jacquard_timing_transitions( path: Path, clock_period: int, width: int = 44, output_port_map: dict[str, int] | None = None, ) -> list[BitTransition]: - """Parse Loom timing VCD into per-bit transitions with arrival offsets.""" + """Parse Jacquard timing VCD into per-bit transitions with arrival offsets.""" code_to_bit: dict[str, int] = {} in_header = True transitions: list[BitTransition] = [] @@ -316,14 +316,14 @@ def parse_cvc_timing_transitions( def run_timing_comparison( - loom_transitions: list[BitTransition], + jacquard_transitions: list[BitTransition], cvc_transitions: list[BitTransition], clock_period: int, skip_cycles: int, num_cycles: int, skip_bits: set[int], ) -> None: - """Compare timing between Loom and CVC transitions, print report.""" + """Compare timing between Jacquard and CVC transitions, print report.""" def group_by_cycle_bit( transitions: list[BitTransition], @@ -340,20 +340,20 @@ def group_by_cycle_bit( result[key] = t.arrival_ps return result - loom_grouped = group_by_cycle_bit(loom_transitions) + jq_grouped = group_by_cycle_bit(jacquard_transitions) cvc_grouped = group_by_cycle_bit(cvc_transitions) - common_keys = set(loom_grouped.keys()) & set(cvc_grouped.keys()) - loom_only = set(loom_grouped.keys()) - set(cvc_grouped.keys()) - cvc_only = set(cvc_grouped.keys()) - set(loom_grouped.keys()) + common_keys = set(jq_grouped.keys()) & set(cvc_grouped.keys()) + jq_only = set(jq_grouped.keys()) - set(cvc_grouped.keys()) + cvc_only = set(cvc_grouped.keys()) - set(jq_grouped.keys()) print(f"\n{'='*60}") print("Timing Comparison Report") print(f"{'='*60}") - print(f" Loom transitions (filtered): {len(loom_grouped)}") - print(f" CVC transitions (filtered): {len(cvc_grouped)}") - print(f" Common (cycle,bit) pairs: {len(common_keys)}") - print(f" Loom-only transitions: {len(loom_only)}") + print(f" Jacquard transitions (filtered): {len(jq_grouped)}") + print(f" CVC transitions (filtered): {len(cvc_grouped)}") + print(f" Common (cycle,bit) pairs: {len(common_keys)}") + print(f" Jacquard-only transitions: {len(jq_only)}") print(f" CVC-only transitions: {len(cvc_only)}") if not common_keys: @@ -361,18 +361,18 @@ def group_by_cycle_bit( print(f"{'='*60}") return - # Compute differences: (cycle, bit, cvc_arrival, loom_arrival, diff) + # Compute differences: (cycle, bit, cvc_arrival, jq_arrival, diff) diffs: list[tuple[int, int, int, int, int]] = [] for key in sorted(common_keys): cycle, bit = key cvc_arr = cvc_grouped[key] - loom_arr = loom_grouped[key] - diff = loom_arr - cvc_arr - diffs.append((cycle, bit, cvc_arr, loom_arr, diff)) + jq_arr = jq_grouped[key] + diff = jq_arr - cvc_arr + diffs.append((cycle, bit, cvc_arr, jq_arr, diff)) abs_diffs = [abs(d[4]) for d in diffs] - print(f"\n Arrival Time Differences (Loom - CVC):") + print(f"\n Arrival Time Differences (Jacquard - CVC):") print(f" Mean: {mean(abs_diffs):,.0f} ps") print(f" Median: {median(abs_diffs):,.0f} ps") print(f" Max: {max(abs_diffs):,.0f} ps") @@ -402,32 +402,32 @@ def group_by_cycle_bit( # Top discrepancies diffs_sorted = sorted(diffs, key=lambda d: abs(d[4]), reverse=True) print(f"\n Top 10 Largest Discrepancies:") - print(f" {'Cycle':>7} {'Bit':>4} {'CVC(ps)':>10} {'Loom(ps)':>10} {'Diff(ps)':>10} {'%clk':>6}") - for cycle, bit, cvc_arr, loom_arr, diff in diffs_sorted[:10]: + print(f" {'Cycle':>7} {'Bit':>4} {'CVC(ps)':>10} {'Jqrd(ps)':>10} {'Diff(ps)':>10} {'%clk':>6}") + for cycle, bit, cvc_arr, jq_arr, diff in diffs_sorted[:10]: pct = 100.0 * abs(diff) / clock_period - print(f" {cycle:>7} {bit:>4} {cvc_arr:>10,} {loom_arr:>10,} {diff:>+10,} {pct:>5.1f}%") + print(f" {cycle:>7} {bit:>4} {cvc_arr:>10,} {jq_arr:>10,} {diff:>+10,} {pct:>5.1f}%") # Timing-critical analysis near_edge_threshold = 0.8 * clock_period timing_critical: list[tuple[int, int, int, int, str]] = [] - for cycle, bit, cvc_arr, loom_arr, diff in diffs: + for cycle, bit, cvc_arr, jq_arr, diff in diffs: cvc_near = cvc_arr > near_edge_threshold - loom_near = loom_arr > near_edge_threshold - if cvc_near != loom_near: - if loom_near and not cvc_near: - reason = "Loom late (near next edge), CVC safe" + jq_near = jq_arr > near_edge_threshold + if cvc_near != jq_near: + if jq_near and not cvc_near: + reason = "Jacquard late (near next edge), CVC safe" else: - reason = "CVC late (near next edge), Loom safe" - timing_critical.append((cycle, bit, cvc_arr, loom_arr, reason)) + reason = "CVC late (near next edge), Jacquard safe" + timing_critical.append((cycle, bit, cvc_arr, jq_arr, reason)) # Check for transitions captured in different cycles edge_crossings: list[tuple[int, int, int, int]] = [] - for cycle, bit, cvc_arr, loom_arr, diff in diffs: + for cycle, bit, cvc_arr, jq_arr, diff in diffs: cvc_same = cvc_arr < clock_period - loom_same = loom_arr < clock_period - if cvc_same != loom_same: - edge_crossings.append((cycle, bit, cvc_arr, loom_arr)) + jq_same = jq_arr < clock_period + if cvc_same != jq_same: + edge_crossings.append((cycle, bit, cvc_arr, jq_arr)) print(f"\n Timing-Critical Analysis:") print(f" Near-edge threshold: {near_edge_threshold:,.0f} ps " @@ -436,9 +436,9 @@ def group_by_cycle_bit( f"{len(timing_critical)}") if timing_critical: - print(f"\n {'Cycle':>7} {'Bit':>4} {'CVC(ps)':>10} {'Loom(ps)':>10} Issue") - for cycle, bit, cvc_arr, loom_arr, reason in timing_critical[:20]: - print(f" {cycle:>7} {bit:>4} {cvc_arr:>10,} {loom_arr:>10,} " + print(f"\n {'Cycle':>7} {'Bit':>4} {'CVC(ps)':>10} {'Jqrd(ps)':>10} Issue") + for cycle, bit, cvc_arr, jq_arr, reason in timing_critical[:20]: + print(f" {cycle:>7} {bit:>4} {cvc_arr:>10,} {jq_arr:>10,} " f"{reason}") if len(timing_critical) > 20: print(f" ... ({len(timing_critical) - 20} more)") @@ -446,9 +446,9 @@ def group_by_cycle_bit( if edge_crossings: print(f"\n Clock edge crossings (different cycle capture): " f"{len(edge_crossings)}") - print(f" {'Cycle':>7} {'Bit':>4} {'CVC(ps)':>10} {'Loom(ps)':>10}") - for cycle, bit, cvc_arr, loom_arr in edge_crossings[:10]: - print(f" {cycle:>7} {bit:>4} {cvc_arr:>10,} {loom_arr:>10,}") + print(f" {'Cycle':>7} {'Bit':>4} {'CVC(ps)':>10} {'Jqrd(ps)':>10}") + for cycle, bit, cvc_arr, jq_arr in edge_crossings[:10]: + print(f" {cycle:>7} {bit:>4} {cvc_arr:>10,} {jq_arr:>10,}") if len(edge_crossings) > 10: print(f" ... ({len(edge_crossings) - 10} more)") else: @@ -465,7 +465,7 @@ def main() -> None: config_path: Path | None = None num_cycles_override: int | None = None skip_bits: set[int] = set() - loom_timing_vcd: Path | None = None + jacquard_timing_vcd: Path | None = None cvc_timing_vcd: Path | None = None positional: list[str] = [] @@ -489,8 +489,8 @@ def main() -> None: else: skip_bits.add(int(part)) i += 2 - elif args[i] == "--loom-timing-vcd" and i + 1 < len(args): - loom_timing_vcd = Path(args[i + 1]) + elif args[i] in ("--jacquard-timing-vcd", "--loom-timing-vcd") and i + 1 < len(args): + jacquard_timing_vcd = Path(args[i + 1]) i += 2 elif args[i] == "--cvc-timing-vcd" and i + 1 < len(args): cvc_timing_vcd = Path(args[i + 1]) @@ -501,13 +501,13 @@ def main() -> None: if len(positional) < 2: print( - f"Usage: {sys.argv[0]} [--skip-cycles N] " + f"Usage: {sys.argv[0]} [--skip-cycles N] " f"[--config ] [--num-cycles N] [--skip-bits 0-5]", file=sys.stderr, ) sys.exit(1) - loom_path = Path(positional[0]) + jacquard_path = Path(positional[0]) cvc_path = Path(positional[1]) output_port_map: dict[str, int] | None = None @@ -517,10 +517,10 @@ def main() -> None: clock_period = 40000 # ps - print(f"Parsing Loom VCD: {loom_path}") - loom_result = parse_loom_vcd(loom_path, output_port_map=output_port_map) - loom_changes = loom_result.changes - print(f" {len(loom_changes)} gpio_out value changes, last_time={loom_result.last_time}ps") + print(f"Parsing Jacquard VCD: {jacquard_path}") + jq_result = parse_jacquard_vcd(jacquard_path, output_port_map=output_port_map) + jq_changes = jq_result.changes + print(f" {len(jq_changes)} gpio_out value changes, last_time={jq_result.last_time}ps") print(f"Parsing CVC VCD: {cvc_path}") cvc_result = parse_cvc_vcd(cvc_path) @@ -534,7 +534,7 @@ def main() -> None: print(f" Using explicit cycle count: {num_cycles}") else: # Use the minimum of both last timestamps as the comparison range - max_time = min(loom_result.last_time, cvc_result.last_time) + max_time = min(jq_result.last_time, cvc_result.last_time) num_cycles = max_time // clock_period + 1 # Build per-cycle values by interpolating from change lists @@ -553,7 +553,7 @@ def build_cycle_values( values[cycle] = current_val return values - loom_values = build_cycle_values(loom_changes, num_cycles) + jq_values = build_cycle_values(jq_changes, num_cycles) cvc_values = build_cycle_values(cvc_changes, num_cycles) # Build comparison mask (exclude skip_bits) @@ -569,7 +569,7 @@ def build_cycle_values( first_mismatch = None for cycle in range(skip_cycles, num_cycles): - lv = loom_values[cycle] & compare_mask + lv = jq_values[cycle] & compare_mask cv = cvc_values[cycle] & compare_mask if lv == cv: matches += 1 @@ -580,7 +580,7 @@ def build_cycle_values( diff_bits = [i for i in range(44) if diff & (1 << i) and i not in skip_bits] t = cycle * clock_period print(f"\n MISMATCH at cycle {cycle} (t={t}ps):") - print(f" Loom: 0x{lv:011x}") + print(f" Jacquard: 0x{lv:011x}") print(f" CVC: 0x{cv:011x}") print(f" Diff bits: {diff_bits}") if first_mismatch is None: @@ -603,13 +603,13 @@ def build_cycle_values( print(f"{'='*60}") # --- Timing comparison (optional, informational only) --- - if loom_timing_vcd: + if jacquard_timing_vcd: # Default CVC timing VCD to the same functional CVC VCD cvc_timing_path = cvc_timing_vcd if cvc_timing_vcd else cvc_path - print(f"\nParsing Loom timing VCD: {loom_timing_vcd}") - loom_timing = parse_loom_timing_transitions( - loom_timing_vcd, clock_period, output_port_map=output_port_map, + print(f"\nParsing Jacquard timing VCD: {jacquard_timing_vcd}") + jq_timing = parse_jacquard_timing_transitions( + jacquard_timing_vcd, clock_period, output_port_map=output_port_map, ) print(f"Parsing CVC timing VCD: {cvc_timing_path}") @@ -618,7 +618,7 @@ def build_cycle_values( ) run_timing_comparison( - loom_timing, cvc_timing, clock_period, + jq_timing, cvc_timing, clock_period, skip_cycles, num_cycles, skip_bits, ) diff --git a/tests/mcu_soc/cvc/convert_stimulus.py b/tests/mcu_soc/cvc/convert_stimulus.py index 470de2e..6880dff 100644 --- a/tests/mcu_soc/cvc/convert_stimulus.py +++ b/tests/mcu_soc/cvc/convert_stimulus.py @@ -2,9 +2,9 @@ # requires-python = ">=3.10" # dependencies = [] # /// -"""Convert a Loom stimulus VCD to Verilog timed assignments for CVC. +"""Convert a Jacquard stimulus VCD to Verilog timed assignments for CVC. -Reads the stimulus VCD (generated by `loom cosim --stimulus-vcd`) and produces +Reads the stimulus VCD (generated by `jacquard cosim --stimulus-vcd`) and produces a Verilog include file with delay-based `initial begin ... end` blocks that drive the DUT ports. @@ -168,7 +168,7 @@ def generate_verilog( scalar_ports.add(port_name) with open(output_path, 'w') as f: - f.write("// Auto-generated stimulus from Loom cosim VCD\n") + f.write("// Auto-generated stimulus from Jacquard cosim VCD\n") f.write(f"// Source: stimulus.vcd\n") f.write(f"// Signals: {len(id_to_name)}, Events: {len(events)}\n") f.write(f"// Ports: {sorted(port_widths.keys())} + {sorted(scalar_ports)}\n\n") diff --git a/tests/mcu_soc/cvc/gen_cell_models.py b/tests/mcu_soc/cvc/gen_cell_models.py index c2c7667..f38b50a 100644 --- a/tests/mcu_soc/cvc/gen_cell_models.py +++ b/tests/mcu_soc/cvc/gen_cell_models.py @@ -210,7 +210,7 @@ def read_udp(udp_dir_name: str) -> str | None: udp_text = match.group(1) - # Initialize DFF UDPs to 0 (matching Loom's 0-initialization). + # Initialize DFF UDPs to 0 (matching Jacquard's 0-initialization). # Without this, CVC starts all DFF outputs at X and X-propagation # prevents the design from functioning during comparison. udp_text = re.sub( diff --git a/tests/mcu_soc/cvc/run_cvc.sh b/tests/mcu_soc/cvc/run_cvc.sh index 177c12b..043569d 100644 --- a/tests/mcu_soc/cvc/run_cvc.sh +++ b/tests/mcu_soc/cvc/run_cvc.sh @@ -6,7 +6,7 @@ # # Prerequisites: # 1. Generate stimulus VCD: -# cargo run -r --features metal --bin loom -- cosim \ +# cargo run -r --features metal --bin jacquard -- cosim \ # tests/mcu_soc/data/6_final.v \ # --config tests/mcu_soc/sim_config_sky130.json \ # --top-module openframe_project_wrapper \ @@ -32,7 +32,7 @@ REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" DATA_DIR="$REPO_ROOT/tests/mcu_soc/data" CVC_DIR="$SCRIPT_DIR" OUTPUT_DIR="$CVC_DIR/output" -IMAGE_NAME="loom-cvc" +IMAGE_NAME="jacquard-cvc" mkdir -p "$OUTPUT_DIR" diff --git a/tests/mcu_soc/cvc/stimulus_gen.v b/tests/mcu_soc/cvc/stimulus_gen.v index ccf335e..81ec7d3 100644 --- a/tests/mcu_soc/cvc/stimulus_gen.v +++ b/tests/mcu_soc/cvc/stimulus_gen.v @@ -1,4 +1,4 @@ -// Auto-generated stimulus from Loom cosim VCD +// Auto-generated stimulus from Jacquard cosim VCD // Source: stimulus.vcd // Signals: 301, Events: 2001 // Ports: ['gpio_in', 'gpio_in_h', 'gpio_loopback_one', 'gpio_loopback_zero', 'mask_rev'] + ['por_l', 'porb_h', 'porb_l', 'resetb_h', 'resetb_l'] diff --git a/tests/mcu_soc/cvc/stimulus_gen_new.v b/tests/mcu_soc/cvc/stimulus_gen_new.v index 8ac9c8f..cb3abf1 100644 --- a/tests/mcu_soc/cvc/stimulus_gen_new.v +++ b/tests/mcu_soc/cvc/stimulus_gen_new.v @@ -1,4 +1,4 @@ -// Auto-generated stimulus from Loom cosim VCD +// Auto-generated stimulus from Jacquard cosim VCD // Source: stimulus.vcd // Signals: 19, Events: 20001 // Ports: ['gpio_in'] + [] diff --git a/tests/mcu_soc/cvc/strip_sdf_checks.py b/tests/mcu_soc/cvc/strip_sdf_checks.py index 41fd389..fcf4b2c 100644 --- a/tests/mcu_soc/cvc/strip_sdf_checks.py +++ b/tests/mcu_soc/cvc/strip_sdf_checks.py @@ -6,7 +6,7 @@ CVC requires matching specify-block timing checks for every SDF TIMINGCHECK entry, and has trouble with escaped port names in INTERCONNECT entries. -For initial Loom vs CVC waveform comparison, IOPATH delays suffice. +For initial Jacquard vs CVC waveform comparison, IOPATH delays suffice. Strips: - TIMINGCHECK blocks (no matching specify checks) diff --git a/tests/mcu_soc/cvc/tb_cvc.v b/tests/mcu_soc/cvc/tb_cvc.v index e73b180..3b0dcdb 100644 --- a/tests/mcu_soc/cvc/tb_cvc.v +++ b/tests/mcu_soc/cvc/tb_cvc.v @@ -1,17 +1,17 @@ // CVC SDF-annotated testbench for MCU SoC timing validation. // -// Replays stimulus captured from Loom cosim and compares against CVC's +// Replays stimulus captured from Jacquard cosim and compares against CVC's // event-driven SDF simulation as a reference. // // Setup: -// 1. Generate stimulus: loom cosim ... --stimulus-vcd stimulus.vcd +// 1. Generate stimulus: jacquard cosim ... --stimulus-vcd stimulus.vcd // 2. Convert: uv run convert_stimulus.py stimulus.vcd stimulus_gen.v // 3. Generate cell models: uv run gen_cell_models.py // 4. Run CVC: // cvc64 +typdelays tb_cvc.v sky130_cells.v 6_final.v && ./cvcsim // // Outputs: -// cvc_output.vcd — GPIO output waveforms for comparison with Loom +// cvc_output.vcd — GPIO output waveforms for comparison with Jacquard `timescale 1ps/1ps @@ -107,7 +107,7 @@ module tb_cvc; mask_rev = 32'h0; end - // ---- Stimulus (generated from Loom cosim VCD) ---- + // ---- Stimulus (generated from Jacquard cosim VCD) ---- `include "stimulus_gen.v" endmodule diff --git a/tests/timing_test/cvc/Dockerfile b/tests/timing_test/cvc/Dockerfile index a2f674a..5cc8146 100644 --- a/tests/timing_test/cvc/Dockerfile +++ b/tests/timing_test/cvc/Dockerfile @@ -1,5 +1,5 @@ # CVC (open-src-cvc) Verilog simulator for SDF timing validation. -# Build: docker build --platform linux/amd64 -t loom-cvc tests/timing_test/cvc +# Build: docker build --platform linux/amd64 -t jacquard-cvc tests/timing_test/cvc # # CVC compiles Verilog to native machine code, so the runtime image # needs gcc and binutils in addition to the cvc64 binary. diff --git a/tests/timing_test/cvc/run_cvc.sh b/tests/timing_test/cvc/run_cvc.sh index c1a040a..6700c56 100644 --- a/tests/timing_test/cvc/run_cvc.sh +++ b/tests/timing_test/cvc/run_cvc.sh @@ -6,7 +6,7 @@ # # Builds the CVC Docker image (cached after first run), then runs the # inv_chain testbench with SDF back-annotation. Compares the reported -# total delay against Loom's expected 1323ps. +# total delay against Jacquard's expected 1323ps. # # Outputs: # tests/timing_test/cvc/output/cvc_output.log (stdout from CVC sim) @@ -18,7 +18,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" INV_CHAIN_DIR="$REPO_ROOT/tests/timing_test/inv_chain_pnr" OUTPUT_DIR="$SCRIPT_DIR/output" -IMAGE_NAME="loom-cvc" +IMAGE_NAME="jacquard-cvc" mkdir -p "$OUTPUT_DIR" @@ -60,17 +60,17 @@ if grep -q "RESULT: total_delay=" "$OUTPUT_DIR/cvc_output.log"; then CVC_CHAIN=$(grep "RESULT: chain_delay=" "$OUTPUT_DIR/cvc_output.log" | sed 's/.*=//') LOOM_TOTAL=1323 echo "CVC: clk_to_q=${CVC_CLK_TO_Q}ps chain=${CVC_CHAIN}ps total=${CVC_TOTAL}ps" - echo "Loom: clk_to_q=350ps chain=973ps total=${LOOM_TOTAL}ps" + echo "Jacquard: clk_to_q=350ps chain=973ps total=${LOOM_TOTAL}ps" echo "" - # Loom uses max(rise, fall) per cell — a conservative approximation since + # Jacquard uses max(rise, fall) per cell — a conservative approximation since # the GPU kernel processes 32 packed signals and can't track per-signal # transition direction. CVC tracks actual rise/fall transitions. # Expected overestimate: 8 inverters × 10ps IOPATH + 8 wires × 1ps = 88ps. DIFF=$((LOOM_TOTAL - CVC_TOTAL)) - echo "Difference: ${DIFF}ps (Loom conservative overestimate)" + echo "Difference: ${DIFF}ps (Jacquard conservative overestimate)" if [ "$DIFF" -ge 0 ] && [ "$DIFF" -le 200 ]; then - echo "PASS: Loom within expected conservative bound" + echo "PASS: Jacquard within expected conservative bound" else echo "FAIL: Unexpected difference (expected 0-200ps overestimate)" exit 1 diff --git a/tests/timing_test/inv_chain_pnr/inv_chain_stimulus.vcd b/tests/timing_test/inv_chain_pnr/inv_chain_stimulus.vcd index b26c561..c3eab95 100644 --- a/tests/timing_test/inv_chain_pnr/inv_chain_stimulus.vcd +++ b/tests/timing_test/inv_chain_pnr/inv_chain_stimulus.vcd @@ -2,7 +2,7 @@ $date Fri Feb 28 00:00:00 2026 $end $version - Loom test stimulus + Jacquard test stimulus $end $timescale 1ps diff --git a/tests/timing_test/inv_chain_pnr/tb_cvc.v b/tests/timing_test/inv_chain_pnr/tb_cvc.v index e37ae5d..aa01faa 100644 --- a/tests/timing_test/inv_chain_pnr/tb_cvc.v +++ b/tests/timing_test/inv_chain_pnr/tb_cvc.v @@ -83,7 +83,7 @@ module tb_cvc; forever #5000 CLK = ~CLK; end - // Stimulus: matches the pattern used by inv_chain_stimulus.vcd for Loom + // Stimulus: matches the pattern used by inv_chain_stimulus.vcd for Jacquard // Cycle 0: D=0 latched // Cycle 1: D=1 latched (set D=1 shortly after cycle 0 clock edge) // Cycle 2: D=0 latched (set D=0 shortly after cycle 1 clock edge) diff --git a/tests/timing_test/multi_depth/multi_depth_stimulus.vcd b/tests/timing_test/multi_depth/multi_depth_stimulus.vcd index c7cf75b..ebcf500 100644 --- a/tests/timing_test/multi_depth/multi_depth_stimulus.vcd +++ b/tests/timing_test/multi_depth/multi_depth_stimulus.vcd @@ -2,7 +2,7 @@ $date Thu Feb 27 00:00:00 2026 $end $version - Loom test stimulus + Jacquard test stimulus $end $timescale 1ps diff --git a/tests/timing_test/multi_depth/run_cvc_multi_depth.sh b/tests/timing_test/multi_depth/run_cvc_multi_depth.sh index bd776e3..fac8edf 100644 --- a/tests/timing_test/multi_depth/run_cvc_multi_depth.sh +++ b/tests/timing_test/multi_depth/run_cvc_multi_depth.sh @@ -6,7 +6,7 @@ # # Builds the CVC Docker image (cached after first run), then runs the # multi_depth testbench with SDF back-annotation. Reports per-group -# arrival times for comparison against Loom's timing simulation. +# arrival times for comparison against Jacquard's timing simulation. # # Outputs: # tests/timing_test/multi_depth/cvc_output.log (stdout from CVC sim) @@ -18,7 +18,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" MULTI_DEPTH_DIR="$SCRIPT_DIR" CVC_DIR="$REPO_ROOT/tests/timing_test/cvc" -IMAGE_NAME="loom-cvc" +IMAGE_NAME="jacquard-cvc" # Build the CVC image if not present (reuses same Dockerfile as inv_chain) if ! docker image inspect "$IMAGE_NAME" > /dev/null 2>&1; then diff --git a/tests/timing_test/multi_depth/tb_cvc.v b/tests/timing_test/multi_depth/tb_cvc.v index e5fe0e5..ccf2910 100644 --- a/tests/timing_test/multi_depth/tb_cvc.v +++ b/tests/timing_test/multi_depth/tb_cvc.v @@ -66,7 +66,7 @@ module tb_cvc; .out(out) ); - // VCD output for comparison with Loom + // VCD output for comparison with Jacquard initial begin $dumpfile("cvc_multi_depth_output.vcd"); $dumpvars(0, uut); diff --git a/tests/timing_test/sky130_timing/Makefile b/tests/timing_test/sky130_timing/Makefile index 13d12c5..3c2e690 100644 --- a/tests/timing_test/sky130_timing/Makefile +++ b/tests/timing_test/sky130_timing/Makefile @@ -5,7 +5,7 @@ all: inv_chain.v.gv logic_cone.v.gv inv_chain.sdf logic_cone.sdf -# Convert Verilog to AIG graph format for loom +# Convert Verilog to AIG graph format for Jacquard %.v.gv: %.v @echo "Converting $< to AIG..." cargo run -r --bin jacquard -- map $< > $@ 2>&1 || { \ diff --git a/tests/timing_test/sky130_timing/README.md b/tests/timing_test/sky130_timing/README.md index a88efb8..3bb4b7e 100644 --- a/tests/timing_test/sky130_timing/README.md +++ b/tests/timing_test/sky130_timing/README.md @@ -61,7 +61,7 @@ only combinational path delays and setup/hold times from library timing models. ### Run with CVC ```sh -# Run with CVC (requires open-src-cvc Docker image: loom-cvc) +# Run with CVC (requires open-src-cvc Docker image: jacquard-cvc) cvc64 +typdelays tb_inv_chain.v inv_chain.v ./cvcsim @@ -69,13 +69,13 @@ cvc64 +typdelays tb_logic_cone.v logic_cone.v ./cvcsim ``` -### Compare Loom vs CVC +### Compare Jacquard vs CVC -Use the comparison script in the parent directory to validate that Loom's +Use the comparison script in the parent directory to validate that Jacquard's GPU timing simulation matches CVC's reference timing: ```sh -bash ../inv_chain_pnr/../compare_timing.py cvc_output.vcd loom_output.vcd +bash ../inv_chain_pnr/../compare_timing.py cvc_output.vcd jacquard_output.vcd ``` ## Files diff --git a/tests/timing_test/sky130_timing/gen_liberty_sdf.py b/tests/timing_test/sky130_timing/gen_liberty_sdf.py index 7c93834..4475763 100644 --- a/tests/timing_test/sky130_timing/gen_liberty_sdf.py +++ b/tests/timing_test/sky130_timing/gen_liberty_sdf.py @@ -75,7 +75,7 @@ def gen_sdf_header(design_name): return f"""(SDFVERSION "3.0") (DESIGN "{design_name}") (DATE "{design_name} pre-layout Liberty-only SDF") -(VENDOR "Loom") +(VENDOR "Jacquard") (PROGRAM "gen_liberty_sdf.py") (VERSION "1.0") (HIERARCHY "{design_name}") diff --git a/tests/timing_test/sky130_timing/inv_chain.sdf b/tests/timing_test/sky130_timing/inv_chain.sdf index 847e414..a54bb70 100644 --- a/tests/timing_test/sky130_timing/inv_chain.sdf +++ b/tests/timing_test/sky130_timing/inv_chain.sdf @@ -1,7 +1,7 @@ (SDFVERSION "3.0") (DESIGN "inv_chain") (DATE "inv_chain pre-layout Liberty-only SDF") -(VENDOR "Loom") +(VENDOR "Jacquard") (PROGRAM "gen_liberty_sdf.py") (VERSION "1.0") (HIERARCHY "inv_chain") diff --git a/tests/timing_test/sky130_timing/logic_cone.sdf b/tests/timing_test/sky130_timing/logic_cone.sdf index a2e6477..5fff0f0 100644 --- a/tests/timing_test/sky130_timing/logic_cone.sdf +++ b/tests/timing_test/sky130_timing/logic_cone.sdf @@ -1,7 +1,7 @@ (SDFVERSION "3.0") (DESIGN "logic_cone") (DATE "logic_cone pre-layout Liberty-only SDF") -(VENDOR "Loom") +(VENDOR "Jacquard") (PROGRAM "gen_liberty_sdf.py") (VERSION "1.0") (HIERARCHY "logic_cone")