Validation guide - which script reproduces which paper number
=============================================================
From Windows PowerShell, cd into the top folder (the one with RUN_ME.ps1) and run:
    powershell -ExecutionPolicy Bypass -File .\RUN_ME.ps1                    (quick verify)
    powershell -ExecutionPolicy Bypass -File .\RUN_ME.ps1 -Full             (+ software/analysis)
    powershell -ExecutionPolicy Bypass -File .\RUN_ME.ps1 -Full -WithVivado (+ hardware, Vivado 2019.1)
All result files go to reproduce_output\.
If the package path contains spaces, the Vivado work folders (ablation_work, saif_work)
are created in a space-free folder, normally %TEMP% (Vivado HLS rejects spaces).

All hardware numbers in the paper come from ONE scripted flow: Vivado HLS 2019.1
C-synthesis at 5.0 ns, then out-of-context synth/opt/place/phys_opt/route at 5.5 ns on
xa7z010clg225-1I (scripts\run_ablation.ps1, scripts\run_saif_power.ps1), and dynamic power
from SAIF of a zero-delay functional simulation at full streaming rate
(scripts\run_saif_power_v2.ps1). 03_Reports holds the reports of that flow.

Reference model (sanity)
  RUN_ME.ps1 step [1]. Expect:
    zero-key V3 = 0FFB6755 600B2072 66DB7A7D EBDB4A2E
    testbench first word = F74AA527

Table 1 - hardware resources / timing / power (full design = V3)
  Read from 03_Reports (RUN_ME step [2]):
    V3_utilization_routed.rpt       934 LUT, 1071 FF, 0 DSP, 0 BRAM
    V3_timing_summary_routed.rpt    WNS 0.068 ns, WHS 0.132 ns
    V3_power_saif.rpt               dynamic 0.029 W, static 0.090 W, total 0.119 W
    V3_power_saif_timing_sensitivity.rpt   dynamic 0.042 W (glitch sensitivity check)
  Rebuild from source (step [5], needs Vivado).

Table 2 - NIST SP 800-22
  scripts\parse_stat_logs.ps1 -> reproduce_output\stat_tables\nist_subtests.csv
  Expect 188 sub-tests, 0 failures.
  Lowest observed proportions 490/500 and 318/323; the passing thresholds
  (alpha=0.01) are 489/500 and 315/323, so every sub-test passes.

Table 3 - Dieharder
  scripts\parse_stat_logs.ps1 -> dieharder_all_runs.csv
  Three runs of 114 tests, 0 FAILED; WEAK tests pass on re-run.

Table 4 - TestU01 data volumes
  scripts\count_testu01_volume.ps1 -> testu01_volume_results.txt
  SmallCrush 15 / Crush 144 / BigCrush 160 statistics, all PASS.

Table 5 / Figs 3-5 - NPCR, UACI, entropy, autocorrelation (warm-up 0)
  scripts\run_npcr_uaci_v3.ps1 -> reproduce_output\npcr_uaci_results\
  Figures: scripts\make_figures.ps1 (needs numpy + matplotlib)
  Expect NPCR 99.998474%, UACI 33.242817%, entropy ~7.9994 bits/byte.

Ablation table (V0..V3) - resources and timing (needs Vivado)
  scripts\run_ablation.ps1 -> ablation_results.txt   (reference: 03_Reports\ablation\)
  LUT  V0 685 / V1 853 / V2 794 / V3 934
  FF   V0 847 / V1 975 / V2 943 / V3 1071
  WNS  V0 0.190 / V1 0.292 / V2 0.173 / V3 0.068 ns
  (run_ablation.ps1 also prints a vectorless power estimate; it is not used in the paper.)

