aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJannis Harder <me@jix.one>2023-03-14 19:13:18 +0100
committerJannis Harder <me@jix.one>2023-03-15 09:51:36 +0100
commit390d1c583a4529bb190684ddbf18545e34c07663 (patch)
tree45f4a9d8c19c78351958f3e0991e08a670741153
parentc50f641812deed626bc9ecbfe171f56f36bf8432 (diff)
downloadyosys-390d1c583a4529bb190684ddbf18545e34c07663.tar.gz
yosys-390d1c583a4529bb190684ddbf18545e34c07663.tar.bz2
yosys-390d1c583a4529bb190684ddbf18545e34c07663.zip
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.
-rw-r--r--frontends/verific/verific.cc67
-rw-r--r--tests/verific/enum_values.sv37
-rw-r--r--tests/verific/enum_values.ys19
3 files changed, 89 insertions, 34 deletions
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 <len>'sb<bits> 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<RTLIL::IdString, RTLIL::Const> &attributes, DesignObj *obj, Netlist *nl)
@@ -263,21 +273,9 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
const char *k, *v;
FOREACH_MAP_ITEM(type_range->GetEnumIdMap(), mi, &k, &v) {
if (nl->IsFromVerilog()) {
- // Expect <decimal>'b<binary>
- 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 <decimal>'b<binary>.\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