3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-05-10 17:25:49 +00:00

ast: add GC for dev debugging

This commit is contained in:
Emil J. Tywoniak 2025-04-25 00:49:37 +02:00
parent 272b7fa697
commit d8cae1d904
3 changed files with 104 additions and 0 deletions

View file

@ -248,6 +248,9 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
children.push_back(child4);
fixup_hierarchy_flags();
#ifdef ASTNODE_GC
Tagger::get().reg(this);
#endif
}
// create a (deep recursive) copy of a node
@ -283,12 +286,28 @@ void AstNode::cloneInto(AstNode *other) const
// delete all children in this node
void AstNode::delete_children()
{
#ifdef ASTNODE_GC
for (auto &it : children)
if (Tagger::get().nodes.count(it))
delete it;
else
log("skip child %p\n", it);
#else
for (auto &it : children)
delete it;
#endif
children.clear();
#ifdef ASTNODE_GC
for (auto &it : attributes)
if (Tagger::get().nodes.count(it.second))
delete it.second;
else
log("skip attr %p\n", it.second);
#else
for (auto &it : attributes)
delete it.second;
#endif
attributes.clear();
}
@ -296,7 +315,14 @@ void AstNode::delete_children()
AstNode::~AstNode()
{
astnodes--;
#ifdef ASTNODE_GC
Tagger::get().unreg(this);
#endif
delete_children();
if (yosys_xtrace) {
log("DESTR %X %p\n", hashidx_, this);
log_backtrace("", yosys_xtrace-1);
}
}
// create a nice text representation of the node

View file

@ -467,6 +467,72 @@ namespace AST_INTERNAL
AST::AstNode *original_ast = nullptr);
}
#undef ASTNODE_GC
#ifdef ASTNODE_GC
struct Tagger {
std::set<AST::AstNode*> nodes;
std::set<AST::AstNode*> tagged;
static Tagger& get() {
static Tagger instance;
return instance;
}
void reg(AST::AstNode* p) {
if (!p)
return;
log_assert(!nodes.count(p));
nodes.insert(p);
}
void unreg(AST::AstNode* p) {
if (!p || !nodes.count(p))
return;
nodes.erase(p);
}
void tag(AST::AstNode* p) {
if (!p)
return;
tagged.insert(p);
for (AST::AstNode* c : p->children)
tag(c);
for (auto x : p->attributes)
tag(x.second);
tag(p->id2ast);
}
void clear() {
tagged.clear();
}
void dump_untagged() {
Yosys::log("Dumping untagged:\n");
for (auto p : nodes) {
if (!tagged.count(p)) {
Yosys::log(">> %p\n", p);
p->dumpAst(stdout, "");
}
}
}
void shadow_kill(AST::AstNode* p) {
if (!p || !nodes.count(p))
return;
for (AST::AstNode* c : p->children)
shadow_kill(c);
for (auto x : p->attributes)
shadow_kill(x.second);
shadow_kill(p->id2ast);
delete p;
}
void kill_untagged() {
auto copy = nodes;
while (!copy.empty()) {
AST::AstNode* p = *(copy.begin());
copy.erase(p);
fflush(stdout);
if (!tagged.count(p)) {
shadow_kill(p);
}
}
}
};
#endif // ASTNODE_GC
YOSYS_NAMESPACE_END
#endif

View file

@ -39,6 +39,7 @@
YOSYS_NAMESPACE_BEGIN
using namespace VERILOG_FRONTEND;
// use the Verilog bison/flex parser to generate an AST and use AST::process() to convert it to RTLIL
static std::vector<std::string> verilog_defaults;
@ -528,7 +529,15 @@ struct VerilogFrontend : public Frontend {
AST::process(design, current_ast, flag_nodisplay, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches,
flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
#ifdef ASTNODE_GC
Tagger::get().clear();
Tagger::get().tag(current_ast);
for (RTLIL::Module* m : design->modules())
if (AST::AstModule* am = dynamic_cast<AST::AstModule*>(m))
Tagger::get().tag(am->ast);
Tagger::get().dump_untagged();
#endif
if (!flag_nopp)
delete lexin;
@ -539,6 +548,9 @@ struct VerilogFrontend : public Frontend {
delete current_ast;
current_ast = NULL;
#ifdef ASTNODE_GC
Tagger::get().kill_untagged();
#endif
log("Successfully finished Verilog frontend.\n");
}