Ablation table (V0..V3) - dynamic power (needs Vivado)
  scripts\run_saif_power.ps1, then scripts\run_saif_power_v2.ps1 -IncludeTimingSim
  -> reproduce_output\saif_power_results_v2.txt   (reference: 03_Reports\saif_power_results_v2.txt)
  Zero-delay functional SAIF, TREADY 100 %, 20,000 words, 3 key sets (identical),
  output bit-exact vs RTL, 100 % nets matched:
    dynamic power        V0 28 / V1 40 / V2 37 / V3 29 mW
    of which clock       V0 18 / V1 24 / V2 22 / V3 10 mW
    of which logic+sig.  V0 10 / V1 17 / V2 15 / V3 20 mW
    pJ/bit (dynamic)     V0 4.81 / V1 6.88 / V2 6.36 / V3 4.98
  SDF timing simulation, glitch sensitivity check only (the xsim gate-level model gives
  some wrong output words; their count is printed, up to ~6 %):
    dynamic power        V0 31 / V1 48 / V2 45 / V3 42 mW
    pJ/bit (dynamic)     V0 5.33 / V1 8.25 / V2 7.73 / V3 7.22

Ablation table note - why the clock component differs (needs Vivado)
  scripts\check_clock_spread.tcl -> reproduce_output\clock_spread.txt
  (reference: 03_Reports\clock_spread.txt; RUN_ME -WithVivado runs it)
  ap_clk routing nodes = 0 and clock buffer cells = 0 for every variant: in the
  out-of-context flow the clock net is ideal (unrouted, unbuffered), so its power is a
  placement-dependent estimate. Flip-flops: V0 847 in 1 clock region, V1 975 in 2,
  V2 943 in 2, V3 1071 in 1; the clock estimate does not follow the flip-flop count.

Comparison table - this work
  Mbps/LUT: 5818 / 685 = 8.49 (xoshiro only), 5818 / 934 = 6.23 (full design)
  pJ/bit:   4.81 and 4.98 (zero-delay); 5.33 and 7.22 with glitch activity (timing sim)

Section 4 - state recovery + keyless distinguisher
  scripts\run_structural_attack.ps1 -> structural_attack_results.txt
  scripts\xoshiro_state_recovery.py -> reproduce_output\attack_result.txt
  Plain xoshiro recovered from 4 outputs; full design needs a 64-bit key guess.
  Plain xoshiro linear complexity = 128 (80/80 streams flagged); full design
  LC ~300 (0/80 flagged). Best attack on the full design ~2^63 (2^61.3 for ~91% of keys).
  Section G (per layer): V1 (+Weyl) needs 2^32 guesses of w0, V2 (+Tent) 2^31 guesses of t0
  (2^29.3 for ~91% of keys), each less than two days on one core (measured 27-40 us per
  guess, depending on the machine and its load);
  V1 and V2 LC ~300, 0/80 flagged. Only V3 needs a joint 64-bit guess.
  The time per guess depends on the machine; the guess counts and LC flags do not.

Section 4 - Tent map (affine / degree 1, cycles, period)
  scripts\run_algebraic_degree.ps1 -> algebraic_degree_results.txt
  scripts\run_analysis.ps1 -> analysis_results.txt
  Tent step affine (0 triple violations); 12 Tent cycles; image size 2^31.
  State-sequence period: V0 = 2^128-1, V1 = 2^160, V3 up to 2^185.4 (~97% of seeds).

Seeds
  The exact seeding scheme and the per-battery seeds are listed in
  04_Validation_Data\SEEDS.txt (NIST, Dieharder x3, TestU01, NPCR/UACI).

Other files
  02_Source_Code\tb_prng32_axis_mod.vhd is the AXI4-Stream testbench used only for the
  handshake waveform figure (TVALID/TREADY/TLAST); it is not used for any number.
  03_Reports\prng32_axis_cosim.rpt is the HLS C/RTL co-simulation report (PASS).

Note: the three statistical batteries (NIST, Dieharder, TestU01) are NOT re-run
(they take many CPU-hours); their original logs are in 04_Validation_Data and are
summarized by parse_stat_logs.ps1. To re-run them, pipe the generator built from
02_Source_Code into the standard NIST / Dieharder / TestU01 tools.
