Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid cast from type ‘std::__cxx11::basic_string<char>’ to type ‘QData’ {aka ‘long unsigned int’} #4921

Closed
esynr3z opened this issue Feb 24, 2024 · 4 comments
Labels
resolution: fixed Closed; fixed

Comments

@esynr3z
Copy link

esynr3z commented Feb 24, 2024

Hi! I'm getting strange error when I'm trying to compile SVUnit:

In file included from Vtestrunner__ALL.cpp:38:
Vtestrunner_svunit_pkg__03a__03afilter__Vclpkg__DepSet_h2ac5c5c3__0.cpp: In member function ‘void Vtestrunner_svunit_pkg__03a__03afilter::__VnoInFunc_get_filter_expression_parts(Vtestrunner__Syms*, std::string, Vtestrunner_filter_expression_parts__struct__0&)’:
Vtestrunner_svunit_pkg__03a__03afilter__Vclpkg__DepSet_h2ac5c5c3__0.cpp:64:36: error: invalid cast from type ‘std::__cxx11::basic_string<char>’ to type ‘QData’ {aka ‘long unsigned int’}
   64 |                 .__PVT__positive = (QData)(parts.at(0U)),
      |                                    ^~~~~~~~~~~~~~~~~~~~~
Vtestrunner_svunit_pkg__03a__03afilter__Vclpkg__DepSet_h2ac5c5c3__0.cpp:69:32: error: invalid cast from type ‘std::__cxx11::basic_string<char>’ to type ‘QData’ {aka ‘long unsigned int’}
   69 |             .__PVT__positive = (QData)(parts.at(0U)),
      |                                ^~~~~~~~~~~~~~~~~~~~~
Vtestrunner_svunit_pkg__03a__03afilter__Vclpkg__DepSet_h2ac5c5c3__0.cpp:70:32: error: invalid cast from type ‘std::__cxx11::basic_string<char>’ to type ‘QData’ {aka ‘long unsigned int’}
   70 |             .__PVT__negative = (QData)(parts.at(1U))};

Could you please help figuring out what could be a root cause of this?

I've reported reproducer to SVUnit issues, but below are the main things to consider:

Vtestrunner_svunit_pkg__03a__03afilter__Vclpkg__DepSet_h2ac5c5c3__0.cpp
// Verilated -*- C++ -*-
// DESCRIPTION: Verilator output: Design implementation internals
// See Vtestrunner.h for the primary calling header

#include "Vtestrunner__pch.h"
#include "Vtestrunner__Syms.h"
#include "Vtestrunner_svunit_pkg__03a__03afilter__Vclpkg.h"

void Vtestrunner_svunit_pkg__03a__03afilter__Vclpkg::__VnoInFunc_get(Vtestrunner__Syms* __restrict vlSymsp, VlClassRef<Vtestrunner_svunit_pkg__03a__03afilter> &get__Vfuncrtn) {
    VL_DEBUG_IF(VL_DBG_MSGF("+  Vtestrunner_svunit_pkg__03a__03afilter__Vclpkg::__VnoInFunc_get\n"); );
    // Body
    if ((VlNull{} == this->__PVT__single_instance)) {
        this->__PVT__single_instance = VL_NEW(Vtestrunner_svunit_pkg__03a__03afilter, vlSymsp);
    }
    get__Vfuncrtn = this->__PVT__single_instance;
}

Vtestrunner_svunit_pkg__03a__03afilter::Vtestrunner_svunit_pkg__03a__03afilter(Vtestrunner__Syms* __restrict vlSymsp) {
    VL_DEBUG_IF(VL_DBG_MSGF("+              Vtestrunner_svunit_pkg__03a__03afilter::new\n"); );
    // Init
    _ctor_var_reset(vlSymsp);
    std::string __Vfunc_get_filter_value_from_run_script__0__Vfuncout;
    Vtestrunner_filter_expression_parts__struct__0 __Vfunc_get_filter_expression_parts__1__Vfuncout;
    VlQueue<VlClassRef<Vtestrunner_svunit_pkg__03a__03afilter_for_single_pattern>> __Vfunc_get_subfilters__2__Vfuncout;
    VlQueue<VlClassRef<Vtestrunner_svunit_pkg__03a__03afilter_for_single_pattern>> __Vfunc_get_subfilters__3__Vfuncout;
    // Body
    std::string raw_filter;
    this->__VnoInFunc_get_filter_value_from_run_script(vlSymsp, __Vfunc_get_filter_value_from_run_script__0__Vfuncout);
    raw_filter = __Vfunc_get_filter_value_from_run_script__0__Vfuncout;
    Vtestrunner_filter_expression_parts__struct__0 parts;
    this->__VnoInFunc_get_filter_expression_parts(vlSymsp, raw_filter, __Vfunc_get_filter_expression_parts__1__Vfuncout);
    parts = __Vfunc_get_filter_expression_parts__1__Vfuncout;
    this->__VnoInFunc_get_subfilters(vlSymsp, VL_CVT_PACK_STR_NN(parts
                                                                 .__PVT__positive), __Vfunc_get_subfilters__2__Vfuncout);
    this->__PVT__positive_subfilters = __Vfunc_get_subfilters__2__Vfuncout;
    if ((std::string{""} != parts.__PVT__negative)) {
        this->__VnoInFunc_get_subfilters(vlSymsp, VL_CVT_PACK_STR_NN(parts
                                                                     .__PVT__negative), __Vfunc_get_subfilters__3__Vfuncout);
        this->__PVT__negative_subfilters = __Vfunc_get_subfilters__3__Vfuncout;
    }
}

void Vtestrunner_svunit_pkg__03a__03afilter::__VnoInFunc_get_filter_expression_parts(Vtestrunner__Syms* __restrict vlSymsp, std::string raw_filter, Vtestrunner_filter_expression_parts__struct__0 &get_filter_expression_parts__Vfuncrtn) {
    VL_DEBUG_IF(VL_DBG_MSGF("+              Vtestrunner_svunit_pkg__03a__03afilter::__VnoInFunc_get_filter_expression_parts\n"); );
    // Init
    VlQueue<std::string> __Vfunc_split_by_char__4__Vfuncout;
    // Body
    VlQueue<std::string> parts;
    {
        if ((0x2dU == VL_GETC_N(raw_filter,0U))) {
            raw_filter = VL_CONCATN_NNN(std::string{"*"}, raw_filter);
        }
        vlSymsp->TOP__svunit_pkg__03a__03astring_utils__Vclpkg.__VnoInFunc_split_by_char(vlSymsp, 
                                                                                std::string{"-"}, raw_filter, __Vfunc_split_by_char__4__Vfuncout);
        parts = __Vfunc_split_by_char__4__Vfuncout;
        if (VL_UNLIKELY(VL_LTS_III(32, 2U, parts.size()))) {
            VL_WRITEF("[%0t] %%Fatal: svunit_filter.svh:72: Assertion failed in %Nsvunit_pkg.filter.get_filter_expression_parts: Expected at most a single '-' character.\n",
                      64,VL_TIME_UNITED_Q(1),-12,vlSymsp->name());
            VL_STOP_MT("/space/projects/sv-json/contrib/svunit/svunit_base/svunit_filter.svh", 72, "");
        }
        if ((1U == parts.size())) {
            get_filter_expression_parts__Vfuncrtn = 
                Vtestrunner_filter_expression_parts__struct__0{
                .__PVT__positive = (QData)(parts.at(0U)), 
                .__PVT__negative = std::string{""}};
            goto __Vlabel1;
        }
        get_filter_expression_parts__Vfuncrtn = Vtestrunner_filter_expression_parts__struct__0{
            .__PVT__positive = (QData)(parts.at(0U)), 
            .__PVT__negative = (QData)(parts.at(1U))};
        __Vlabel1: ;
    }
}

void Vtestrunner_svunit_pkg__03a__03afilter::_ctor_var_reset(Vtestrunner__Syms* __restrict vlSymsp) {
    VL_DEBUG_IF(VL_DBG_MSGF("+              Vtestrunner_svunit_pkg__03a__03afilter::_ctor_var_reset\n"); );
    // Body
    if (false && vlSymsp) {}  // Prevent unused
    }

Verilator version: Verilator 5.020 2024-01-01 rev v5.020
However, I've tried more versions:

  • v5.012, v5.014, v5.016 - everything works fine
  • v5.018, v5.020, master 30e711a - get the issue above

OS: Ubuntu 22.04.4 LTS

@esynr3z esynr3z added the new New issue not seen by maintainers label Feb 24, 2024
@esynr3z
Copy link
Author

esynr3z commented Feb 24, 2024

@tudortimi you could be also interested in this

@wsnyder
Copy link
Member

wsnyder commented Feb 24, 2024

It's something related to setting positive/negative in the sources. Can you please take all of the relevant SVUnit verilog code going into verilator (e.g. run with debug and can likely use obj_dir/*__inputs.vpp to start what to feed into Verilator, and simplify as much as possible to recreate this?

@wsnyder wsnyder added status: asked reporter Bug is waiting for reporter to answer a question and removed new New issue not seen by maintainers labels Feb 24, 2024
@wsnyder
Copy link
Member

wsnyder commented Feb 24, 2024

P.S. Verilator is misinterpreting or not giving a lint error on code somewhere code like
reg [63:0] data;
struct ... { string positive; }
.... data = positive;

@esynr3z
Copy link
Author

esynr3z commented Feb 24, 2024

I've copypasted some code from svunit to create a reproducer.

test.sv
module test;

