Skip non-synthesizable objects (#243)
* Skip non-synthesizable objects
Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
* Add check for case node
Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
* Add AST_BLOCK if not present in initial
Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
* Add AST_BLOCK if stmt is missing in always
Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
* Add AST_BLOCK if stmt is missing in initial
Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
* Check if node is present in hier_path
Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
* Check for node in if_else
Signed-off-by: Kamil Rakoczy <krakoczy@antmicro.com>
* Rely on UHDM's SynthSubset to filter out non-synthesizables
Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
Co-authored-by: Krzysztof Bieganski <kbieganski@antmicro.com>
diff --git a/systemverilog-plugin/UhdmAst.cc b/systemverilog-plugin/UhdmAst.cc
index 46a91f8..7f1d2b3 100644
--- a/systemverilog-plugin/UhdmAst.cc
+++ b/systemverilog-plugin/UhdmAst.cc
@@ -1376,7 +1376,12 @@
if (initial_node_it != parent->children.end()) {
AST::AstNode *initial_node = *initial_node_it;
- log_assert(!(initial_node->children.empty()));
+ // simplify assumes that initial has a block under it
+ // In case we don't have one (there were no statements under the initial), let's add it
+ if (initial_node->children.empty()) {
+ initial_node->children.push_back(new AST::AstNode(AST::AST_BLOCK));
+ }
+
log_assert(initial_node->children[0]->type == AST::AST_BLOCK);
log_assert(!(child->children.empty()));
log_assert(child->children[0]->type == AST::AST_BLOCK);
@@ -2471,13 +2476,18 @@
{
current_node = make_ast_node(AST::AST_ALWAYS);
visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
- AST::AstNode *block = nullptr;
- if (node && node->type != AST::AST_BLOCK) {
- block = new AST::AstNode(AST::AST_BLOCK, node);
+ if (node) {
+ AST::AstNode *block = nullptr;
+ if (node->type != AST::AST_BLOCK) {
+ block = new AST::AstNode(AST::AST_BLOCK, node);
+ } else {
+ block = node;
+ }
+ current_node->children.push_back(block);
} else {
- block = node;
+ // create empty block
+ current_node->children.push_back(new AST::AstNode(AST::AST_BLOCK));
}
- current_node->children.push_back(block);
});
switch (vpi_get(vpiAlwaysType, obj_h)) {
case vpiAlwaysComb:
@@ -2525,6 +2535,8 @@
node = block_node;
}
current_node->children.push_back(node);
+ } else {
+ current_node->children.push_back(make_ast_node(AST::AST_BLOCK));
}
});
}
@@ -3104,7 +3116,8 @@
condition->children.push_back(constant);
visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
auto *statements = new AST::AstNode(AST::AST_BLOCK);
- statements->children.push_back(node);
+ if (node)
+ statements->children.push_back(node);
condition->children.push_back(statements);
});
current_node->children.push_back(condition);
@@ -3115,7 +3128,8 @@
condition->children.push_back(elseBlock);
visit_one_to_one({vpiElseStmt}, obj_h, [&](AST::AstNode *node) {
auto *statements = new AST::AstNode(AST::AST_BLOCK);
- statements->children.push_back(node);
+ if (node)
+ statements->children.push_back(node);
condition->children.push_back(statements);
});
current_node->children.push_back(condition);
@@ -3224,12 +3238,14 @@
current_node->children.push_back(new AST::AstNode(AST::AST_DEFAULT));
}
visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
- if (node->type != AST::AST_BLOCK) {
- auto block_node = new AST::AstNode(AST::AST_BLOCK);
- block_node->children.push_back(node);
- node = block_node;
+ if (node) {
+ if (node->type != AST::AST_BLOCK) {
+ auto block_node = new AST::AstNode(AST::AST_BLOCK);
+ block_node->children.push_back(node);
+ node = block_node;
+ }
+ current_node->children.push_back(node);
}
- current_node->children.push_back(node);
});
}
@@ -3307,22 +3323,24 @@
current_node->str = "\\";
AST::AstNode *top_node = nullptr;
visit_one_to_many({vpiActual}, obj_h, [&](AST::AstNode *node) {
- if (node->str.find('[') != std::string::npos)
- node->str = node->str.substr(0, node->str.find('['));
- // for first node, just set correct string and move any children
- if (!top_node) {
- current_node->str += node->str.substr(1);
- current_node->children = std::move(node->children);
- top_node = current_node;
- delete node;
- } else {
- if (node->str.empty()) {
- log_assert(!node->children.empty());
- top_node->children.push_back(node->children[0]);
+ if (node) {
+ if (node->str.find('[') != std::string::npos)
+ node->str = node->str.substr(0, node->str.find('['));
+ // for first node, just set correct string and move any children
+ if (!top_node) {
+ current_node->str += node->str.substr(1);
+ current_node->children = std::move(node->children);
+ top_node = current_node;
+ delete node;
} else {
- node->type = static_cast<AST::AstNodeType>(AST::AST_DOT);
- top_node->children.push_back(node);
- top_node = node;
+ if (node->str.empty()) {
+ log_assert(!node->children.empty());
+ top_node->children.push_back(node->children[0]);
+ } else {
+ node->type = static_cast<AST::AstNodeType>(AST::AST_DOT);
+ top_node->children.push_back(node);
+ top_node = node;
+ }
}
}
});
@@ -3435,20 +3453,6 @@
{
current_node = make_ast_node(AST::AST_FCALL);
- // skip unsupported simulation functions
- std::string to_skip[] = {
- "\\$value$plusargs", "\\$test$plusargs", "\\$displayb", "\\$displayh", "\\$displayo", "\\$strobeb", "\\$strobeh", "\\$strobeo",
- "\\$writeb", "\\$writeh", "\\$writeo", "\\$dumplimit", "\\$dumpflush", "\\$fdisplay", "\\$fdisplayb", "\\$fdisplayh",
- "\\$fdisplayo", "\\$fmonitor", "\\$fstrobe", "\\$fstrobeb", "\\$fstrobeh", "\\$fstrobeo", "\\$fwrite", "\\$fwriteb",
- "\\$fwriteh", "\\$fwriteo", "\\$ungetc", "\\$fgetc", "\\$fgets", "\\$ftell", "\\$printtimescale"};
-
- if (std::find(std::begin(to_skip), std::end(to_skip), current_node->str) != std::end(to_skip)) {
- log_warning("System function %s was skipped\n", current_node->str.substr(1).c_str());
- delete current_node;
- current_node = nullptr;
- return;
- }
-
std::string task_calls[] = {"\\$display", "\\$monitor", "\\$write", "\\$time", "\\$readmemh", "\\$readmemb", "\\$finish", "\\$stop"};
if (current_node->str == "\\$signed") {
@@ -3503,16 +3507,6 @@
});
}
-void UhdmAst::process_nonsynthesizable(const UHDM::BaseClass *object)
-{
- log_warning("%s:%d: Non-synthesizable object of type '%s'\n", object->VpiFile().c_str(), object->VpiLineNo(), UHDM::VpiTypeName(obj_h).c_str());
- current_node = make_ast_node(AST::AST_BLOCK);
- visit_one_to_one({vpiStmt}, obj_h, [&](AST::AstNode *node) {
- if (node)
- current_node->children.push_back(node);
- });
-}
-
void UhdmAst::process_logic_typespec()
{
current_node = make_ast_node(AST::AST_WIRE);
@@ -4040,6 +4034,13 @@
const unsigned object_type = vpi_get(vpiType, obj_h);
const uhdm_handle *const handle = (const uhdm_handle *)obj_h;
const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
+ for (auto *obj : shared.nonSynthesizableObjects) {
+ if (!object->Compare(obj)) {
+ log_warning("%s:%d: Skipping non-synthesizable object of type '%s'\n", object->VpiFile().c_str(), object->VpiLineNo(),
+ UHDM::VpiTypeName(obj_h).c_str());
+ return nullptr;
+ }
+ }
if (shared.debug_flag) {
std::cout << indent << "Object '" << object->VpiName() << "' of type '" << UHDM::VpiTypeName(obj_h) << '\'' << std::endl;
@@ -4236,9 +4237,6 @@
break;
case UHDM::uhdmimport_typespec:
break;
- case vpiDelayControl:
- process_nonsynthesizable(object);
- break;
case vpiLogicTypespec:
process_logic_typespec();
break;
diff --git a/systemverilog-plugin/UhdmAst.h b/systemverilog-plugin/UhdmAst.h
index 8f6a368..b7877a6 100644
--- a/systemverilog-plugin/UhdmAst.h
+++ b/systemverilog-plugin/UhdmAst.h
@@ -148,7 +148,6 @@
void process_gate();
void process_primterm();
void simplify_parameter(AST::AstNode *parameter, AST::AstNode *module_node = nullptr);
- void process_nonsynthesizable(const UHDM::BaseClass *object);
void process_unsupported_stmt(const UHDM::BaseClass *object);
UhdmAst(UhdmAst *p, UhdmAstShared &s, const std::string &i) : parent(p), shared(s), indent(i)
diff --git a/systemverilog-plugin/uhdmastfrontend.cc b/systemverilog-plugin/uhdmastfrontend.cc
index 4874ee8..c09688c 100644
--- a/systemverilog-plugin/uhdmastfrontend.cc
+++ b/systemverilog-plugin/uhdmastfrontend.cc
@@ -44,6 +44,9 @@
UHDM::Serializer serializer;
std::vector<vpiHandle> restoredDesigns = serializer.Restore(filename);
+ UHDM::SynthSubset *synthSubset = new UHDM::SynthSubset(&serializer, this->shared.nonSynthesizableObjects, false);
+ synthSubset->listenDesigns(restoredDesigns);
+ delete synthSubset;
if (this->shared.debug_flag || !this->report_directory.empty()) {
for (auto design : restoredDesigns) {
std::stringstream strstr;
diff --git a/systemverilog-plugin/uhdmastshared.h b/systemverilog-plugin/uhdmastshared.h
index 9799055..2fa3e8b 100644
--- a/systemverilog-plugin/uhdmastshared.h
+++ b/systemverilog-plugin/uhdmastshared.h
@@ -52,6 +52,8 @@
std::unordered_map<std::string, AST::AstNode *> param_types;
AST::AstNode *current_top_node = nullptr;
+ // Set of non-synthesizable objects to skip in current design;
+ std::set<const UHDM::BaseClass *> nonSynthesizableObjects;
};
YOSYS_NAMESPACE_END
diff --git a/systemverilog-plugin/uhdmcommonfrontend.h b/systemverilog-plugin/uhdmcommonfrontend.h
index 6fcb0f9..3d5ff16 100644
--- a/systemverilog-plugin/uhdmcommonfrontend.h
+++ b/systemverilog-plugin/uhdmcommonfrontend.h
@@ -20,6 +20,8 @@
#include "UhdmAst.h"
#include "frontends/ast/ast.h"
#include "kernel/yosys.h"
+#include "uhdm/SynthSubset.h"
+#include "uhdm/VpiListener.h"
#include <string>
#include <vector>
diff --git a/systemverilog-plugin/uhdmsurelogastfrontend.cc b/systemverilog-plugin/uhdmsurelogastfrontend.cc
index 39cc751..f2beaee 100644
--- a/systemverilog-plugin/uhdmsurelogastfrontend.cc
+++ b/systemverilog-plugin/uhdmsurelogastfrontend.cc
@@ -121,6 +121,11 @@
}
}
+ UHDM::Serializer serializer;
+ UHDM::SynthSubset *synthSubset = new UHDM::SynthSubset(&serializer, this->shared.nonSynthesizableObjects, false);
+ synthSubset->listenDesigns(uhdm_design);
+ delete synthSubset;
+
SURELOG::shutdown_compiler(compiler);
delete clp;
delete symbolTable;