Skip to content

Instantly share code, notes, and snippets.

@nathanielnrn
Created July 5, 2024 20:43
Show Gist options
  • Save nathanielnrn/237812d9682dd55f60bd6cbfd0fb6868 to your computer and use it in GitHub Desktop.
Save nathanielnrn/237812d9682dd55f60bd6cbfd0fb6868 to your computer and use it in GitHub Desktop.
Combinational Loops
/**
* Core primitives for Calyx.
* Implements core primitives used by the compiler.
*
* Conventions:
* - All parameter names must be SNAKE_CASE and all caps.
* - Port names must be snake_case, no caps.
*/
module std_slice #(
parameter IN_WIDTH = 32,
parameter OUT_WIDTH = 32
) (
input wire logic [ IN_WIDTH-1:0] in,
output logic [OUT_WIDTH-1:0] out
);
assign out = in[OUT_WIDTH-1:0];
`ifdef VERILATOR
always_comb begin
if (IN_WIDTH < OUT_WIDTH)
$error(
"std_slice: Input width less than output width\n",
"IN_WIDTH: %0d", IN_WIDTH,
"OUT_WIDTH: %0d", OUT_WIDTH
);
end
`endif
endmodule
module std_pad #(
parameter IN_WIDTH = 32,
parameter OUT_WIDTH = 32
) (
input wire logic [IN_WIDTH-1:0] in,
output logic [OUT_WIDTH-1:0] out
);
localparam EXTEND = OUT_WIDTH - IN_WIDTH;
assign out = { {EXTEND {1'b0}}, in};
`ifdef VERILATOR
always_comb begin
if (IN_WIDTH > OUT_WIDTH)
$error(
"std_pad: Output width less than input width\n",
"IN_WIDTH: %0d", IN_WIDTH,
"OUT_WIDTH: %0d", OUT_WIDTH
);
end
`endif
endmodule
module std_cat #(
parameter LEFT_WIDTH = 32,
parameter RIGHT_WIDTH = 32,
parameter OUT_WIDTH = 64
) (
input wire logic [LEFT_WIDTH-1:0] left,
input wire logic [RIGHT_WIDTH-1:0] right,
output logic [OUT_WIDTH-1:0] out
);
assign out = {left, right};
`ifdef VERILATOR
always_comb begin
if (LEFT_WIDTH + RIGHT_WIDTH != OUT_WIDTH)
$error(
"std_cat: Output width must equal sum of input widths\n",
"LEFT_WIDTH: %0d", LEFT_WIDTH,
"RIGHT_WIDTH: %0d", RIGHT_WIDTH,
"OUT_WIDTH: %0d", OUT_WIDTH
);
end
`endif
endmodule
module std_not #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] in,
output logic [WIDTH-1:0] out
);
assign out = ~in;
endmodule
module std_and #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left & right;
endmodule
module std_or #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left | right;
endmodule
module std_xor #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left ^ right;
endmodule
module std_sub #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left - right;
endmodule
module std_gt #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic out
);
assign out = left > right;
endmodule
module std_lt #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic out
);
assign out = left < right;
endmodule
module std_eq #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic out
);
assign out = left == right;
endmodule
module std_neq #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic out
);
assign out = left != right;
endmodule
module std_ge #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic out
);
assign out = left >= right;
endmodule
module std_le #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic out
);
assign out = left <= right;
endmodule
module std_rsh #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left >> right;
endmodule
/// this primitive is intended to be used
/// for lowering purposes (not in source programs)
module std_mux #(
parameter WIDTH = 32
) (
input wire logic cond,
input wire logic [WIDTH-1:0] tru,
input wire logic [WIDTH-1:0] fal,
output logic [WIDTH-1:0] out
);
assign out = cond ? tru : fal;
endmodule
module std_bit_slice #(
parameter IN_WIDTH = 32,
parameter START_IDX = 0,
parameter END_IDX = 31,
parameter OUT_WIDTH = 32
)(
input wire logic [IN_WIDTH-1:0] in,
output logic [OUT_WIDTH-1:0] out
);
assign out = in[END_IDX:START_IDX];
`ifdef VERILATOR
always_comb begin
if (START_IDX < 0 || END_IDX > IN_WIDTH-1)
$error(
"std_bit_slice: Slice range out of bounds\n",
"IN_WIDTH: %0d", IN_WIDTH,
"START_IDX: %0d", START_IDX,
"END_IDX: %0d", END_IDX,
);
end
`endif
endmodule
module undef #(
parameter WIDTH = 32
) (
output logic [WIDTH-1:0] out
);
assign out = 'x;
endmodule
module std_const #(
parameter WIDTH = 32,
parameter VALUE = 32
) (
output logic [WIDTH-1:0] out
);
assign out = VALUE;
endmodule
module std_wire #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] in,
output logic [WIDTH-1:0] out
);
assign out = in;
endmodule
module std_add #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left + right;
endmodule
module std_lsh #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left << right;
endmodule
module std_reg #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] in,
input wire logic write_en,
input wire logic clk,
input wire logic reset,
output logic [WIDTH-1:0] out,
output logic done
);
always_ff @(posedge clk) begin
if (reset) begin
out <= 0;
done <= 0;
end else if (write_en) begin
out <= in;
done <= 1'd1;
end else done <= 1'd0;
end
endmodule
module init_one_reg #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] in,
input wire logic write_en,
input wire logic clk,
input wire logic reset,
output logic [WIDTH-1:0] out,
output logic done
);
always_ff @(posedge clk) begin
if (reset) begin
out <= 1;
done <= 0;
end else if (write_en) begin
out <= in;
done <= 1'd1;
end else done <= 1'd0;
end
endmodule
module invokee(
input logic go,
input logic clk,
input logic reset,
output logic done,
output logic [31:0] ref_reg_in,
output logic ref_reg_write_en,
input logic [31:0] ref_reg_out,
input logic ref_reg_done
);
// COMPONENT START: invokee
logic invokee_ref_reg_write_go_in;
logic invokee_ref_reg_write_go_out;
logic invokee_ref_reg_write_done_in;
logic invokee_ref_reg_write_done_out;
std_wire # (
.WIDTH(1)
) invokee_ref_reg_write_go (
.in(invokee_ref_reg_write_go_in),
.out(invokee_ref_reg_write_go_out)
);
std_wire # (
.WIDTH(1)
) invokee_ref_reg_write_done (
.in(invokee_ref_reg_write_done_in),
.out(invokee_ref_reg_write_done_out)
);
wire _guard0 = 1;
wire _guard1 = invokee_ref_reg_write_done_out;
wire _guard2 = invokee_ref_reg_write_go_out;
wire _guard3 = invokee_ref_reg_write_go_out;
assign done = _guard1;
assign ref_reg_in = 32'd0;
assign ref_reg_write_en = _guard3;
assign invokee_ref_reg_write_done_in = ref_reg_done;
assign invokee_ref_reg_write_go_in = go;
// COMPONENT END: invokee
endmodule
module wrapper(
input logic go,
input logic clk,
input logic reset,
output logic done
);
// COMPONENT START: wrapper
logic [31:0] concrete_reg_in;
logic concrete_reg_write_en;
logic concrete_reg_clk;
logic concrete_reg_reset;
logic [31:0] concrete_reg_out;
logic concrete_reg_done;
logic invokee_go;
logic invokee_clk;
logic invokee_reset;
logic invokee_done;
logic [31:0] invokee_ref_reg_in;
logic [31:0] invokee_ref_reg_out;
logic invokee_ref_reg_write_en;
logic invokee_ref_reg_done;
logic [1:0] fsm_in;
logic fsm_write_en;
logic fsm_clk;
logic fsm_reset;
logic [1:0] fsm_out;
logic fsm_done;
logic invoke0_go_in;
logic invoke0_go_out;
logic invoke0_done_in;
logic invoke0_done_out;
logic invoke1_go_in;
logic invoke1_go_out;
logic invoke1_done_in;
logic invoke1_done_out;
logic tdcc_go_in;
logic tdcc_go_out;
logic tdcc_done_in;
logic tdcc_done_out;
std_reg # (
.WIDTH(32)
) concrete_reg (
.clk(concrete_reg_clk),
.done(concrete_reg_done),
.in(concrete_reg_in),
.out(concrete_reg_out),
.reset(concrete_reg_reset),
.write_en(concrete_reg_write_en)
);
invokee invokee (
.clk(invokee_clk),
.done(invokee_done),
.go(invokee_go),
.ref_reg_done(invokee_ref_reg_done),
.ref_reg_in(invokee_ref_reg_in),
.ref_reg_out(invokee_ref_reg_out),
.ref_reg_write_en(invokee_ref_reg_write_en),
.reset(invokee_reset)
);
std_reg # (
.WIDTH(2)
) fsm (
.clk(fsm_clk),
.done(fsm_done),
.in(fsm_in),
.out(fsm_out),
.reset(fsm_reset),
.write_en(fsm_write_en)
);
std_wire # (
.WIDTH(1)
) invoke0_go (
.in(invoke0_go_in),
.out(invoke0_go_out)
);
std_wire # (
.WIDTH(1)
) invoke0_done (
.in(invoke0_done_in),
.out(invoke0_done_out)
);
std_wire # (
.WIDTH(1)
) invoke1_go (
.in(invoke1_go_in),
.out(invoke1_go_out)
);
std_wire # (
.WIDTH(1)
) invoke1_done (
.in(invoke1_done_in),
.out(invoke1_done_out)
);
std_wire # (
.WIDTH(1)
) tdcc_go (
.in(tdcc_go_in),
.out(tdcc_go_out)
);
std_wire # (
.WIDTH(1)
) tdcc_done (
.in(tdcc_done_in),
.out(tdcc_done_out)
);
wire _guard0 = 1;
wire _guard1 = invoke1_go_out;
wire _guard2 = invoke1_go_out;
wire _guard3 = invoke1_go_out;
wire _guard4 = tdcc_done_out;
wire _guard5 = fsm_out == 2'd2;
wire _guard6 = fsm_out == 2'd0;
wire _guard7 = invoke0_done_out;
wire _guard8 = _guard6 & _guard7;
wire _guard9 = tdcc_go_out;
wire _guard10 = _guard8 & _guard9;
wire _guard11 = _guard5 | _guard10;
wire _guard12 = fsm_out == 2'd1;
wire _guard13 = invoke1_done_out;
wire _guard14 = _guard12 & _guard13;
wire _guard15 = tdcc_go_out;
wire _guard16 = _guard14 & _guard15;
wire _guard17 = _guard11 | _guard16;
wire _guard18 = fsm_out == 2'd0;
wire _guard19 = invoke0_done_out;
wire _guard20 = _guard18 & _guard19;
wire _guard21 = tdcc_go_out;
wire _guard22 = _guard20 & _guard21;
wire _guard23 = fsm_out == 2'd2;
wire _guard24 = fsm_out == 2'd1;
wire _guard25 = invoke1_done_out;
wire _guard26 = _guard24 & _guard25;
wire _guard27 = tdcc_go_out;
wire _guard28 = _guard26 & _guard27;
wire _guard29 = invoke0_done_out;
wire _guard30 = ~_guard29;
wire _guard31 = fsm_out == 2'd0;
wire _guard32 = _guard30 & _guard31;
wire _guard33 = tdcc_go_out;
wire _guard34 = _guard32 & _guard33;
wire _guard35 = invoke1_done_out;
wire _guard36 = ~_guard35;
wire _guard37 = fsm_out == 2'd1;
wire _guard38 = _guard36 & _guard37;
wire _guard39 = tdcc_go_out;
wire _guard40 = _guard38 & _guard39;
wire _guard41 = fsm_out == 2'd2;
wire _guard42 = invoke1_go_out;
wire _guard43 = invoke0_go_out;
wire _guard44 = invoke1_go_out;
wire _guard45 = invoke0_go_out;
assign invokee_ref_reg_out =
_guard1 ? concrete_reg_out :
32'd0;
assign invokee_clk = clk;
assign invokee_go = _guard2;
assign invokee_reset = reset;
assign invokee_ref_reg_done =
_guard3 ? concrete_reg_done :
1'd0;
assign done = _guard4;
assign fsm_write_en = _guard17;
assign fsm_clk = clk;
assign fsm_reset = reset;
assign fsm_in =
_guard22 ? 2'd1 :
_guard23 ? 2'd0 :
_guard28 ? 2'd2 :
2'd0;
assign invoke0_go_in = _guard34;
assign tdcc_go_in = go;
assign invoke0_done_in = concrete_reg_done;
assign invoke1_go_in = _guard40;
assign tdcc_done_in = _guard41;
assign concrete_reg_write_en =
_guard42 ? invokee_ref_reg_write_en :
_guard43 ? 1'd1 :
1'd0;
assign concrete_reg_clk = clk;
assign concrete_reg_reset = reset;
assign concrete_reg_in =
_guard44 ? invokee_ref_reg_in :
_guard45 ? 32'd0 :
'x;
assign invoke1_done_in = invokee_done;
// COMPONENT END: wrapper
endmodule
module main(
input logic go,
input logic clk,
input logic reset,
output logic done
);
// COMPONENT START: main
logic wrapper_go;
logic wrapper_clk;
logic wrapper_reset;
logic wrapper_done;
wrapper wrapper (
.clk(wrapper_clk),
.done(wrapper_done),
.go(wrapper_go),
.reset(wrapper_reset)
);
wire _guard0 = 1;
assign done = wrapper_done;
assign wrapper_clk = clk;
assign wrapper_go = go;
assign wrapper_reset = reset;
// COMPONENT END: main
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment