Fix inconsistent naming of generate scope arrays (#3840)

This commit is contained in:
Andrew Nolte 2023-02-01 17:30:02 -05:00 committed by GitHub
parent ef9f443532
commit 18e317fb78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 115 additions and 13 deletions

View File

@ -158,7 +158,6 @@ string AstNode::vcdName(const string& namein) {
string AstNode::prettyName(const string& namein) {
// This function is somewhat hot, so we short-circuit some compares
string pretty;
pretty = "";
pretty.reserve(namein.length());
for (const char* pos = namein.c_str(); *pos;) {
if (pos[0] == '-' && pos[1] == '>') { // ->
@ -206,6 +205,78 @@ string AstNode::prettyName(const string& namein) {
return pretty;
}
string AstNode::vpiName(const string& namein) {
// This is slightly different from prettyName, in that when we encounter escaped characters,
// we change that identifier to an escaped identifier, wrapping it with '\' and ' '
// as specified in LRM 23.6
string pretty;
pretty.reserve(namein.length());
bool inEscapedIdent = false;
int lastIdent = 0;
for (const char* pos = namein.c_str(); *pos;) {
char specialChar = 0;
if (pos[0] == '-' && pos[1] == '>') { // ->
specialChar = '.';
pos += 2;
} else if (pos[0] == '_' && pos[1] == '_') { // __
if (0 == std::strncmp(pos, "__BRA__", 7)) {
specialChar = '[';
pos += 7;
} else if (0 == std::strncmp(pos, "__KET__", 7)) {
specialChar = ']';
pos += 7;
} else if (0 == std::strncmp(pos, "__DOT__", 7)) {
specialChar = '.';
pos += 7;
} else if (0 == std::strncmp(pos, "__PVT__", 7)) {
pos += 7;
continue;
} else if (pos[0] == '_' && pos[1] == '_' && pos[2] == '0' && isxdigit(pos[3])
&& isxdigit(pos[4])) {
char value = 0;
value += 16 * (isdigit(pos[3]) ? (pos[3] - '0') : (tolower(pos[3]) - 'a' + 10));
value += (isdigit(pos[4]) ? (pos[4] - '0') : (tolower(pos[4]) - 'a' + 10));
// __ doesn't always imply escaped ident
if (value != '_') inEscapedIdent = true;
pretty += value;
pos += 5;
continue;
}
} else if (pos[0] == '.') {
specialChar = '.';
++pos;
}
if (specialChar) {
if (inEscapedIdent && (specialChar == '[' || specialChar == '.')) {
pretty += " ";
pretty.insert(lastIdent, "\\");
inEscapedIdent = false;
}
pretty += specialChar;
if (specialChar == ']' || specialChar == '.') {
lastIdent = pretty.length();
inEscapedIdent = false;
}
} else {
pretty += pos[0];
++pos;
}
}
if (inEscapedIdent) {
pretty += " ";
pretty.insert(lastIdent, "\\");
}
if (pretty[0] == 'T' && pretty.substr(0, 4) == "TOP.") pretty.replace(0, 4, "");
if (pretty[0] == 'T' && pretty.substr(0, 5) == "TOP->") pretty.replace(0, 5, "");
return pretty;
}
string AstNode::prettyTypeName() const {
if (name() == "") return typeName();
return std::string{typeName()} + " '" + prettyName() + "'";

View File

@ -1666,6 +1666,7 @@ public:
string shortName() const; // Name with __PVT__ removed for concatenating scopes
static string dedotName(const string& namein); // Name with dots removed
static string prettyName(const string& namein); // Name for printing out to the user
static string vpiName(const string& namein); // Name for vpi access
static string prettyNameQ(const string& namein) { // Quoted pretty name (for errors)
return std::string{"'"} + prettyName(namein) + "'";
}

View File

@ -156,6 +156,22 @@ class EmitCSyms final : EmitCBaseVisitor {
string out = scpname;
// Remove hierarchy
string::size_type pos = out.rfind('.');
// If there's more than one ident and an escape, find the true last ident
if (pos != string::npos && scpname.find('\\') != string::npos) {
size_t i = 0;
// always makes progress
while (i < scpname.length()) {
if (scpname[i] == '\\') {
while (i < scpname.length() && scpname[i] != ' ') ++i;
++i; // Proc ' ', it should always be there. Then grab '.' on next cycle
} else {
while (i < scpname.length() && scpname[i] != '.') ++i;
if (i < scpname.length()) { pos = i++; }
}
}
}
if (pos != std::string::npos) out.erase(0, pos + 1);
// Decode all escaped characters
while ((pos = out.find("__0")) != string::npos) {
@ -296,10 +312,10 @@ class EmitCSyms final : EmitCBaseVisitor {
const string type
= (nodep->origModName() == "__BEGIN__") ? "SCOPE_OTHER" : "SCOPE_MODULE";
const string name = nodep->scopep()->shortName() + "__DOT__" + nodep->name();
const string name_dedot = AstNode::dedotName(name);
const string name_pretty = AstNode::vpiName(name);
const int timeunit = m_modp->timeunit().powerOfTen();
m_vpiScopeCandidates.insert(
std::make_pair(name, ScopeData(scopeSymString(name), name_dedot, timeunit, type)));
m_vpiScopeCandidates.insert(std::make_pair(
name, ScopeData(scopeSymString(name), name_pretty, timeunit, type)));
}
}
void visit(AstScope* nodep) override {
@ -310,10 +326,10 @@ class EmitCSyms final : EmitCBaseVisitor {
if (v3Global.opt.vpi() && !nodep->isTop()) {
const string type = VN_IS(nodep->modp(), Package) ? "SCOPE_OTHER" : "SCOPE_MODULE";
const string name_dedot = AstNode::dedotName(nodep->shortName());
const string name_pretty = AstNode::vpiName(nodep->shortName());
const int timeunit = m_modp->timeunit().powerOfTen();
m_vpiScopeCandidates.insert(
std::make_pair(nodep->name(), ScopeData(scopeSymString(nodep->name()), name_dedot,
std::make_pair(nodep->name(), ScopeData(scopeSymString(nodep->name()), name_pretty,
timeunit, type)));
}
}

View File

@ -120,7 +120,7 @@ int mon_check() {
CHECK_RESULT_NZ(mod2);
const char* mod_a_name = vpi_get_str(vpiName, mod2);
CHECK_RESULT_CSTR(mod_a_name, "mod_a");
CHECK_RESULT_CSTR(mod_a_name, "\\mod.a ");
TestVpiHandle it3 = vpi_iterate(vpiModule, mod2);
CHECK_RESULT_NZ(it3);
@ -129,13 +129,13 @@ int mon_check() {
CHECK_RESULT_NZ(mod3);
const char* mod_c_name = vpi_get_str(vpiName, mod3);
if (std::strcmp(mod_c_name, "mod_b") == 0) {
if (std::strcmp(mod_c_name, "\\mod_b$ ") == 0) {
// Full visibility in other simulators, skip mod_b
TestVpiHandle mod4 = vpi_scan(it3);
CHECK_RESULT_NZ(mod4);
mod_c_name = vpi_get_str(vpiName, mod4);
}
CHECK_RESULT_CSTR(mod_c_name, "mod_c.");
CHECK_RESULT_CSTR(mod_c_name, "\\mod\\c$ ");
return 0; // Ok
}

View File

@ -31,7 +31,7 @@ extern "C" int mon_check();
wire a, b, x;
A mod_a(/*AUTOINST*/
A \mod.a (/*AUTOINST*/
// Outputs
.x (x),
// Inputs
@ -72,14 +72,14 @@ module A(/*AUTOARG*/
wire y, c;
B mod_b(/*AUTOINST*/
B \mod_b$ (/*AUTOINST*/
// Outputs
.y (y),
// Inputs
.b (b),
.c (c));
C \mod_c. (/*AUTOINST*/
C \mod\c$ (/*AUTOINST*/
// Outputs
.x (x),
// Inputs

View File

@ -648,6 +648,12 @@ int _mon_check_putget_str(p_cb_data cb_data) {
= vpi_handle_by_name((PLI_BYTE8*)"verbose", data[i].scope));
}
for (int i = 1; i <= 6; i++) {
char buf[32];
snprintf(buf, sizeof(buf), TestSimulator::rooted("subs[%d].subsub"), i);
CHECK_RESULT_NZ(data[i].scope = vpi_handle_by_name((PLI_BYTE8*)buf, NULL));
}
static t_cb_data cb_data;
static s_vpi_value v;
TestVpiHandle count_h = VPI_HANDLE("count");

View File

@ -95,7 +95,15 @@ extern "C" int mon_check();
generate
for (i=1; i<=6; i=i+1) begin : arr
arr #(.LENGTH(i)) arr();
end endgenerate
end
endgenerate
genvar k;
generate
for (k=1; k<=6; k=k+1) begin : subs
sub subsub();
end
endgenerate
endmodule : t