diff --git a/ivtest/ivltests/sv_ap_uarray1.v b/ivtest/ivltests/sv_ap_uarray1.v index b8279dd6a..2d4930bdb 100644 --- a/ivtest/ivltests/sv_ap_uarray1.v +++ b/ivtest/ivltests/sv_ap_uarray1.v @@ -3,12 +3,11 @@ module test; - bit failed; - + bit passed; `define check(val, exp) do \ if (val !== exp) begin \ $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ - failed = 1'b1; \ + passed = 1'b0; \ end \ while(0) @@ -17,6 +16,7 @@ module test; int z[4]; initial begin + passed = 1'b1; x = '{1'b1, 1 + 1, 3.3, "TEST"}; y = '{1'b1, 1 + 1, 3.3, "TEST"}; z = '{1'b1, 1 + 1, 3.3, "TEST"}; @@ -36,7 +36,7 @@ module test; `check(z[2], 3); `check(z[3], 1413829460); - if (!failed) begin + if (passed) begin $display("PASSED"); end end diff --git a/ivtest/ivltests/sv_ap_uarray2.v b/ivtest/ivltests/sv_ap_uarray2.v index 96d6befed..778524179 100644 --- a/ivtest/ivltests/sv_ap_uarray2.v +++ b/ivtest/ivltests/sv_ap_uarray2.v @@ -4,12 +4,12 @@ module test; - bit failed; + bit passed; `define check(val, exp) do \ if (val !== exp) begin \ $display("FAILED(%0d). '%s' expected %0d, got %0d", `__LINE__, `"val`", exp, val); \ - failed = 1'b1; \ + passed = 1'b0; \ end \ while(0) @@ -18,6 +18,7 @@ module test; int z[2][2]; initial begin + passed = 1'b1; x = '{'{1'b1, 1 + 1}, '{3.3, "TEST"}}; y = '{'{1'b1, 1 + 1}, '{3.3, "TEST"}}; z = '{'{1'b1, 1 + 1}, '{3.3, "TEST"}}; @@ -37,7 +38,7 @@ module test; `check(z[1][0], 3); `check(z[1][1], 1413829460); - if (!failed) begin + if (passed) begin $display("PASSED"); end end diff --git a/ivtest/vvp_tests/br_gh1143a.json b/ivtest/vvp_tests/br_gh1143a.json index e76ae6347..2ab433e14 100644 --- a/ivtest/vvp_tests/br_gh1143a.json +++ b/ivtest/vvp_tests/br_gh1143a.json @@ -1,5 +1,9 @@ { "type" : "normal", "source" : "br_gh1143a.v", - "iverilog-args" : [ "-g2012" ] + "iverilog-args" : [ "-g2012" ], + "vlog95" : { + "__comment" : "No way to add the initialization to the for loop", + "type" : "TE" + } } diff --git a/ivtest/vvp_tests/br_gh1143b.json b/ivtest/vvp_tests/br_gh1143b.json index 64e8ccf3c..a6cb58c2d 100644 --- a/ivtest/vvp_tests/br_gh1143b.json +++ b/ivtest/vvp_tests/br_gh1143b.json @@ -1,5 +1,9 @@ { "type" : "normal", "source" : "br_gh1143b.v", - "iverilog-args" : [ "-g2012" ] + "iverilog-args" : [ "-g2012" ], + "vlog95" : { + "__comment" : "No way to add the condition to the for loop", + "type" : "CE" + } } diff --git a/ivtest/vvp_tests/br_gh1143c.json b/ivtest/vvp_tests/br_gh1143c.json index b4d88049b..e0219ac89 100644 --- a/ivtest/vvp_tests/br_gh1143c.json +++ b/ivtest/vvp_tests/br_gh1143c.json @@ -1,5 +1,9 @@ { "type" : "normal", "source" : "br_gh1143c.v", - "iverilog-args" : [ "-g2012" ] + "iverilog-args" : [ "-g2012" ], + "vlog95" : { + "_comment" : "No way to add the increment to the for loop", + "type" : "TE" + } } diff --git a/ivtest/vvp_tests/br_gh1143d.json b/ivtest/vvp_tests/br_gh1143d.json index a397debcd..149d5c661 100644 --- a/ivtest/vvp_tests/br_gh1143d.json +++ b/ivtest/vvp_tests/br_gh1143d.json @@ -1,5 +1,9 @@ { "type" : "normal", "source" : "br_gh1143d.v", - "iverilog-args" : [ "-g2012" ] + "iverilog-args" : [ "-g2012" ], + "vlog95" : { + "__comment" : "No way to add the missing init, cond, incr to the for loop", + "type" : "CE" + } } diff --git a/ivtest/vvp_tests/module_port_array_init1.json b/ivtest/vvp_tests/module_port_array_init1.json index ec34b89b7..5f82e4527 100644 --- a/ivtest/vvp_tests/module_port_array_init1.json +++ b/ivtest/vvp_tests/module_port_array_init1.json @@ -1,5 +1,9 @@ { "type" : "normal", "source" : "module_port_array_init1.v", - "iverilog-args" : [ "-g2005-sv" ] + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Array port/nets are not supported", + "type" : "CE" + } } diff --git a/tgt-vlog95/stmt.c b/tgt-vlog95/stmt.c index ca692f27f..54f55fb2a 100644 --- a/tgt-vlog95/stmt.c +++ b/tgt-vlog95/stmt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2022 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2011-2026 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -407,23 +407,76 @@ static unsigned is_delayed_or_event_assign(ivl_scope_t scope, return 1; } +/* + * Unroll an array pattern to the individual assignments. + */ +static void emit_array_pattern(ivl_scope_t scope, ivl_lval_t lval, + ivl_signal_t var, ivl_expr_t rval, + unsigned array_idx) +{ + (void)array_idx; + for (unsigned idx = 0; idx < ivl_expr_parms(rval); idx += 1) { + ivl_expr_t expr = ivl_expr_parm(rval, idx); + unsigned wid; + int lsb; + if (ivl_expr_type(expr) == IVL_EX_ARRAY_PATTERN) { + fprintf(stderr, "%s:%u: vlog95 error: nested array patterns " + "are not currently supported!\n", + ivl_expr_file(rval), ivl_expr_lineno(rval)); + vlog_errors += 1; + return; + } + fprintf(vlog_out, "%*c", get_indent(), ' '); + emit_stmt_lval_name(scope, lval, var); + assert(ivl_signal_dimensions(var)); + /* For an array the LSB/MSB order is not important. + * They are always accessed from base counting up. */ + lsb = ivl_signal_array_base(var); + fprintf(vlog_out, "[%d] = ", lsb+idx); + wid = ivl_lval_width(lval); + emit_expr(scope, expr, wid, 1, 0, 0); + fprintf(vlog_out, ";\n"); + } +} + /* * A common routine to emit the basic assignment construct. It can also * translate an assignment with an opcode when allowed. */ -static void emit_assign_and_opt_opcode(ivl_scope_t scope, ivl_statement_t stmt, - unsigned allow_opcode) +static unsigned emit_assign_and_opt_opcode(ivl_scope_t scope, ivl_statement_t stmt, + unsigned allow_opcode) { unsigned wid; char opcode; const char *opcode_str; + ivl_expr_t rval; assert (ivl_statement_type(stmt) == IVL_ST_ASSIGN); + rval = ivl_stmt_rval(stmt); + opcode = ivl_stmt_opcode(stmt); + /* Check for an array assignment pattern and wrap it in a begin/end. */ + if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) { + ivl_lval_t lval = ivl_stmt_lval(stmt, 0); + ivl_signal_t sig = ivl_lval_sig(lval); + assert(opcode == 0); + assert(ivl_stmt_lvals(stmt) == 1); + fprintf(vlog_out, "begin"); + if (emit_file_line) { + fprintf(vlog_out, " /* %s:%u */", + ivl_stmt_file(stmt), + ivl_stmt_lineno(stmt)); + } + fprintf(vlog_out, "\n"); + indent += indent_incr; + emit_array_pattern(scope, lval, sig, rval, 0); + indent -= indent_incr; + fprintf(vlog_out, "%*cend", get_indent(), ' '); + return 0; + } // HERE: Do we need to calculate the width? The compiler should have already // done this for us. wid = emit_stmt_lval(scope, stmt); /* Get the opcode and the string version of the opcode. */ - opcode = ivl_stmt_opcode(stmt); switch (opcode) { case 0: opcode_str = ""; break; case '+': opcode_str = "+"; break; @@ -467,7 +520,8 @@ static void emit_assign_and_opt_opcode(ivl_scope_t scope, ivl_statement_t stmt, vlog_errors += 1; } } - emit_expr(scope, ivl_stmt_rval(stmt), wid, 1, 0, 0); + emit_expr(scope, rval, wid, 1, 0, 0); + return 1; } /* @@ -847,10 +901,11 @@ static unsigned is_utask_call_with_args(ivl_scope_t scope, static void emit_stmt_assign(ivl_scope_t scope, ivl_statement_t stmt) { + unsigned emit_semi; fprintf(vlog_out, "%*c", get_indent(), ' '); /* Emit the basic assignment (an opcode is allowed).*/ - emit_assign_and_opt_opcode(scope, stmt, 1); - fprintf(vlog_out, ";"); + emit_semi = emit_assign_and_opt_opcode(scope, stmt, 1); + if (emit_semi) fprintf(vlog_out, ";"); emit_stmt_file_line(stmt); fprintf(vlog_out, "\n"); } @@ -1313,19 +1368,39 @@ static void emit_stmt_fork_named(ivl_scope_t scope, ivl_statement_t stmt) static void emit_stmt_forloop(ivl_scope_t scope, ivl_statement_t stmt) { ivl_statement_t use_init = ivl_stmt_init_stmt(stmt); + ivl_expr_t use_cond = ivl_stmt_cond_expr(stmt); ivl_statement_t use_step = ivl_stmt_step_stmt(stmt); ivl_statement_t use_stmt = ivl_stmt_sub_stmt(stmt); fprintf(vlog_out, "%*cfor (", get_indent(), ' '); /* Assume that the init statement is an assignment. */ if (use_init) - emit_assign_and_opt_opcode(scope, use_init, 0); + (void)emit_assign_and_opt_opcode(scope, use_init, 0); + else { + fprintf(vlog_out, ""); + fprintf(stderr, "%s:%u: vlog95 warning: Missing for() " + "initialization will need to be added manually.\n", + ivl_stmt_file(stmt), ivl_stmt_lineno(stmt)); + } fprintf(vlog_out, "; "); - emit_expr(scope, ivl_stmt_cond_expr(stmt), 0, 0, 0, 0); + if (use_cond) + emit_expr(scope, use_cond, 0, 0, 0, 0); + else { + fprintf(vlog_out, ""); + fprintf(stderr, "%s:%u: vlog95 warning: Missing for() " + "condition will need to be added manually.\n", + ivl_stmt_file(stmt), ivl_stmt_lineno(stmt)); + } fprintf(vlog_out, "; "); /* Assume that the step statement is an assignment. */ if (use_step) - emit_assign_and_opt_opcode(scope, use_step, 1); + (void)emit_assign_and_opt_opcode(scope, use_step, 1); + else { + fprintf(vlog_out, ""); + fprintf(stderr, "%s:%u: vlog95 warning: Missing for() " + "increment will need to be added manually.\n", + ivl_stmt_file(stmt), ivl_stmt_lineno(stmt)); + } fprintf(vlog_out, ")"); single_indent = 1; emit_stmt(scope, use_stmt); @@ -1501,6 +1576,7 @@ void emit_stmt(ivl_scope_t scope, ivl_statement_t stmt) } break; case IVL_ST_BREAK: + fprintf(vlog_out, "%*c;\n", get_indent(), ' '); fprintf(stderr, "%s:%u: vlog95 sorry: 'break' is not " "currently translated.\n", ivl_stmt_file(stmt), @@ -1520,6 +1596,7 @@ void emit_stmt(ivl_scope_t scope, ivl_statement_t stmt) emit_stmt_condit(scope, stmt); break; case IVL_ST_CONTINUE: + fprintf(vlog_out, "%*c;\n", get_indent(), ' '); fprintf(stderr, "%s:%u: vlog95 sorry: 'continue' is not " "currently translated.\n", ivl_stmt_file(stmt),