✓
Passing This code compiles and runs correctly.
Code
// TEST: self|fpga width semantics — a `clamp(lo,hi)` term in the |fpga
// meet claims the boundary saturates, so the emitter generates saturating
// logic (wide map, then held inside [lo,hi]) and the generated bench notes
// "saturated" where the host-wide map diverges from the port.
//
// Bounds judge, clamp normalizes — refine's own vocabulary is the ruling:
// bare `>=0 & <=255` would size the port and wrap; `clamp` asks the fabric
// to hold the range. value=200 *2 saturates to 255 on fabric while the
// host (unbounded i64) still computes 400 — the divergence is the point.
//
// Pinned shape: `k.<field> <op>= <literal>` on an int shape whose |fpga
// facet carries clamp(0,255); the sim must pass (saturation is the
// circuit's contract, the note documents the host gap).
import std/proto
import std/refine
import std/kernel
import std/io
std/proto(Sample) {
value: i64
}
std/refine(Sample)|fpga {
value: i64 & clamp(0,255)
}
std/kernel:shape(Sample) {
value: i64,
}
std/kernel:init(Sample) {
{ value: 200 },
{ value: 60 },
}
| kernel k |> std/kernel:self|fpga { k.value *= 2 }
| computed c |> std/io:print.blk {
v[0]={{ c[0].value:d }} v[1]={{ c[1].value:d }}
}
Supporting Files
// Generated by std/kernel:self|fpga — one kernel self op, one pipeline
// stage. Host lowering is the ordinary Zig loop; this artifact is gated
// by iverilog + the generated testbench + yosys check, all run by the build.
module koru_fpga_kernel_init_4195181959_data_self_0 (
input logic clk,
input logic rst_n,
input logic in_valid,
input logic [7:0] in_value,
output logic out_valid,
output logic [7:0] out_value
);
logic [7:0] mapped_value;
logic signed [63:0] wide_value;
assign wide_value = $signed({1'b0, in_value}) * 64'sd2;
assign mapped_value = (wide_value > 64'sd255) ? 8'd255 : (wide_value < 64'sd0) ? 8'd0 : wide_value[7:0];
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
out_valid <= 1'b0;
out_value <= 8'd0;
end else begin
out_valid <= in_valid;
out_value <= mapped_value;
end
end
endmodule
// Generated testbench for koru_fpga_kernel_init_4195181959_data_self_0 — drives the init dataset on
// consecutive beats, checks the stage's output one beat later.
// errors exit nonzero via $fatal so the BUILD fails on a wrong circuit.
module tb;
logic clk = 0;
logic rst_n = 0;
logic in_valid = 0;
logic [7:0] in_value = 0;
logic out_valid;
logic [7:0] out_value;
logic [7:0] exp_value;
logic signed [63:0] expw_value;
koru_fpga_kernel_init_4195181959_data_self_0 dut (.*);
always #5 clk = ~clk;
int errors = 0;
task check;
if (!out_valid || out_value !== exp_value) begin
$display("FAIL: got valid=%b value=%0d, want value=%0d", out_valid, out_value, exp_value);
errors = errors + 1;
end else begin
$display("ok: value=%0d", out_value);
if (expw_value != out_value) $display("note: value saturated %0d -> %0d (8-bit port)", expw_value, out_value);
end
endtask
initial begin
@(negedge clk); rst_n = 1;
// beat 1: drive element 0
@(negedge clk); in_valid = 1; in_value = 8'd200;
expw_value = $signed({1'b0, in_value}) * 64'sd2; exp_value = (expw_value > 64'sd255) ? 8'd255 : (expw_value < 64'sd0) ? 8'd0 : expw_value[7:0];
// beat 2: drive element 1
@(negedge clk); check(); in_valid = 1; in_value = 8'd60;
expw_value = $signed({1'b0, in_value}) * 64'sd2; exp_value = (expw_value > 64'sd255) ? 8'd255 : (expw_value < 64'sd0) ? 8'd0 : expw_value[7:0];
// drain: last check, then drop valid
@(negedge clk); check(); in_valid = 0;
if (errors == 0) $display("PASS: koru_fpga_kernel_init_4195181959_data_self_0 pipeline");
else $fatal(1, "FAIL: %0d errors", errors);
$finish;
end
endmodule
Actual
v[0]=400 v[1]=120
Expected output
v[0]=400 v[1]=120
Flows
flow ~std/proto click a branch to expand · @labels scroll to their anchor
std/proto (Sample, source: value: i64)
flow ~std/refine click a branch to expand · @labels scroll to their anchor
std/refine|fpga (Sample, source: value: i64 & clamp(0,255))
flow ~shape click a branch to expand · @labels scroll to their anchor
shape (expr: Sample, source: value: i64,)
flow ~init click a branch to expand · @labels scroll to their anchor
init (expr: Sample, source: { value: 200 },
{ value: 60 },)
Test Configuration
MUST_RUN