mirror of https://github.com/YosysHQ/yosys.git
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.
This commit is contained in:
parent
c50f641812
commit
390d1c583a
|
@ -200,14 +200,6 @@ RTLIL::IdString VerificImporter::new_verific_id(Verific::DesignObj *obj)
|
||||||
return s;
|
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.
|
// When used as attributes or parameter values Verific constants come already processed.
|
||||||
// - Real string values are already under quotes
|
// - Real string values are already under quotes
|
||||||
// - Numeric values with specified width are always converted to binary
|
// - 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
|
// - There could be some internal values that are strings without quotes
|
||||||
// so we check if value is all digits or not
|
// 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);
|
std::string val = std::string(value);
|
||||||
if (val.size()>1 && val[0]=='\"' && val.back()=='\"')
|
if (allow_string && val.size()>1 && val[0]=='\"' && val.back()=='\"') {
|
||||||
return RTLIL::Const(val.substr(1,val.size()-2));
|
c = RTLIL::Const(val.substr(1,val.size()-2));
|
||||||
else
|
} else if ((found = val.find("'sb")) != std::string::npos) {
|
||||||
if (val.find("'b") != std::string::npos)
|
is_signed = output_signed;
|
||||||
return RTLIL::Const::from_string(val.substr(val.find("'b") + 2));
|
c = RTLIL::Const::from_string(val.substr(found + 3));
|
||||||
else
|
} else if ((found = val.find("'b")) != std::string::npos) {
|
||||||
if (isNumber(val))
|
c = RTLIL::Const::from_string(val.substr(found + 2));
|
||||||
return RTLIL::Const(std::stoi(val),32);
|
} else if ((value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) &&
|
||||||
else
|
((decimal = std::strtol(value, &end, 10)), !end[0])) {
|
||||||
return RTLIL::Const(val);
|
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)
|
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;
|
const char *k, *v;
|
||||||
FOREACH_MAP_ITEM(type_range->GetEnumIdMap(), mi, &k, &v) {
|
FOREACH_MAP_ITEM(type_range->GetEnumIdMap(), mi, &k, &v) {
|
||||||
if (nl->IsFromVerilog()) {
|
if (nl->IsFromVerilog()) {
|
||||||
// Expect <decimal>'b<binary>
|
auto const value = verific_const(v, false);
|
||||||
auto p = strchr(v, '\'');
|
|
||||||
if (p) {
|
attributes.emplace(stringf("\\enum_value_%s", value.as_string().c_str()), RTLIL::escape_id(k));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
#ifdef VERIFIC_VHDL_SUPPORT
|
#ifdef VERIFIC_VHDL_SUPPORT
|
||||||
else if (nl->IsFromVhdl()) {
|
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);
|
import_attributes(wire->attributes, net, nl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
import_attributes(wire->attributes, netbus, nl);
|
||||||
|
|
||||||
RTLIL::Const initval = Const(State::Sx, GetSize(wire));
|
RTLIL::Const initval = Const(State::Sx, GetSize(wire));
|
||||||
bool initval_valid = false;
|
bool initval_valid = false;
|
||||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue