From 390d1c583a4529bb190684ddbf18545e34c07663 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Tue, 14 Mar 2023 19:13:18 +0100 Subject: verific: Fix enum_values support and signed attribute values This uses the same constant parsing for enum_values and for attributes and extends it to handle signed values as those are used for enums that implicitly use the int type. --- frontends/verific/verific.cc | 67 ++++++++++++++++++++++---------------------- tests/verific/enum_values.sv | 37 ++++++++++++++++++++++++ tests/verific/enum_values.ys | 19 +++++++++++++ 3 files changed, 89 insertions(+), 34 deletions(-) create mode 100644 tests/verific/enum_values.sv create mode 100644 tests/verific/enum_values.ys diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index ab3e55427..605dcdfb2 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -200,14 +200,6 @@ RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj) return s; } -static bool isNumber(const string& str) -{ - for (auto &c : str) { - if (std::isdigit(c) == 0) return false; - } - return true; -} - // When used as attributes or parameter values Verific constants come already processed. // - Real string values are already under quotes // - Numeric values with specified width are always converted to binary @@ -215,19 +207,37 @@ static bool isNumber(const string& str) // - There could be some internal values that are strings without quotes // so we check if value is all digits or not // -static const RTLIL::Const verific_const(const char *value) +// Note: For signed values, verific uses 'sb and decimal values can +// also be negative. +static const RTLIL::Const verific_const(const char *value, bool allow_string = true, bool output_signed = false) { + size_t found; + char *end; + int decimal; + bool is_signed = false; + RTLIL::Const c; std::string val = std::string(value); - if (val.size()>1 && val[0]=='\"' && val.back()=='\"') - return RTLIL::Const(val.substr(1,val.size()-2)); - else - if (val.find("'b") != std::string::npos) - return RTLIL::Const::from_string(val.substr(val.find("'b") + 2)); - else - if (isNumber(val)) - return RTLIL::Const(std::stoi(val),32); - else - return RTLIL::Const(val); + if (allow_string && val.size()>1 && val[0]=='\"' && val.back()=='\"') { + c = RTLIL::Const(val.substr(1,val.size()-2)); + } else if ((found = val.find("'sb")) != std::string::npos) { + is_signed = output_signed; + c = RTLIL::Const::from_string(val.substr(found + 3)); + } else if ((found = val.find("'b")) != std::string::npos) { + c = RTLIL::Const::from_string(val.substr(found + 2)); + } else if ((value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) && + ((decimal = std::strtol(value, &end, 10)), !end[0])) { + is_signed = output_signed; + c = RTLIL::Const((int)decimal, 32); + } else if (allow_string) { + c = RTLIL::Const(val); + } else { + log_error("expected numeric constant but found '%s'", value); + } + + if (is_signed) + c.flags |= RTLIL::CONST_FLAG_SIGNED; + + return c; } void VerificImporter::import_attributes(dict &attributes, DesignObj *obj, Netlist *nl) @@ -263,21 +273,9 @@ void VerificImporter::import_attributes(dict &att const char *k, *v; FOREACH_MAP_ITEM(type_range->GetEnumIdMap(), mi, &k, &v) { if (nl->IsFromVerilog()) { - // Expect 'b - auto p = strchr(v, '\''); - if (p) { - if (*(p+1) != 'b') - p = nullptr; - else - for (auto q = p+2; *q != '\0'; q++) - if (*q != '0' && *q != '1' && *q != 'x' && *q != 'z') { - p = nullptr; - break; - } - } - if (p == nullptr) - log_error("Expected TypeRange value '%s' to be of form 'b.\n", v); - attributes.emplace(stringf("\\enum_value_%s", p+2), RTLIL::escape_id(k)); + auto const value = verific_const(v, false); + + attributes.emplace(stringf("\\enum_value_%s", value.as_string().c_str()), RTLIL::escape_id(k)); } #ifdef VERIFIC_VHDL_SUPPORT else if (nl->IsFromVhdl()) { @@ -1467,6 +1465,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma import_attributes(wire->attributes, net, nl); break; } + import_attributes(wire->attributes, netbus, nl); RTLIL::Const initval = Const(State::Sx, GetSize(wire)); bool initval_valid = false; diff --git a/tests/verific/enum_values.sv b/tests/verific/enum_values.sv new file mode 100644 index 000000000..69b53fd8e --- /dev/null +++ b/tests/verific/enum_values.sv @@ -0,0 +1,37 @@ +typedef enum { + WA, WB, WC, WD +} wide_state_t; + +typedef enum logic [1:0] { + A = 3, B = 0, C, D +} state_t; + +module top(input clk, output z); + + wide_state_t wide_state = WA; + + always @(posedge clk) begin + case (wide_state) + WA: wide_state <= WB; + WB: wide_state <= WC; + WC: wide_state <= WD; + default: wide_state <= WA; + endcase + end + + (* some_attribute = shortint'(42) *) + (* another_attribute = -1 *) + state_t state = A; + + always @(posedge clk) begin + case (state) + A: state <= B; + B: state <= C; + C: state <= D; + default: state <= A; + endcase + end + + assign z = (wide_state == WB) ^ (state == B); + +endmodule diff --git a/tests/verific/enum_values.ys b/tests/verific/enum_values.ys new file mode 100644 index 000000000..f580ded8a --- /dev/null +++ b/tests/verific/enum_values.ys @@ -0,0 +1,19 @@ +read -sv enum_values.sv +hierarchy -top top +printattrs a:* + +select -assert-count 1 a:some_attribute=16'd42 +# currently select doesn't support negative values in attributes +select -assert-count 1 a:another_attribute=32'hffffffff + +select -assert-count 1 top/state a:wiretype=\state_t %i +select -assert-count 1 top/state a:enum_value_11=\A %i +select -assert-count 1 top/state a:enum_value_00=\B %i +select -assert-count 1 top/state a:enum_value_01=\C %i +select -assert-count 1 top/state a:enum_value_10=\D %i + +select -assert-count 1 top/wide_state a:wiretype=\wide_state_t %i +select -assert-count 1 top/wide_state a:enum_value_00000000000000000000000000000000=\WA %i +select -assert-count 1 top/wide_state a:enum_value_00000000000000000000000000000001=\WB %i +select -assert-count 1 top/wide_state a:enum_value_00000000000000000000000000000010=\WC %i +select -assert-count 1 top/wide_state a:enum_value_00000000000000000000000000000011=\WD %i -- cgit v1.2.3