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_gh567 normal,-g2001 ivltests gold=br_gh567.gold
br_gh632 normal ivltests
br_gh632b normal,-S ivltests
br_gh632c normal ivltests
br_ml20150315 normal ivltests gold=br_ml_20150315.gold
br_ml20150321 CE 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)
{
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
* 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);
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.
If it ever does, it might be better to implement the
flip-flop as a UDP. See tgt-vlog95 for an example of
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 "
"with both an async. set and clear.\n",
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);
}
nex = ivl_lpm_data(net,0);
assert(nex);
fprintf(vvp_out, "%s", draw_net_input(nex));
assert(width_of_nexus(nex) == width);
fprintf(vvp_out, "%s, %s, %s", d_in, clk_in, e_in);
nex = ivl_lpm_clk(net);
assert(nex);
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 (clr_in) {
fprintf(vvp_out, ", %s", clr_in);
}
if ( (nex = ivl_lpm_async_clr(net)) ) {
assert(width_of_nexus(nex) == 1);
fprintf(vvp_out, ", %s", draw_net_input(nex));
}
if ( (nex = ivl_lpm_async_set(net)) ) {
if (set_in) {
ivl_expr_t val = ivl_lpm_aset_value(net);
assert(width_of_nexus(nex) == 1);
fprintf(vvp_out, ", %s", draw_net_input(nex));
fprintf(vvp_out, ", %s", set_in);
if (val) {
unsigned nbits = ivl_expr_width(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)
{
ivl_nexus_t nex;
const char*d_in;
const char*e_in;
unsigned width = ivl_lpm_width(net);
fprintf(vvp_out, "L_%p .latch %u ", net, width);
nex = ivl_lpm_data(net,0);
assert(nex);
fprintf(vvp_out, "%s", draw_net_input(nex));
assert(width_of_nexus(nex) == width);
d_in = draw_net_input(nex);
nex = ivl_lpm_enable(net);
assert(nex);
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)
@ -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));
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
* function we need to define the output delay net when needed,
* 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, "\"");
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");
@ -2059,6 +2089,7 @@ static void draw_lpm_part(ivl_lpm_t net)
unsigned width, base;
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);
width = ivl_lpm_width(net);
@ -2066,14 +2097,13 @@ static void draw_lpm_part(ivl_lpm_t net)
sel = ivl_lpm_data(net,1);
if (sel == 0) {
fprintf(vvp_out, "L_%p%s .part %s",
net, dly, draw_net_input(ivl_lpm_data(net, 0)));
fprintf(vvp_out, "L_%p%s .part %s", net, dly, input);
fprintf(vvp_out, ", %u, %u;\n", base, width);
} else {
const char*sel_symbol = draw_net_input(sel);
fprintf(vvp_out, "L_%p%s .part/v%s %s", net, dly,
(ivl_lpm_signed(net) ? ".s" : ""),
draw_net_input(ivl_lpm_data(net,0)));
input);
fprintf(vvp_out, ", %s", sel_symbol);
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 signal_width = width_of_nexus(ivl_lpm_q(net));
fprintf(vvp_out, "L_%p .part/pv %s",
net, draw_net_input(ivl_lpm_data(net, 0)));
const char*input = 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);
}
@ -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)
{
const char*input = draw_net_input(ivl_lpm_data(net, 0));
const char*dly = draw_lpm_output_delay(net, IVL_VT_LOGIC);
fprintf(vvp_out, "L_%p%s .reduce/%s %s;\n", net, dly,
type, draw_net_input(ivl_lpm_data(net,0)));
fprintf(vvp_out, "L_%p%s .reduce/%s %s;\n", net, dly, type, input);
}
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);
fprintf(vvp_out, "L_%p%s .repeat %u, %u, %s;\n", net, dly,
ivl_lpm_width(net), ivl_lpm_size(net),
draw_net_input(ivl_lpm_data(net,0)));
ivl_lpm_width(net), ivl_lpm_size(net), input);
}
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);
fprintf(vvp_out, "L_%p%s .extend/s %u, %s;\n",
net, dly, ivl_lpm_width(net),
draw_net_input(ivl_lpm_data(net,0)));
net, dly, ivl_lpm_width(net), input);
}
static void draw_lpm_in_scope(ivl_lpm_t net)