diff options
-rw-r--r-- | backends/aiger/xaiger.cc | 4 | ||||
-rw-r--r-- | backends/cxxrtl/cxxrtl.cc | 90 | ||||
-rw-r--r-- | backends/verilog/verilog_backend.cc | 2 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 28 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 3 | ||||
-rw-r--r-- | tests/svtypes/typedef_package.sv | 11 |
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 |