Improve timing reports and register poly mul inputs
This commit is contained in:
82
run_tb.sh
82
run_tb.sh
@@ -120,6 +120,84 @@ execute_tcl() {
|
|||||||
# each <spec> = "snapshot:K:CASE". Launches all specs in parallel, waits,
|
# each <spec> = "snapshot:K:CASE". Launches all specs in parallel, waits,
|
||||||
# then prints an ordered summary and returns nonzero if any job failed.
|
# then prints an ordered summary and returns nonzero if any job failed.
|
||||||
PAR_BASE="${TMPDIR:-/tmp}/run_tb_par_$$"
|
PAR_BASE="${TMPDIR:-/tmp}/run_tb_par_$$"
|
||||||
|
|
||||||
|
print_timing_summary() {
|
||||||
|
local logs=("$@")
|
||||||
|
local found=0 log
|
||||||
|
|
||||||
|
for log in "${logs[@]}"; do
|
||||||
|
if [ -f "$log" ] && grep -q '^TIME ' "$log"; then
|
||||||
|
found=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
[ "$found" -eq 0 ] && return 0
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Timing summary (clk=20MHz, period=50ns)"
|
||||||
|
printf " %-7s %-3s %-5s %10s %12s %12s %s\n" "OP" "K" "CASE" "cycles" "time_us" "time_ms" "log"
|
||||||
|
for log in "${logs[@]}"; do
|
||||||
|
[ -f "$log" ] || continue
|
||||||
|
awk -v logfile="$log" '
|
||||||
|
/^TIME / {
|
||||||
|
k = ""; c = ""; op = ""; cycles = ""; runtime = "";
|
||||||
|
for (i = 1; i <= NF; i++) {
|
||||||
|
split($i, a, "=");
|
||||||
|
if (a[1] == "K") k = a[2];
|
||||||
|
else if (a[1] == "CASE") c = a[2];
|
||||||
|
else if (a[1] == "OP") op = a[2];
|
||||||
|
else if (a[1] == "cycles") cycles = a[2];
|
||||||
|
else if (a[1] == "runtime") runtime = a[2];
|
||||||
|
}
|
||||||
|
if (runtime != "") {
|
||||||
|
printf " %-7s %-3s %-5s %10d %12.3f %12.3f %s\n",
|
||||||
|
op, k, c, cycles, runtime / 1000.0, runtime / 1000000.0, logfile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$log"
|
||||||
|
done
|
||||||
|
|
||||||
|
local found_state=0
|
||||||
|
for log in "${logs[@]}"; do
|
||||||
|
if [ -f "$log" ] && grep -q '^ STATE ' "$log"; then
|
||||||
|
found_state=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
[ "$found_state" -eq 0 ] && return 0
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "State timing breakdown (clk=20MHz, period=50ns)"
|
||||||
|
printf " %-7s %-3s %-5s %-12s %10s %12s\n" "OP" "K" "CASE" "STATE" "cycles" "time_us"
|
||||||
|
for log in "${logs[@]}"; do
|
||||||
|
[ -f "$log" ] || continue
|
||||||
|
awk '
|
||||||
|
/^TIME_BREAKDOWN / {
|
||||||
|
k = ""; c = ""; op = "";
|
||||||
|
for (i = 1; i <= NF; i++) {
|
||||||
|
split($i, a, "=");
|
||||||
|
if (a[1] == "K") k = a[2];
|
||||||
|
else if (a[1] == "CASE") c = a[2];
|
||||||
|
else if (a[1] == "OP") op = a[2];
|
||||||
|
}
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
/^ STATE / {
|
||||||
|
state = $2;
|
||||||
|
cycles = "";
|
||||||
|
time_ns = "";
|
||||||
|
for (i = 1; i <= NF; i++) {
|
||||||
|
split($i, a, "=");
|
||||||
|
if (a[1] == "cycles") cycles = a[2];
|
||||||
|
else if (a[1] == "time_ns") time_ns = a[2];
|
||||||
|
}
|
||||||
|
if (time_ns != "") {
|
||||||
|
printf " %-7s %-3s %-5s %-12s %10d %12.3f\n",
|
||||||
|
op, k, c, state, cycles, time_ns / 1000.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$log"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
run_xsim_jobs() {
|
run_xsim_jobs() {
|
||||||
local mtag="$1" pgrep="$2" pmatch="$3"; shift 3
|
local mtag="$1" pgrep="$2" pmatch="$3"; shift 3
|
||||||
local specs=("$@")
|
local specs=("$@")
|
||||||
@@ -146,12 +224,13 @@ run_xsim_jobs() {
|
|||||||
wait
|
wait
|
||||||
|
|
||||||
# ordered summary + per-job log copy to /tmp/run_tb_<mtag>_k*_c*.log
|
# ordered summary + per-job log copy to /tmp/run_tb_<mtag>_k*_c*.log
|
||||||
local fail=0 pf nf log
|
local fail=0 pf nf log timing_logs=()
|
||||||
for s in "${specs[@]}"; do
|
for s in "${specs[@]}"; do
|
||||||
IFS=: read -r snap k c <<< "$s"
|
IFS=: read -r snap k c <<< "$s"
|
||||||
wd="$PAR_BASE/${mtag}_k${k}_c${c}"
|
wd="$PAR_BASE/${mtag}_k${k}_c${c}"
|
||||||
log="/tmp/run_tb_${mtag}_k${k}_c${c}.log"
|
log="/tmp/run_tb_${mtag}_k${k}_c${c}.log"
|
||||||
cp -f "$wd/run.out" "$log" 2>/dev/null
|
cp -f "$wd/run.out" "$log" 2>/dev/null
|
||||||
|
timing_logs+=("$log")
|
||||||
pf=$(grep -oE "$pgrep" "$log" | tail -1)
|
pf=$(grep -oE "$pgrep" "$log" | tail -1)
|
||||||
nf=$(grep -c 'cannot be opened' "$log")
|
nf=$(grep -c 'cannot be opened' "$log")
|
||||||
echo " K=$k CASE=$c -> ${pf:-NORESULT} (file-not-found=$nf, log: $log)"
|
echo " K=$k CASE=$c -> ${pf:-NORESULT} (file-not-found=$nf, log: $log)"
|
||||||
@@ -162,6 +241,7 @@ run_xsim_jobs() {
|
|||||||
{ [ "$pf" = "$pmatch" ] && [ "$nf" -eq 0 ]; } || fail=1
|
{ [ "$pf" = "$pmatch" ] && [ "$nf" -eq 0 ]; } || fail=1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
print_timing_summary "${timing_logs[@]}"
|
||||||
rm -rf "$PAR_BASE"
|
rm -rf "$PAR_BASE"
|
||||||
return $fail
|
return $fail
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,11 @@ module poly_mul_sync (
|
|||||||
reg [7:0] load_cnt; // 0..256 for loading 256 pairs
|
reg [7:0] load_cnt; // 0..256 for loading 256 pairs
|
||||||
reg [6:0] comp_k; // 0..127, current base-case index
|
reg [6:0] comp_k; // 0..127, current base-case index
|
||||||
|
|
||||||
// Registered basecase_mul results
|
// Registered basecase_mul inputs/results
|
||||||
|
reg [11:0] bc_a0_reg, bc_a1_reg;
|
||||||
|
reg [11:0] bc_b0_reg, bc_b1_reg;
|
||||||
|
reg [11:0] bc_zeta_reg;
|
||||||
|
reg bc_valid_reg;
|
||||||
reg [11:0] c0_reg, c1_reg;
|
reg [11:0] c0_reg, c1_reg;
|
||||||
|
|
||||||
// Combinational read signals for COMP_CALC
|
// Combinational read signals for COMP_CALC
|
||||||
@@ -73,19 +77,19 @@ module poly_mul_sync (
|
|||||||
.zeta (zeta)
|
.zeta (zeta)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Pipelined basecase multiply. One request is issued at a time; the
|
// Pipelined basecase multiply. One request is issued at a time; inputs are
|
||||||
// output interface is unchanged for top-level consumers.
|
// registered locally so comp_k does not directly drive the DSP input muxes.
|
||||||
wire [11:0] bc_c0, bc_c1;
|
wire [11:0] bc_c0, bc_c1;
|
||||||
wire bc_vo;
|
wire bc_vo;
|
||||||
basecase_mul_pipe u_bc (
|
basecase_mul_pipe u_bc (
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
.rst_n(rst_n),
|
.rst_n(rst_n),
|
||||||
.valid_i(state == S_COMP_ISSUE),
|
.valid_i(bc_valid_reg),
|
||||||
.a0 (mem_a0),
|
.a0 (bc_a0_reg),
|
||||||
.a1 (mem_a1),
|
.a1 (bc_a1_reg),
|
||||||
.b0 (mem_b0),
|
.b0 (bc_b0_reg),
|
||||||
.b1 (mem_b1),
|
.b1 (bc_b1_reg),
|
||||||
.zeta(zeta),
|
.zeta(bc_zeta_reg),
|
||||||
.c0 (bc_c0),
|
.c0 (bc_c0),
|
||||||
.c1 (bc_c1),
|
.c1 (bc_c1),
|
||||||
.valid_o(bc_vo)
|
.valid_o(bc_vo)
|
||||||
@@ -122,6 +126,12 @@ module poly_mul_sync (
|
|||||||
state <= S_IDLE;
|
state <= S_IDLE;
|
||||||
load_cnt <= 8'd0;
|
load_cnt <= 8'd0;
|
||||||
comp_k <= 7'd0;
|
comp_k <= 7'd0;
|
||||||
|
bc_a0_reg <= 12'd0;
|
||||||
|
bc_a1_reg <= 12'd0;
|
||||||
|
bc_b0_reg <= 12'd0;
|
||||||
|
bc_b1_reg <= 12'd0;
|
||||||
|
bc_zeta_reg <= 12'd0;
|
||||||
|
bc_valid_reg <= 1'b0;
|
||||||
c0_reg <= 12'd0;
|
c0_reg <= 12'd0;
|
||||||
c1_reg <= 12'd0;
|
c1_reg <= 12'd0;
|
||||||
for (i = 0; i < 256; i = i + 1) begin
|
for (i = 0; i < 256; i = i + 1) begin
|
||||||
@@ -130,6 +140,7 @@ module poly_mul_sync (
|
|||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
state <= next_state;
|
state <= next_state;
|
||||||
|
bc_valid_reg <= 1'b0;
|
||||||
|
|
||||||
// ---- LOAD phase ----
|
// ---- LOAD phase ----
|
||||||
// First coefficient captured on IDLE → LOAD transition
|
// First coefficient captured on IDLE → LOAD transition
|
||||||
@@ -147,6 +158,18 @@ module poly_mul_sync (
|
|||||||
end
|
end
|
||||||
|
|
||||||
// ---- COMPUTE phase ----
|
// ---- COMPUTE phase ----
|
||||||
|
// COMP_ISSUE: cut the comp_k -> memory mux -> basecase DSP path.
|
||||||
|
// bc_valid_reg pulses on the following cycle, while these regs hold
|
||||||
|
// stable inputs through the basecase pipeline launch.
|
||||||
|
if (state == S_COMP_ISSUE) begin
|
||||||
|
bc_a0_reg <= mem_a0;
|
||||||
|
bc_a1_reg <= mem_a1;
|
||||||
|
bc_b0_reg <= mem_b0;
|
||||||
|
bc_b1_reg <= mem_b1;
|
||||||
|
bc_zeta_reg <= zeta;
|
||||||
|
bc_valid_reg <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
// COMP_WAIT: capture pipelined basecase_mul results when ready.
|
// COMP_WAIT: capture pipelined basecase_mul results when ready.
|
||||||
if (state == S_COMP_WAIT && bc_vo) begin
|
if (state == S_COMP_WAIT && bc_vo) begin
|
||||||
c0_reg <= bc_c0;
|
c0_reg <= bc_c0;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ module tb_mlkem_dec_katK_xsim;
|
|||||||
localparam EKB = 384*KP + 32; // ek_pke bytes within dk
|
localparam EKB = 384*KP + 32; // ek_pke bytes within dk
|
||||||
localparam DKPB = 384*KP; // dk_pke bytes
|
localparam DKPB = 384*KP; // dk_pke bytes
|
||||||
localparam CTB = (KP==4) ? 1568 : (32*(10*KP+4)); // ct bytes: 768/1088/1568
|
localparam CTB = (KP==4) ? 1568 : (32*(10*KP+4)); // ct bytes: 768/1088/1568
|
||||||
localparam integer CLK_PERIOD_NS = 100; // 10 MHz
|
localparam integer CLK_PERIOD_NS = 50; // 20 MHz
|
||||||
localparam integer CLK_HALF_NS = CLK_PERIOD_NS / 2;
|
localparam integer CLK_HALF_NS = CLK_PERIOD_NS / 2;
|
||||||
|
|
||||||
reg clk=0, rst_n=0, start_i=0;
|
reg clk=0, rst_n=0, start_i=0;
|
||||||
@@ -112,7 +112,7 @@ module tb_mlkem_dec_katK_xsim;
|
|||||||
integer runtime_ns;
|
integer runtime_ns;
|
||||||
begin
|
begin
|
||||||
runtime_ns = cycles * CLK_PERIOD_NS;
|
runtime_ns = cycles * CLK_PERIOD_NS;
|
||||||
$display("TIME K=%0d CASE=%0d OP=%0s cycles=%0d clk=10MHz period=%0dns runtime=%0d ns (%0d.%03d us, %0d.%03d ms)",
|
$display("TIME K=%0d CASE=%0d OP=%0s cycles=%0d clk=20MHz period=%0dns runtime=%0d ns (%0d.%03d us, %0d.%03d ms)",
|
||||||
KP, casenum, op_name, cycles, CLK_PERIOD_NS, runtime_ns,
|
KP, casenum, op_name, cycles, CLK_PERIOD_NS, runtime_ns,
|
||||||
runtime_ns/1000, runtime_ns%1000,
|
runtime_ns/1000, runtime_ns%1000,
|
||||||
runtime_ns/1000000, (runtime_ns%1000000)/1000);
|
runtime_ns/1000000, (runtime_ns%1000000)/1000);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ module tb_mlkem_enc_katK_xsim;
|
|||||||
localparam CTB = (KP==4) ? 1568 : (32*(10*KP+4)); // ct bytes: K2 768,K3 1088,K4 1568
|
localparam CTB = (KP==4) ? 1568 : (32*(10*KP+4)); // ct bytes: K2 768,K3 1088,K4 1568
|
||||||
localparam DU = (KP==4) ? 11 : 10; // compression du
|
localparam DU = (KP==4) ? 11 : 10; // compression du
|
||||||
localparam C1B = 32*DU*KP; // c1 byte count: K2 640,K3 960,K4 1408
|
localparam C1B = 32*DU*KP; // c1 byte count: K2 640,K3 960,K4 1408
|
||||||
localparam integer CLK_PERIOD_NS = 100; // 10 MHz
|
localparam integer CLK_PERIOD_NS = 50; // 20 MHz
|
||||||
localparam integer CLK_HALF_NS = CLK_PERIOD_NS / 2;
|
localparam integer CLK_HALF_NS = CLK_PERIOD_NS / 2;
|
||||||
|
|
||||||
reg clk=0, rst_n=0, start_i=0;
|
reg clk=0, rst_n=0, start_i=0;
|
||||||
@@ -105,7 +105,7 @@ module tb_mlkem_enc_katK_xsim;
|
|||||||
integer runtime_ns;
|
integer runtime_ns;
|
||||||
begin
|
begin
|
||||||
runtime_ns = cycles * CLK_PERIOD_NS;
|
runtime_ns = cycles * CLK_PERIOD_NS;
|
||||||
$display("TIME K=%0d CASE=%0d OP=%0s cycles=%0d clk=10MHz period=%0dns runtime=%0d ns (%0d.%03d us, %0d.%03d ms)",
|
$display("TIME K=%0d CASE=%0d OP=%0s cycles=%0d clk=20MHz period=%0dns runtime=%0d ns (%0d.%03d us, %0d.%03d ms)",
|
||||||
KP, casenum, op_name, cycles, CLK_PERIOD_NS, runtime_ns,
|
KP, casenum, op_name, cycles, CLK_PERIOD_NS, runtime_ns,
|
||||||
runtime_ns/1000, runtime_ns%1000,
|
runtime_ns/1000, runtime_ns%1000,
|
||||||
runtime_ns/1000000, (runtime_ns%1000000)/1000);
|
runtime_ns/1000000, (runtime_ns%1000000)/1000);
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ module tb_mlkem_hello_world_xsim;
|
|||||||
.dbg_mprime_o(dbg_mprime_o), .dbg_kbar_o(dbg_kbar_o),
|
.dbg_mprime_o(dbg_mprime_o), .dbg_kbar_o(dbg_kbar_o),
|
||||||
.dbg_decz_o(dbg_decz_o), .dbg_dech_o(dbg_dech_o)
|
.dbg_decz_o(dbg_decz_o), .dbg_dech_o(dbg_dech_o)
|
||||||
);
|
);
|
||||||
always #5 clk = ~clk;
|
always #25 clk = ~clk; // 20 MHz
|
||||||
|
|
||||||
// storage shuttled between operations (the "wire" between Alice and Bob)
|
// storage shuttled between operations (the "wire" between Alice and Bob)
|
||||||
reg [7:0] ek_b [0:EKB-1];
|
reg [7:0] ek_b [0:EKB-1];
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ module tb_mlkem_kg_katK_xsim;
|
|||||||
parameter KP = 2;
|
parameter KP = 2;
|
||||||
localparam EKB = 384*KP + 32;
|
localparam EKB = 384*KP + 32;
|
||||||
localparam DKB = 768*KP + 96;
|
localparam DKB = 768*KP + 96;
|
||||||
localparam integer CLK_PERIOD_NS = 100; // 10 MHz
|
localparam integer CLK_PERIOD_NS = 50; // 20 MHz
|
||||||
localparam integer CLK_HALF_NS = CLK_PERIOD_NS / 2;
|
localparam integer CLK_HALF_NS = CLK_PERIOD_NS / 2;
|
||||||
|
|
||||||
reg clk=0, rst_n=0, start_i=0;
|
reg clk=0, rst_n=0, start_i=0;
|
||||||
@@ -99,7 +99,7 @@ module tb_mlkem_kg_katK_xsim;
|
|||||||
integer runtime_ns;
|
integer runtime_ns;
|
||||||
begin
|
begin
|
||||||
runtime_ns = cycles * CLK_PERIOD_NS;
|
runtime_ns = cycles * CLK_PERIOD_NS;
|
||||||
$display("TIME K=%0d CASE=%0d OP=%0s cycles=%0d clk=10MHz period=%0dns runtime=%0d ns (%0d.%03d us, %0d.%03d ms)",
|
$display("TIME K=%0d CASE=%0d OP=%0s cycles=%0d clk=20MHz period=%0dns runtime=%0d ns (%0d.%03d us, %0d.%03d ms)",
|
||||||
KP, casenum, op_name, cycles, CLK_PERIOD_NS, runtime_ns,
|
KP, casenum, op_name, cycles, CLK_PERIOD_NS, runtime_ns,
|
||||||
runtime_ns/1000, runtime_ns%1000,
|
runtime_ns/1000, runtime_ns%1000,
|
||||||
runtime_ns/1000000, (runtime_ns%1000000)/1000);
|
runtime_ns/1000000, (runtime_ns%1000000)/1000);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ module tb_mlkem_two_inst_xsim;
|
|||||||
localparam MLEN = 11; // "hello world"
|
localparam MLEN = 11; // "hello world"
|
||||||
|
|
||||||
reg clk=0;
|
reg clk=0;
|
||||||
always #5 clk = ~clk;
|
always #25 clk = ~clk; // 20 MHz
|
||||||
|
|
||||||
// ---------------- Instance A: KeyGen + Encaps ----------------
|
// ---------------- Instance A: KeyGen + Encaps ----------------
|
||||||
reg a_rst_n=0, a_start=0;
|
reg a_rst_n=0, a_start=0;
|
||||||
|
|||||||
Reference in New Issue
Block a user