Further fixes for vvp code generation for c. assign of an array word.

The draw_net_input() function can write additional statements to the output
file, so must not be called in the midst of writing a statement.

(cherry picked from commit e53b2e774b)
This commit is contained in:
Martin Whitaker 2022-03-19 10:22:49 +00:00
parent 92e4597607
commit ff21f02c6c
4 changed files with 137 additions and 41 deletions

View File

@ -0,0 +1,34 @@
module tb();
reg inputs[1:0];
reg out;
always @* begin
if (inputs[1]) out = inputs[0];
end
reg failed;
(* ivl_synthesis_off *)
initial begin
failed = 0;
#1 inputs[1] = 1;
#1 inputs[0] = 0;
#1 $display(inputs[1],,inputs[0],,out);
if (out !== 0) failed = 1;
#1 inputs[1] = 0;
#1 inputs[0] = 1;
#1 $display(inputs[1],,inputs[0],,out);
if (out !== 0) failed = 1;
#1 inputs[1] = 1;
#1 $display(inputs[1],,inputs[0],,out);
if (out !== 1) failed = 1;
if (failed)
$display("FAILED");
else
$display("PASSED");
end
endmodule

View File

@ -0,0 +1,30 @@
module tb();
reg [7:0] in[1:0];
wire [7:0] out[1:0];
assign out[0] = $clog2(in[0]);
assign out[1] = $clog2(in[1]);
reg failed;
initial begin
failed = 0;
#1 in[0] = 1;
#1 $display("%0d -> %0d", in[0],out[0]);
if (out[0] !== 0) failed = 1;
#1 in[1] = 2;
#1 $display("%0d -> %0d", in[1],out[1]);
if (out[1] !== 1) failed = 1;
#1 in[0] = 3;
#1 $display("%0d -> %0d", in[0],out[0]);
if (out[0] !== 2) failed = 1;
if (failed)
$display("FAILED");
else
$display("PASSED");
end
endmodule

View File

@ -342,6 +342,8 @@ br_gh531 normal ivltests gold=br_gh531.gold
br_gh533 CE ivltests br_gh533 CE ivltests
br_gh567 normal,-g2001 ivltests gold=br_gh567.gold br_gh567 normal,-g2001 ivltests gold=br_gh567.gold
br_gh632 normal ivltests br_gh632 normal ivltests
br_gh632b normal,-S ivltests
br_gh632c normal ivltests
br_ml20150315 normal ivltests gold=br_ml_20150315.gold br_ml20150315 normal ivltests gold=br_ml_20150315.gold
br_ml20150321 CE ivltests br_ml20150321 CE ivltests
br_ml20150606 normal ivltests br_ml20150606 normal ivltests

View File

@ -1748,6 +1748,11 @@ static void draw_lpm_concat(ivl_lpm_t net)
static void draw_lpm_ff(ivl_lpm_t net) static void draw_lpm_ff(ivl_lpm_t net)
{ {
ivl_nexus_t nex; ivl_nexus_t nex;
const char*clk_in;
const char*d_in;
const char*e_in;
const char*clr_in;
const char*set_in;
/* Sync set/clear control is not currently supported. This is not /* Sync set/clear control is not currently supported. This is not
* a problem, as synthesis can incorporate this in the D input * a problem, as synthesis can incorporate this in the D input
@ -1760,12 +1765,47 @@ static void draw_lpm_ff(ivl_lpm_t net)
unsigned width = ivl_lpm_width(net); unsigned width = ivl_lpm_width(net);
char*edge = ivl_lpm_negedge(net) ? "n" : "p"; char*edge = ivl_lpm_negedge(net) ? "n" : "p";
if (ivl_lpm_async_clr(net)) {
nex = ivl_lpm_clk(net);
assert(nex);
assert(width_of_nexus(nex) == 1);
clk_in = draw_net_input(nex);
nex = ivl_lpm_data(net,0);
assert(nex);
assert(width_of_nexus(nex) == width);
d_in = draw_net_input(nex);
nex = ivl_lpm_enable(net);
if (nex) {
assert(width_of_nexus(nex) == 1);
e_in = draw_net_input(nex);
} else {
e_in = ", C4<1>";
}
nex = ivl_lpm_async_clr(net);
if (nex) {
assert(width_of_nexus(nex) == 1);
clr_in = draw_net_input(nex);
} else {
clr_in = 0;
}
nex = ivl_lpm_async_set(net);
if (nex) {
assert(width_of_nexus(nex) == 1);
set_in = draw_net_input(nex);
} else {
set_in = 0;
}
if (clr_in) {
/* Synthesis doesn't currently support both set and clear. /* Synthesis doesn't currently support both set and clear.
If it ever does, it might be better to implement the If it ever does, it might be better to implement the
flip-flop as a UDP. See tgt-vlog95 for an example of flip-flop as a UDP. See tgt-vlog95 for an example of
how to do this. */ how to do this. */
if (ivl_lpm_async_set(net)) { if (set_in) {
fprintf(stderr, "%s:%u:vvp.tgt: sorry: No support for a DFF " fprintf(stderr, "%s:%u:vvp.tgt: sorry: No support for a DFF "
"with both an async. set and clear.\n", "with both an async. set and clear.\n",
ivl_lpm_file(net), ivl_lpm_lineno(net)); ivl_lpm_file(net), ivl_lpm_lineno(net));
@ -1778,33 +1818,15 @@ static void draw_lpm_ff(ivl_lpm_t net)
fprintf(vvp_out, "L_%p .dff/%s %u ", net, edge, width); fprintf(vvp_out, "L_%p .dff/%s %u ", net, edge, width);
} }
nex = ivl_lpm_data(net,0); fprintf(vvp_out, "%s, %s, %s", d_in, clk_in, e_in);
assert(nex);
fprintf(vvp_out, "%s", draw_net_input(nex));
assert(width_of_nexus(nex) == width);
nex = ivl_lpm_clk(net); if (clr_in) {
assert(nex); fprintf(vvp_out, ", %s", clr_in);
assert(width_of_nexus(nex) == 1);
fprintf(vvp_out, ", %s", draw_net_input(nex));
nex = ivl_lpm_enable(net);
if (nex) {
assert(width_of_nexus(nex) == 1);
fprintf(vvp_out, ", %s", draw_net_input(nex));
} else {
fprintf(vvp_out, ", C4<1>");
} }
if ( (nex = ivl_lpm_async_clr(net)) ) { if (set_in) {
assert(width_of_nexus(nex) == 1);
fprintf(vvp_out, ", %s", draw_net_input(nex));
}
if ( (nex = ivl_lpm_async_set(net)) ) {
ivl_expr_t val = ivl_lpm_aset_value(net); ivl_expr_t val = ivl_lpm_aset_value(net);
assert(width_of_nexus(nex) == 1); fprintf(vvp_out, ", %s", set_in);
fprintf(vvp_out, ", %s", draw_net_input(nex));
if (val) { if (val) {
unsigned nbits = ivl_expr_width(val); unsigned nbits = ivl_expr_width(val);
const char*bits = ivl_expr_bits(val); const char*bits = ivl_expr_bits(val);
@ -1828,21 +1850,22 @@ static void draw_lpm_ff(ivl_lpm_t net)
static void draw_lpm_latch(ivl_lpm_t net) static void draw_lpm_latch(ivl_lpm_t net)
{ {
ivl_nexus_t nex; ivl_nexus_t nex;
const char*d_in;
const char*e_in;
unsigned width = ivl_lpm_width(net); unsigned width = ivl_lpm_width(net);
fprintf(vvp_out, "L_%p .latch %u ", net, width);
nex = ivl_lpm_data(net,0); nex = ivl_lpm_data(net,0);
assert(nex); assert(nex);
fprintf(vvp_out, "%s", draw_net_input(nex));
assert(width_of_nexus(nex) == width); assert(width_of_nexus(nex) == width);
d_in = draw_net_input(nex);
nex = ivl_lpm_enable(net); nex = ivl_lpm_enable(net);
assert(nex); assert(nex);
assert(width_of_nexus(nex) == 1); assert(width_of_nexus(nex) == 1);
fprintf(vvp_out, ", %s", draw_net_input(nex)); e_in = draw_net_input(nex);
fprintf(vvp_out, ";\n"); fprintf(vvp_out, "L_%p .latch %u %s, %s;\n", net, width, d_in, e_in);
} }
static void draw_lpm_shiftl(ivl_lpm_t net) static void draw_lpm_shiftl(ivl_lpm_t net)
@ -1932,6 +1955,13 @@ static void draw_lpm_sfunc(ivl_lpm_t net)
ivl_variable_type_t dt = data_type_of_nexus(ivl_lpm_q(net)); ivl_variable_type_t dt = data_type_of_nexus(ivl_lpm_q(net));
const char*dly = draw_lpm_output_delay(net, dt); const char*dly = draw_lpm_output_delay(net, dt);
/* Get all the input labels that I will use for net signals that
connect to the inputs of the function. */
unsigned ninp = ivl_lpm_size(net);
const char**input_strings = calloc(ninp, sizeof(char*));
for (idx = 0 ; idx < ninp ; idx += 1)
input_strings[idx] = draw_net_input(ivl_lpm_data(net, idx));
/* Because vvp uses a wide functor for the output of a system /* Because vvp uses a wide functor for the output of a system
* function we need to define the output delay net when needed, * function we need to define the output delay net when needed,
* otherwise it will not be cleaned up correctly (gives a * otherwise it will not be cleaned up correctly (gives a
@ -1967,7 +1997,7 @@ static void draw_lpm_sfunc(ivl_lpm_t net)
fprintf(vvp_out, "\""); fprintf(vvp_out, "\"");
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) { for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx))); fprintf(vvp_out, ", %s", input_strings[idx]);
} }
fprintf(vvp_out, ";\n"); fprintf(vvp_out, ";\n");
@ -2059,6 +2089,7 @@ static void draw_lpm_part(ivl_lpm_t net)
unsigned width, base; unsigned width, base;
ivl_nexus_t sel; ivl_nexus_t sel;
const char*input = draw_net_input(ivl_lpm_data(net, 0));
const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC); const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC);
width = ivl_lpm_width(net); width = ivl_lpm_width(net);
@ -2066,14 +2097,13 @@ static void draw_lpm_part(ivl_lpm_t net)
sel = ivl_lpm_data(net,1); sel = ivl_lpm_data(net,1);
if (sel == 0) { if (sel == 0) {
fprintf(vvp_out, "L_%p%s .part %s", fprintf(vvp_out, "L_%p%s .part %s", net, dly, input);
net, dly, draw_net_input(ivl_lpm_data(net, 0)));
fprintf(vvp_out, ", %u, %u;\n", base, width); fprintf(vvp_out, ", %u, %u;\n", base, width);
} else { } else {
const char*sel_symbol = draw_net_input(sel); const char*sel_symbol = draw_net_input(sel);
fprintf(vvp_out, "L_%p%s .part/v%s %s", net, dly, fprintf(vvp_out, "L_%p%s .part/v%s %s", net, dly,
(ivl_lpm_signed(net) ? ".s" : ""), (ivl_lpm_signed(net) ? ".s" : ""),
draw_net_input(ivl_lpm_data(net,0))); input);
fprintf(vvp_out, ", %s", sel_symbol); fprintf(vvp_out, ", %s", sel_symbol);
fprintf(vvp_out, ", %u;\n", width); fprintf(vvp_out, ", %u;\n", width);
} }
@ -2089,9 +2119,9 @@ static void draw_lpm_part_pv(ivl_lpm_t net)
unsigned base = ivl_lpm_base(net); unsigned base = ivl_lpm_base(net);
unsigned signal_width = width_of_nexus(ivl_lpm_q(net)); unsigned signal_width = width_of_nexus(ivl_lpm_q(net));
fprintf(vvp_out, "L_%p .part/pv %s", const char*input = draw_net_input(ivl_lpm_data(net, 0));
net, draw_net_input(ivl_lpm_data(net, 0)));
fprintf(vvp_out, "L_%p .part/pv %s", net, input);
fprintf(vvp_out, ", %u, %u, %u;\n", base, width, signal_width); fprintf(vvp_out, ", %u, %u, %u;\n", base, width, signal_width);
} }
@ -2100,28 +2130,28 @@ static void draw_lpm_part_pv(ivl_lpm_t net)
*/ */
static void draw_lpm_re(ivl_lpm_t net, const char*type) static void draw_lpm_re(ivl_lpm_t net, const char*type)
{ {
const char*input = draw_net_input(ivl_lpm_data(net, 0));
const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC); const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC);
fprintf(vvp_out, "L_%p%s .reduce/%s %s;\n", net, dly, fprintf(vvp_out, "L_%p%s .reduce/%s %s;\n", net, dly, type, input);
type, draw_net_input(ivl_lpm_data(net,0)));
} }
static void draw_lpm_repeat(ivl_lpm_t net) static void draw_lpm_repeat(ivl_lpm_t net)
{ {
const char*input = draw_net_input(ivl_lpm_data(net, 0));
const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC); const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC);
fprintf(vvp_out, "L_%p%s .repeat %u, %u, %s;\n", net, dly, fprintf(vvp_out, "L_%p%s .repeat %u, %u, %s;\n", net, dly,
ivl_lpm_width(net), ivl_lpm_size(net), ivl_lpm_width(net), ivl_lpm_size(net), input);
draw_net_input(ivl_lpm_data(net,0)));
} }
static void draw_lpm_sign_ext(ivl_lpm_t net) static void draw_lpm_sign_ext(ivl_lpm_t net)
{ {
const char*input = draw_net_input(ivl_lpm_data(net, 0));
const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC); const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC);
fprintf(vvp_out, "L_%p%s .extend/s %u, %s;\n", fprintf(vvp_out, "L_%p%s .extend/s %u, %s;\n",
net, dly, ivl_lpm_width(net), net, dly, ivl_lpm_width(net), input);
draw_net_input(ivl_lpm_data(net,0)));
} }
static void draw_lpm_in_scope(ivl_lpm_t net) static void draw_lpm_in_scope(ivl_lpm_t net)