aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--backends/aiger/xaiger.cc4
-rw-r--r--backends/cxxrtl/cxxrtl.cc90
-rw-r--r--backends/verilog/verilog_backend.cc2
-rw-r--r--frontends/ast/simplify.cc28
-rw-r--r--frontends/verilog/verilog_parser.y3
-rw-r--r--tests/svtypes/typedef_package.sv11
6 files changed, 122 insertions, 16 deletions
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc
index 3b51d8685..3c7c745fe 100644
--- a/backends/aiger/xaiger.cc
+++ b/backends/aiger/xaiger.cc
@@ -280,6 +280,10 @@ struct XAigerWriter
if (abc9_flop)
continue;
}
+ else {
+ if (cell->type == ID($__ABC9_DELAY))
+ log_error("Cell type '%s' not recognised. Check that '+/abc9_model.v' has been read.\n", cell->type.c_str());
+ }
bool cell_known = inst_module || cell->known();
for (const auto &c : cell->connections()) {
diff --git a/backends/cxxrtl/cxxrtl.cc b/backends/cxxrtl/cxxrtl.cc
index 6038f87b1..3263f03fd 100644
--- a/backends/cxxrtl/cxxrtl.cc
+++ b/backends/cxxrtl/cxxrtl.cc
@@ -357,13 +357,19 @@ struct FlowGraph {
};
struct CxxrtlWorker {
+ bool split_intf = false;
+ std::string intf_filename;
+ std::string design_ns = "cxxrtl_design";
+ std::ostream *impl_f = nullptr;
+ std::ostream *intf_f = nullptr;
+
bool elide_internal = false;
bool elide_public = false;
bool localize_internal = false;
bool localize_public = false;
bool run_splitnets = false;
- std::ostream &f;
+ std::ostringstream f;
std::string indent;
int temporary = 0;
@@ -377,8 +383,6 @@ struct CxxrtlWorker {
dict<const RTLIL::Module*, std::vector<FlowGraph::Node>> schedule;
pool<const RTLIL::Wire*> localized_wires;
- CxxrtlWorker(std::ostream &f) : f(f) {}
-
void inc_indent() {
indent += "\t";
}
@@ -1193,7 +1197,7 @@ struct CxxrtlWorker {
}
}
- void dump_module(RTLIL::Module *module)
+ void dump_module_intf(RTLIL::Module *module)
{
dump_attrs(module);
f << "struct " << mangle(module) << " : public module {\n";
@@ -1222,7 +1226,10 @@ struct CxxrtlWorker {
dec_indent();
f << "}; // struct " << mangle(module) << "\n";
f << "\n";
+ }
+ void dump_module_impl(RTLIL::Module *module)
+ {
f << "void " << mangle(module) << "::eval() {\n";
inc_indent();
for (auto wire : module->wires())
@@ -1325,18 +1332,49 @@ struct CxxrtlWorker {
}
log_assert(topo_design.sort());
- f << "#include <cxxrtl.h>\n";
+ if (split_intf) {
+ // The only thing more depraved than include guards, is mangling filenames to turn them into include guards.
+ std::string include_guard = design_ns + "_header";
+ std::transform(include_guard.begin(), include_guard.end(), include_guard.begin(), ::toupper);
+
+ f << "#ifndef " << include_guard << "\n";
+ f << "#define " << include_guard << "\n";
+ f << "\n";
+ f << "#include <backends/cxxrtl/cxxrtl.h>\n";
+ f << "\n";
+ f << "using namespace cxxrtl;\n";
+ f << "\n";
+ f << "namespace " << design_ns << " {\n";
+ f << "\n";
+ for (auto module : topo_design.sorted) {
+ if (!design->selected_module(module))
+ continue;
+ dump_module_intf(module);
+ }
+ f << "} // namespace " << design_ns << "\n";
+ f << "\n";
+ f << "#endif\n";
+ *intf_f << f.str(); f.str("");
+ }
+
+ if (split_intf)
+ f << "#include \"" << intf_filename << "\"\n";
+ else
+ f << "#include <backends/cxxrtl/cxxrtl.h>\n";
f << "\n";
f << "using namespace cxxrtl_yosys;\n";
f << "\n";
- f << "namespace cxxrtl_design {\n";
+ f << "namespace " << design_ns << " {\n";
f << "\n";
for (auto module : topo_design.sorted) {
if (!design->selected_module(module))
continue;
- dump_module(module);
+ if (!split_intf)
+ dump_module_intf(module);
+ dump_module_impl(module);
}
- f << "} // namespace cxxrtl_design\n";
+ f << "} // namespace " << design_ns << "\n";
+ *impl_f << f.str(); f.str("");
}
// Edge-type sync rules require us to emit edge detectors, which require coordination between
@@ -1620,6 +1658,16 @@ struct CxxrtlBackend : public Backend {
log("\n");
log("The following options are supported by this backend:\n");
log("\n");
+ log(" -header\n");
+ log(" generate separate interface (.h) and implementation (.cc) files.\n");
+ log(" if specified, the backend must be called with a filename, and filename\n");
+ log(" of the interface is derived from filename of the implementation.\n");
+ log(" otherwise, interface and implementation are generated together.\n");
+ log("\n");
+ log(" -namespace <ns-name>\n");
+ log(" place the generated code into namespace <ns-name>. if not specified,\n");
+ log(" \"cxxrtl_design\" is used.\n");
+ log("\n");
log(" -O <level>\n");
log(" set the optimization level. the default is -O%d. higher optimization\n", DEFAULT_OPT_LEVEL);
log(" levels dramatically decrease compile and run time, and highest level\n");
@@ -1647,6 +1695,7 @@ struct CxxrtlBackend : public Backend {
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
int opt_level = DEFAULT_OPT_LEVEL;
+ CxxrtlWorker worker;
log_header(design, "Executing CXXRTL backend.\n");
@@ -1661,11 +1710,18 @@ struct CxxrtlBackend : public Backend {
opt_level = std::stoi(args[argidx].substr(2));
continue;
}
+ if (args[argidx] == "-header") {
+ worker.split_intf = true;
+ continue;
+ }
+ if (args[argidx] == "-namespace" && argidx+1 < args.size()) {
+ worker.design_ns = args[++argidx];
+ continue;
+ }
break;
}
extra_args(f, filename, args, argidx);
- CxxrtlWorker worker(*f);
switch (opt_level) {
case 5:
worker.run_splitnets = true;
@@ -1682,6 +1738,22 @@ struct CxxrtlBackend : public Backend {
default:
log_cmd_error("Invalid optimization level %d.\n", opt_level);
}
+
+ std::ofstream intf_f;
+ if (worker.split_intf) {
+ if (filename == "<stdout>")
+ log_cmd_error("Option -header must be used with a filename.\n");
+
+ worker.intf_filename = filename.substr(0, filename.rfind('.')) + ".h";
+ intf_f.open(worker.intf_filename, std::ofstream::trunc);
+ if (intf_f.fail())
+ log_cmd_error("Can't open file `%s' for writing: %s\n",
+ worker.intf_filename.c_str(), strerror(errno));
+
+ worker.intf_f = &intf_f;
+ }
+ worker.impl_f = f;
+
worker.prepare_design(design);
worker.dump_design(design);
}
diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc
index 5467e250b..11b2ae10f 100644
--- a/backends/verilog/verilog_backend.cc
+++ b/backends/verilog/verilog_backend.cc
@@ -1984,7 +1984,7 @@ struct VerilogBackend : public Backend {
extra_args(f, filename, args, argidx);
if (extmem)
{
- if (filename.empty())
+ if (filename == "<stdout>")
log_cmd_error("Option -extmem must be used with a filename.\n");
extmem_prefix = filename.substr(0, filename.rfind('.'));
}
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index b87af0f8c..ced5e5cf9 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -420,9 +420,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
current_scope[node->str] = node;
for (auto enode : node->children) {
log_assert(enode->type==AST_ENUM_ITEM);
- if (current_scope.count(enode->str) == 0) {
+ if (current_scope.count(enode->str) == 0)
current_scope[enode->str] = enode;
- }
+ else
+ log_file_error(filename, location.first_line, "enum item %s already exists\n", enode->str.c_str());
}
}
}
@@ -441,6 +442,29 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
}
+ // create name resolution entries for all objects with names
+ if (type == AST_PACKAGE) {
+ //add names to package scope
+ for (size_t i = 0; i < children.size(); i++) {
+ AstNode *node = children[i];
+ // these nodes appear at the top level in a package and can define names
+ if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_TYPEDEF) {
+ current_scope[node->str] = node;
+ }
+ if (node->type == AST_ENUM) {
+ current_scope[node->str] = node;
+ for (auto enode : node->children) {
+ log_assert(enode->type==AST_ENUM_ITEM);
+ if (current_scope.count(enode->str) == 0)
+ current_scope[enode->str] = enode;
+ else
+ log_file_error(filename, location.first_line, "enum item %s already exists in package\n", enode->str.c_str());
+ }
+ }
+ }
+ }
+
+
auto backup_current_block = current_block;
auto backup_current_block_child = current_block_child;
auto backup_current_top_block = current_top_block;
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index bd51aa12b..76373c2e4 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -521,7 +521,8 @@ package_body:
package_body_stmt:
typedef_decl |
- localparam_decl;
+ localparam_decl |
+ param_decl;
interface:
TOK_INTERFACE {
diff --git a/tests/svtypes/typedef_package.sv b/tests/svtypes/typedef_package.sv
index 57a78c53a..2d83742c5 100644
--- a/tests/svtypes/typedef_package.sv
+++ b/tests/svtypes/typedef_package.sv
@@ -1,6 +1,9 @@
package pkg;
typedef logic [7:0] uint8_t;
- typedef enum logic [7:0] {bb=8'hBB} enum8_t;
+ typedef enum logic [7:0] {bb=8'hBB, cc=8'hCC} enum8_t;
+
+ localparam uint8_t PCONST = cc;
+ parameter uint8_t PCONST_COPY = PCONST;
endpackage
module top;
@@ -8,7 +11,9 @@ module top;
(* keep *) pkg::uint8_t a = 8'hAA;
(* keep *) pkg::enum8_t b_enum = pkg::bb;
- always @* assert(a == 8'hAA);
- always @* assert(b_enum == 8'hBB);
+ always_comb assert(a == 8'hAA);
+ always_comb assert(b_enum == 8'hBB);
+ always_comb assert(pkg::PCONST == pkg::cc);
+ always_comb assert(pkg::PCONST_COPY == pkg::cc);
endmodule