diff --git a/elab_expr.cc b/elab_expr.cc index af11c7559..f0660db93 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1531,9 +1531,15 @@ unsigned PECallFunction::test_width(Design*des, NetScope*scope, if (peek_tail_name(path_)[0] == '$') return test_width_sfunc_(des, scope, mode); + NetScope *use_scope = scope; + if (package_) { + use_scope = des->find_package(package_->pscope_name()); + ivl_assert(*this, use_scope); + } + // Search for the symbol. This should turn up a scope. symbol_search_results search_results; - bool search_flag = symbol_search(this, des, scope, path_, &search_results); + bool search_flag = symbol_search(this, des, use_scope, path_, &search_results); if (debug_elaborate) { cerr << get_fileline() << ": PECallFunction::test_width: " diff --git a/ivtest/ivltests/sv_ps_function5.v b/ivtest/ivltests/sv_ps_function5.v new file mode 100644 index 000000000..0c1928d27 --- /dev/null +++ b/ivtest/ivltests/sv_ps_function5.v @@ -0,0 +1,66 @@ +// Check that the signedness of package scoped functions is handled correctly. + +package P; + function shortint s(); + return -1; + endfunction + + function bit [15:0] u(); + return -1; + endfunction +endpackage + +module test; + + bit failed = 1'b0; + + `define check(x) \ + if (!(x)) begin \ + $display("FAILED(%0d): ", `__LINE__, `"x`"); \ + failed = 1'b1; \ + end + + int unsigned x = 10; + int y = 10; + int z; + + initial begin + // These all evaluate as signed + `check(P::s() < 0) + `check($signed(P::u()) < 0) + + // These all evaluate as unsigned + `check(P::u() > 0) + `check({P::s()} > 0) + `check($unsigned(P::s()) > 0) + `check(P::s() > 16'h0) + + // In arithmetic expressions if one operand is unsigned all operands are + // considered unsigned + z = P::u() + x; + `check(z === 65545) + z = P::u() + y; + `check(z === 65545) + + z = P::s() + x; + `check(z === 65545) + z = P::s() + y; + `check(z === 9) + + // For ternary operators if one operand is unsigned the result is unsigend + z = x ? P::u() : x; + `check(z === 65535) + z = x ? P::u() : y; + `check(z === 65535) + + z = x ? P::s() : x; + `check(z === 65535) + z = x ? P::s() : y; + `check(z === -1) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_ps_function6.v b/ivtest/ivltests/sv_ps_function6.v new file mode 100644 index 000000000..8cd0e0935 --- /dev/null +++ b/ivtest/ivltests/sv_ps_function6.v @@ -0,0 +1,28 @@ +// Check that the signedness of package scoped functions is handled correctly, +// when passing the result of the function to a system function + +package P; + function shortint s(); + return -1; + endfunction + + function bit [15:0] u(); + return -1; + endfunction +endpackage + + +module test; + + string s; + + initial begin + s = $sformatf("%0d %0d", P::s(), P::u()); + if (s == "-1 65535") begin + $display("PASSED"); + end else begin + $display("FAILED s=%s", s); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_ps_function7.v b/ivtest/ivltests/sv_ps_function7.v new file mode 100644 index 000000000..b051d373a --- /dev/null +++ b/ivtest/ivltests/sv_ps_function7.v @@ -0,0 +1,19 @@ +// Check that the width of a package scoped function is reported correctly. + +package P; + function bit [22:0] s(); + return 0; + endfunction +endpackage + +module test; + + initial begin + if ($bits(P::s()) == 23) begin + $display("PASSED"); + end else begin + $display("FAILED $bits(P::s()) = %0d", $bits(P::s())); + end + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index ffebda646..880eeb8d6 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -689,6 +689,9 @@ sv_ps_function1 normal,-g2009 ivltests sv_ps_function2 normal,-g2009 ivltests sv_ps_function3 normal,-g2009 ivltests sv_ps_function4 normal,-g2009 ivltests +sv_ps_function5 normal,-g2009 ivltests +sv_ps_function6 normal,-g2009 ivltests +sv_ps_function7 normal,-g2009 ivltests sv_ps_type1 normal,-g2009 ivltests sv_ps_type_cast1 normal,-g2009 ivltests sv_ps_type_cast2 normal,-g2009 ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index 6475f29af..375c010a4 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -309,6 +309,7 @@ sv_string5 CE,-g2009 ivltests sv_string6 CE,-g2009,-pallowsigned=1 ivltests sv_string7 CE,-g2009,-pallowsigned=1 ivltests sv_string7b CE,-g2009,-pallowsigned=1 ivltests +sv_ps_function6 CE,-g2009,-pallowsigned=1 ivltests sv_typedef_fwd_base CE,-g2009 ivltests vhdl_string_lim CE,-g2005-sv,-pallowsigned=1,ivltests/vhdl_string_lim.vhd ivltests vhdl_textio_write CE,-g2005-sv,-pallowsigned=1,ivltests/vhdl_textio_write.vhd ivltests @@ -989,6 +990,7 @@ sv_package2 normal,-g2009,-pallowsigned=1 ivltests sv_package5 normal,-g2009,-pallowsigned=1 ivltests sv_port_default10 normal,-g2009,-pallowsigned=1 ivltests sv_port_default11 normal,-g2009,-pallowsigned=1 ivltests +sv_ps_function5 normal,-g2009,-pallowsigned=1 ivltests sv_root_func normal,-g2009,-pallowsigned=1 ivltests gold=sv_root_func.gold sv_root_task normal,-g2009,-pallowsigned=1 ivltests gold=sv_root_task.gold sv_var_block normal,-g2005-sv,-pallowsigned=1 ivltests diff --git a/tgt-vlog95/scope.c b/tgt-vlog95/scope.c index 899052117..0821255b5 100644 --- a/tgt-vlog95/scope.c +++ b/tgt-vlog95/scope.c @@ -40,6 +40,19 @@ static void emit_func_return(ivl_signal_t sig) } else if (ivl_signal_data_type(sig) == IVL_VT_REAL) { fprintf(vlog_out, " real"); } else { + if (ivl_signal_signed(sig)) { + if (allow_signed) { + fprintf(vlog_out, " signed"); + } else { + fprintf(stderr, "%s:%u: vlog95 error: Signed return " + "value for function `%s` is not " + "supported.\n", + ivl_signal_file(sig), + ivl_signal_lineno(sig), + ivl_signal_basename(sig)); + vlog_errors += 1; + } + } int msb, lsb; get_sig_msb_lsb(sig, &msb, &lsb); if (msb != 0 || lsb != 0) fprintf(vlog_out, " [%d:%d]", msb, lsb);