class filter_for_single_pattern;

  local static const string error_msg = "Expected the filter to be of the type '<test_case>.<test>[:<test_case>.<test>]'";

  local const string testcase;
  local const string test;


  function new(string pattern);
    int unsigned dot_idx = get_dot_idx(pattern);

    testcase = pattern.substr(0, dot_idx-1);
    disallow_partial_wildcards("testcase", testcase);

    test = pattern.substr(dot_idx+1, pattern.len()-1);
    disallow_partial_wildcards("test", test);
  endfunction


  local function int unsigned get_dot_idx(string pattern);
    int unsigned first_dot_idx = get_first_dot_idx(pattern);
    ensure_no_more_dots(pattern, first_dot_idx);
    return first_dot_idx;
  endfunction


  local function int unsigned get_first_dot_idx(string pattern);
    for (int i = 0; i < pattern.len(); i++)
      if (pattern[i] == ".")
        return i;
    $fatal(0, error_msg);
  endfunction


  local function void ensure_no_more_dots(string pattern, int unsigned first_dot_idx);
    for (int i = first_dot_idx+1; i < pattern.len(); i++)
      if (pattern[i] == ".")
        $fatal(0, error_msg);
  endfunction


  local function void disallow_partial_wildcards(string field_name, string field_value);
    if (field_value != "*")
      if (str_contains_char(field_value, "*"))
        $fatal(0, $sformatf("Partial wildcards in %s names aren't currently supported", field_name));
  endfunction


  local static function bit str_contains_char(string s, string c);
    if (c.len() != 1)
      $fatal(0, "Expected a single character");
    foreach (s[i])
      if (s[i] == c[0])
        return 1;
    return 0;
  endfunction


  local function bit is_match(string filter_val, string val);
    return (filter_val == "*") || (filter_val == val);
  endfunction

endclass


class string_utils;

  /* local */ typedef string array_of_string[];

  static function array_of_string split_by_char(string c, string s);
    string parts[$];
    int last_char_position = -1;

    if (c.len() != 1)
      $fatal(0, "Internal error: expected a single character string");

    for (int i = 0; i < s.len(); i++) begin
      if (i == s.len()-1)
        parts.push_back(s.substr(last_char_position+1, i));
      if (string'(s[i]) == c) begin
        parts.push_back(s.substr(last_char_position+1, i-1));
        last_char_position = i;
      end
    end

    return parts;
  endfunction

endclass

class filter;

  /* local */ typedef filter_for_single_pattern array_of_filters[];
  /* local */ typedef string array_of_string[];

  /* local */ typedef struct {
    string positive;
    string negative;
  } filter_expression_parts;


  local static filter single_instance;

  local const filter_for_single_pattern positive_subfilters[];
  local const filter_for_single_pattern negative_subfilters[];


  static function filter get();
    if (single_instance == null)
      single_instance = new();
    return single_instance;
  endfunction


  local function new();
    string raw_filter = get_filter_value_from_run_script();
    filter_expression_parts parts = get_filter_expression_parts(raw_filter);
    positive_subfilters = get_subfilters(parts.positive);
    if (parts.negative != "")
      negative_subfilters = get_subfilters(parts.negative);
  endfunction


  local function string get_filter_value_from_run_script();
    string result;
    if (!$value$plusargs("SVUNIT_FILTER=%s", result))
      result = "*";
    return result;
  endfunction


  local function filter_expression_parts get_filter_expression_parts(string raw_filter);
    string parts[];

    if (raw_filter[0] == "-")
      raw_filter = { "*", raw_filter };

    parts = string_utils::split_by_char("-", raw_filter);
    if (parts.size() > 2)
      $fatal(0, "Expected at most a single '-' character.");

    if (parts.size() == 1)
      return '{ parts[0], "" };
    return '{ parts[0], parts[1] };
  endfunction


  local function array_of_filters get_subfilters(string raw_filter);
    filter_for_single_pattern result[$];
    string patterns[];

    if (raw_filter == "*") begin
      filter_for_single_pattern filter_that_always_matches = new("*.*");
      return '{ filter_that_always_matches };
    end

    patterns = string_utils::split_by_char(":", raw_filter);
    foreach (patterns[i])
      result.push_back(get_subfilter_from_non_trivial_expr(patterns[i]));
    return result;
  endfunction


  local function filter_for_single_pattern get_subfilter_from_non_trivial_expr(string pattern);
    filter_for_single_pattern result;
    result = new(pattern);
    return result;
  endfunction


endclass

endmodule

How I run it:

verilator --binary test.sv && ./obj_dir/Vtest

Using this I get the same error. It is located within get_filter_expression_parts method, but SV code seems legit to me.

@wsnyder wsnyder added resolution: fixed Closed; fixed and removed status: asked reporter Bug is waiting for reporter to answer a question labels Feb 25, 2024
@wsnyder wsnyder closed this as completed Feb 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
resolution: fixed Closed; fixed
Projects
None yet
Development

No branches or pull requests

2 participants