Skip to content

Commit a1fa854

Browse files
authored
Merge pull request #167 from Silimate/union-struct
[CUS-538] - $fork scope union struct support
2 parents 69edb27 + 367af96 commit a1fa854

2 files changed

Lines changed: 93 additions & 49 deletions

File tree

kernel/fstdata.cc

Lines changed: 92 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -109,18 +109,108 @@ static std::string remove_spaces(std::string str)
109109
return str;
110110
}
111111

112+
void FstData::registerVar(const FstVar &var)
113+
{
114+
vars.push_back(var);
115+
if (!var.is_alias)
116+
handle_to_var[var.id] = var;
117+
118+
std::string clean_name = var.name;
119+
if (!clean_name.empty() && clean_name[0] == '\\')
120+
clean_name = clean_name.substr(1);
121+
122+
// Strip trailing bit range [N:M] if present
123+
if (!clean_name.empty() && clean_name.back() == ']') {
124+
size_t open = clean_name.rfind('[');
125+
if (open != std::string::npos) {
126+
std::string inner = clean_name.substr(open + 1, clean_name.size() - open - 2);
127+
if (inner.find(':') != std::string::npos)
128+
clean_name.erase(open);
129+
}
130+
}
131+
132+
// Handle memory addresses
133+
size_t pos = clean_name.find_last_of("<");
134+
if (pos != std::string::npos && clean_name.back() == '>') {
135+
std::string mem_cell = clean_name.substr(0, pos);
136+
normalize_brackets(mem_cell);
137+
std::string addr = clean_name.substr(pos+1);
138+
addr.pop_back(); // remove closing bracket
139+
char *endptr;
140+
int mem_addr = strtol(addr.c_str(), &endptr, 16);
141+
if (*endptr) {
142+
log_debug("Error parsing memory address in : %s\n", clean_name);
143+
} else {
144+
memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id;
145+
}
146+
}
147+
pos = clean_name.find_last_of("[");
148+
if (pos != std::string::npos && clean_name.back() == ']') {
149+
std::string mem_cell = clean_name.substr(0, pos);
150+
normalize_brackets(mem_cell);
151+
std::string addr = clean_name.substr(pos+1);
152+
addr.pop_back(); // remove closing bracket
153+
char *endptr;
154+
int mem_addr = strtol(addr.c_str(), &endptr, 10);
155+
if (*endptr) {
156+
log_debug("Error parsing memory address in : %s\n", clean_name);
157+
} else {
158+
memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id;
159+
}
160+
}
161+
normalize_brackets(clean_name);
162+
name_to_handle[var.scope+"."+clean_name] = var.id;
163+
}
164+
112165
void FstData::extractVarNames()
113166
{
114167
struct fstHier *h;
115168
std::string fst_scope_name;
116169

170+
/* Variables for resolving unions with $fork. */
171+
bool in_fork = false; // if we are inside a $fork scope
172+
std::string fork_parent_scope; // parent scope of fork (used to resolve union location)
173+
std::string fork_name; // name of fork (used to resolve union name)
174+
std::vector<FstVar> fork_vars; // stores all variables in the fork scope
175+
117176
while ((h = fstReaderIterateHier(ctx))) {
118177
switch (h->htyp) {
119178
case FST_HT_SCOPE: {
179+
// Handle tracking for potential union structs with $fork.
180+
if (!in_fork && h->u.scope.typ == FST_ST_VCD_FORK) {
181+
in_fork = true;
182+
fork_parent_scope = fst_scope_name;
183+
fork_name = h->u.scope.name;
184+
fork_vars.clear();
185+
}
186+
// Push the scope onto the stack to 'descend' into the hierarchy.
120187
fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, NULL);
121188
break;
122189
}
123190
case FST_HT_UPSCOPE: {
191+
if (in_fork) {
192+
// A union is detected if there are at least 2 variables in the fork scope and they all have the same fstHandle.
193+
bool is_union = fork_vars.size() >= 2 &&
194+
std::all_of(fork_vars.begin() + 1, fork_vars.end(),
195+
[&](const FstVar &v) { return v.id == fork_vars[0].id; });
196+
if (is_union) {
197+
// If a union, register the fork name as the variable at the parent scope.
198+
FstVar u = fork_vars[0];
199+
u.name = fork_name;
200+
u.scope = fork_parent_scope;
201+
normalize_brackets(u.scope);
202+
u.is_alias = false;
203+
registerVar(u);
204+
} else {
205+
// If not a union, register all variables in the fork scope as normal.
206+
for (auto &v : fork_vars) {
207+
registerVar(v);
208+
}
209+
}
210+
in_fork = false;
211+
fork_vars.clear();
212+
}
213+
// Pop the scope off the stack.
124214
fst_scope_name = fstReaderPopScope(ctx);
125215
break;
126216
}
@@ -133,62 +223,15 @@ void FstData::extractVarNames()
133223
var.scope = fst_scope_name;
134224
normalize_brackets(var.scope);
135225
var.width = h->u.var.length;
136-
vars.push_back(var);
137-
if (!var.is_alias)
138-
handle_to_var[h->u.var.handle] = var;
139-
140-
std::string clean_name = var.name;
141-
if (!clean_name.empty() && clean_name[0] == '\\')
142-
clean_name = clean_name.substr(1);
143-
144-
// Strip trailing bit range [N:M] if present
145-
if (!clean_name.empty() && clean_name.back() == ']') {
146-
size_t open = clean_name.rfind('[');
147-
if (open != std::string::npos) {
148-
std::string inner = clean_name.substr(open + 1, clean_name.size() - open - 2);
149-
if (inner.find(':') != std::string::npos)
150-
clean_name.erase(open);
151-
}
152-
}
153226

154-
// Handle memory addresses
155-
size_t pos = clean_name.find_last_of("<");
156-
if (pos != std::string::npos && clean_name.back() == '>') {
157-
std::string mem_cell = clean_name.substr(0, pos);
158-
normalize_brackets(mem_cell);
159-
std::string addr = clean_name.substr(pos+1);
160-
addr.pop_back(); // remove closing bracket
161-
char *endptr;
162-
int mem_addr = strtol(addr.c_str(), &endptr, 16);
163-
if (*endptr) {
164-
log_debug("Error parsing memory address in : %s\n", clean_name);
165-
} else {
166-
memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id;
167-
}
168-
}
169-
pos = clean_name.find_last_of("[");
170-
if (pos != std::string::npos && clean_name.back() == ']') {
171-
std::string mem_cell = clean_name.substr(0, pos);
172-
normalize_brackets(mem_cell);
173-
std::string addr = clean_name.substr(pos+1);
174-
addr.pop_back(); // remove closing bracket
175-
char *endptr;
176-
int mem_addr = strtol(addr.c_str(), &endptr, 10);
177-
if (*endptr) {
178-
log_debug("Error parsing memory address in : %s\n", clean_name);
179-
} else {
180-
memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id;
181-
}
182-
}
183-
normalize_brackets(clean_name);
184-
name_to_handle[var.scope+"."+clean_name] = h->u.var.handle;
227+
if (in_fork) fork_vars.push_back(var); // store all variables in fork scope into a vector
228+
else registerVar(var); // otherwise, register the variable as normal
185229
break;
186230
}
187231
}
188232
}
189233
}
190234

191-
192235
static void reconstruct_clb_varlen_attimes(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen)
193236
{
194237
FstData *ptr = (FstData*)user_data;

kernel/fstdata.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class FstData
6161
std::string autoScope(Module *topmod);
6262
private:
6363
void extractVarNames();
64+
void registerVar(const FstVar &var);
6465

6566
struct fstReaderContext *ctx;
6667
std::vector<FstVar> vars;

0 commit comments

Comments
 (0)