-
-
Save nathanielnrn/237812d9682dd55f60bd6cbfd0fb6868 to your computer and use it in GitHub Desktop.
Combinational Loops
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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