logicaffeine_compile/codegen_sva/
computedram_rtl.rs1pub fn emit_computedram_model_verilog() -> String {
20 r#"// computedram_model — behavioral ComputeDRAM device: RowClone (2-ACT) + triple-row MAJORITY (3-ACT)
21// + AMBIT bulk NOT (op 5, dual-contact cells): mem[bank] := ~mem[row]. NOT completes the boolean
22// basis {copy, AND, OR, NOT} so XOR / set-difference / popcount kernels run on this engine.
23module computedram_model #(parameter AW=8, DW=64) (
24 input clk, input rst,
25 input issue, input [2:0] op, input [4:0] bank, input [31:0] row,
26 input pre_we, input [AW-1:0] pre_addr, input [DW-1:0] pre_data,
27 input [AW-1:0] rd_addr, output [DW-1:0] rd_out
28);
29 (* ram_style = "registers" *) reg [DW-1:0] mem [0:(1<<AW)-1];
30 reg [AW-1:0] r0_i, r1_i;
31 reg [DW-1:0] snap0, snap1;
32 reg cad_open, pre_int; reg [1:0] ncad;
33 assign rd_out = mem[rd_addr];
34 function [DW-1:0] maj3(input [DW-1:0] a, input [DW-1:0] b, input [DW-1:0] c);
35 maj3 = (a & b) | (a & c) | (b & c);
36 endfunction
37 always @(posedge clk) begin
38 if (pre_we) mem[pre_addr] <= pre_data; // operand placement (works during reset too)
39 if (rst) begin
40 cad_open <= 1'b0; pre_int <= 1'b0; ncad <= 2'd0; r0_i <= 0; r1_i <= 0; snap0 <= 0; snap1 <= 0;
41 end else if (issue) begin
42 case (op)
43 3'd0: begin // ACT
44 if (cad_open && pre_int && ncad == 2'd1) begin
45 // 2nd activation: tentative RowClone (dst := src), snapshot the originals
46 r1_i <= row[AW-1:0]; snap1 <= mem[row[AW-1:0]];
47 mem[row[AW-1:0]] <= snap0;
48 ncad <= 2'd2; pre_int <= 1'b0;
49 end else if (cad_open && pre_int && ncad == 2'd2) begin
50 // 3rd activation: triple-row majority over the ORIGINAL snapshots → all three rows
51 mem[r0_i] <= maj3(snap0, snap1, mem[row[AW-1:0]]);
52 mem[r1_i] <= maj3(snap0, snap1, mem[row[AW-1:0]]);
53 mem[row[AW-1:0]] <= maj3(snap0, snap1, mem[row[AW-1:0]]);
54 ncad <= 2'd3; pre_int <= 1'b0;
55 end else begin
56 // fresh activation: start a new cadence
57 r0_i <= row[AW-1:0]; snap0 <= mem[row[AW-1:0]]; ncad <= 2'd1; cad_open <= 1'b1; pre_int <= 1'b0;
58 end
59 end
60 3'd3: if (cad_open) pre_int <= 1'b1; // interrupted precharge
61 3'd1, 3'd2: begin cad_open <= 1'b0; pre_int <= 1'b0; ncad <= 2'd0; end // RD/WR closes the cadence
62 3'd5: mem[bank[AW-1:0]] <= ~mem[row[AW-1:0]]; // Ambit bulk NOT: dst(bank) := ~src(row)
63 default: ;
64 endcase
65 end
66 end
67endmodule
68"#
69 .to_string()
70}
71
72pub fn emit_computedram_harness_testbench(
76 nwords: usize,
77 src: usize,
78 dst: usize,
79 pattern: u64,
80) -> String {
81 let last = nwords.saturating_sub(1);
82 let runcycles = nwords * 8 + 40;
83 format!(
84 r#"`timescale 1ns/1ps
85module tb_computedram;
86 reg clk=0; always #5 clk=~clk;
87 reg rst=1;
88 reg [63:0] rom [0:{last}];
89 integer idx=0;
90 wire [63:0] cmd_word = rom[idx];
91 wire cmd_valid = (idx <= {last});
92 wire cmd_ack, issue; wire [2:0] op; wire [4:0] bank; wire [31:0] row;
93 dram_executor exec(.clk(clk), .rst(rst), .cmd_word(cmd_word), .cmd_valid(cmd_valid),
94 .cmd_ack(cmd_ack), .issue(issue), .op(op), .bank(bank), .row(row));
95 reg pre_we; reg [7:0] pre_addr; reg [63:0] pre_data; reg [7:0] rd_addr; wire [63:0] rd_out;
96 computedram_model #(.AW(8), .DW(64)) dut(.clk(clk), .rst(rst), .issue(issue), .op(op), .bank(bank),
97 .row(row), .pre_we(pre_we), .pre_addr(pre_addr), .pre_data(pre_data), .rd_addr(rd_addr), .rd_out(rd_out));
98 integer errors;
99 always @(posedge clk) if (!rst && cmd_ack) idx <= idx + 1;
100 initial begin
101 errors=0; pre_we=0; pre_addr=0; pre_data=0; rd_addr=0;
102 $readmemh("cdram_plan.hex", rom);
103 @(posedge clk); pre_we=1; pre_addr=8'd{src}; pre_data=64'h{pattern:016x}; @(posedge clk); pre_we=0;
104 @(posedge clk); rst=0;
105 repeat ({runcycles}) @(posedge clk);
106 rd_addr=8'd{dst}; @(posedge clk); @(posedge clk);
107 if (rd_out !== 64'h{pattern:016x}) begin
108 errors=errors+1; $display("FAIL: RowClone dst(%0d)=%h exp=%h", {dst}, rd_out, 64'h{pattern:016x});
109 end
110 if (errors==0)
111 $display("PASS: ComputeDRAM RowClone ran as raw sub-JEDEC commands through the executor; dst == src (== the RowStore/VM oracle)");
112 $finish;
113 end
114endmodule
115"#
116 )
117}
118
119#[allow(clippy::too_many_arguments)]
124pub fn emit_computedram_reduce_testbench(
125 nwords: usize,
126 a: usize,
127 b: usize,
128 zero: usize,
129 a2: usize,
130 b2: usize,
131 ones: usize,
132 aval: u64,
133 bval: u64,
134) -> String {
135 let last = nwords.saturating_sub(1);
136 let runcycles = nwords * 8 + 60;
137 let and_exp = aval & bval;
138 let or_exp = aval | bval;
139 format!(
140 r#"`timescale 1ns/1ps
141module tb_computedram_reduce;
142 reg clk=0; always #5 clk=~clk;
143 reg rst=1;
144 reg [63:0] rom [0:{last}];
145 integer idx=0;
146 wire [63:0] cmd_word = rom[idx];
147 wire cmd_valid = (idx <= {last});
148 wire cmd_ack, issue; wire [2:0] op; wire [4:0] bank; wire [31:0] row;
149 dram_executor exec(.clk(clk), .rst(rst), .cmd_word(cmd_word), .cmd_valid(cmd_valid),
150 .cmd_ack(cmd_ack), .issue(issue), .op(op), .bank(bank), .row(row));
151 reg pre_we; reg [7:0] pre_addr; reg [63:0] pre_data; reg [7:0] rd_addr; wire [63:0] rd_out;
152 computedram_model #(.AW(8), .DW(64)) dut(.clk(clk), .rst(rst), .issue(issue), .op(op), .bank(bank),
153 .row(row), .pre_we(pre_we), .pre_addr(pre_addr), .pre_data(pre_data), .rd_addr(rd_addr), .rd_out(rd_out));
154 integer errors;
155 always @(posedge clk) if (!rst && cmd_ack) idx <= idx + 1;
156 task preload(input [7:0] addr, input [63:0] val); begin
157 @(posedge clk); pre_we=1; pre_addr=addr; pre_data=val; @(posedge clk); pre_we=0;
158 end endtask
159 initial begin
160 errors=0; pre_we=0; pre_addr=0; pre_data=0; rd_addr=0;
161 $readmemh("cdram_reduce.hex", rom);
162 preload(8'd{a}, 64'h{aval:016x}); // AND operands + 0 control
163 preload(8'd{b}, 64'h{bval:016x});
164 preload(8'd{zero}, 64'h0000000000000000);
165 preload(8'd{a2}, 64'h{aval:016x}); // OR operands + all-ones control
166 preload(8'd{b2}, 64'h{bval:016x});
167 preload(8'd{ones}, 64'hffffffffffffffff);
168 @(posedge clk); rst=0;
169 repeat ({runcycles}) @(posedge clk);
170 rd_addr=8'd{a}; @(posedge clk); @(posedge clk);
171 if (rd_out !== 64'h{and_exp:016x}) begin errors=errors+1; $display("FAIL: in-DRAM AND = %h exp %h", rd_out, 64'h{and_exp:016x}); end
172 rd_addr=8'd{a2}; @(posedge clk); @(posedge clk);
173 if (rd_out !== 64'h{or_exp:016x}) begin errors=errors+1; $display("FAIL: in-DRAM OR = %h exp %h", rd_out, 64'h{or_exp:016x}); end
174 if (errors==0)
175 $display("PASS: in-DRAM bitwise AND (MAJ a,b,0) and OR (MAJ a,b,1) via triple-row activation == the oracle");
176 $finish;
177 end
178endmodule
179"#
180 )
181}
182
183#[cfg(test)]
184#[path = "../../../logicaffeine_tests/unit/logicaffeine_compile/codegen_sva/computedram_rtl/tests.rs"]
185mod tests;