From bf0f96b847a9738df10e2a549a53bddfa0d1346a Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 19 Apr 2020 16:22:02 +0000 Subject: [PATCH] cxxrtl: provide attributes to black box factories, too. Both parameters and attributes are necessary because the parameters have to be the same between every instantiation of the cell, but attributes may well vary. For example, for an UART PHY, the type of the PHY (tty, pty, socket) would be a parameter, but configuration of the implementation specified by the type (socket address) would be an attribute. --- backends/cxxrtl/cxxrtl.cc | 86 +++++++++++++++++++++------------------ backends/cxxrtl/cxxrtl.h | 20 ++++----- 2 files changed, 57 insertions(+), 49 deletions(-) diff --git a/backends/cxxrtl/cxxrtl.cc b/backends/cxxrtl/cxxrtl.cc index 86523eb2c..ef8335e50 100644 --- a/backends/cxxrtl/cxxrtl.cc +++ b/backends/cxxrtl/cxxrtl.cc @@ -1429,6 +1429,33 @@ struct CxxrtlWorker { dec_indent(); } + void dump_metadata_map(const dict &metadata_map) + { + if (metadata_map.empty()) { + f << "metadata_map()"; + return; + } + f << "metadata_map({\n"; + inc_indent(); + for (auto metadata_item : metadata_map) { + if (!metadata_item.first.begins_with("\\")) + continue; + f << indent << "{ " << escape_cxx_string(metadata_item.first.str().substr(1)) << ", "; + if (metadata_item.second.flags & RTLIL::CONST_FLAG_REAL) { + f << std::showpoint << std::stod(metadata_item.second.decode_string()) << std::noshowpoint; + } else if (metadata_item.second.flags & RTLIL::CONST_FLAG_STRING) { + f << escape_cxx_string(metadata_item.second.decode_string()); + } else { + f << metadata_item.second.as_int(/*is_signed=*/metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED); + if (!(metadata_item.second.flags & RTLIL::CONST_FLAG_SIGNED)) + f << "u"; + } + f << " },\n"; + } + dec_indent(); + f << indent << "})"; + } + void dump_module_intf(RTLIL::Module *module) { dump_attrs(module); @@ -1452,7 +1479,7 @@ struct CxxrtlWorker { f << "\n"; f << indent << "static std::unique_ptr<" << mangle(module); f << template_params(module, /*is_decl=*/false) << "> "; - f << "create(std::string name, parameter_map parameters);\n"; + f << "create(std::string name, metadata_map parameters, metadata_map attributes);\n"; dec_indent(); f << indent << "}; // struct " << mangle(module) << "\n"; f << "\n"; @@ -1471,7 +1498,7 @@ struct CxxrtlWorker { f << indent << "template<>\n"; f << indent << "std::unique_ptr<" << mangle(module) << specialization << "> "; f << mangle(module) << specialization << "::"; - f << "create(std::string name, parameter_map parameters);\n"; + f << "create(std::string name, metadata_map parameters, metadata_map attributes);\n"; f << "\n"; } } @@ -1499,30 +1526,9 @@ struct CxxrtlWorker { f << indent << "std::unique_ptr<" << mangle(cell_module) << template_args(cell) << "> "; f << mangle(cell) << " = " << mangle(cell_module) << template_args(cell); f << "::create(" << escape_cxx_string(cell->name.str()) << ", "; - if (!cell->parameters.empty()) { - f << "parameter_map({\n"; - inc_indent(); - for (auto param : cell->parameters) { - // All blackbox parameters should be in the public namespace already; strip leading slash - // to make it more convenient for blackbox implementations. - log_assert(param.first.begins_with("\\")); - f << indent << "{ " << escape_cxx_string(param.first.str().substr(1)) << ", "; - if (param.second.flags & RTLIL::CONST_FLAG_REAL) { - f << std::showpoint << std::stod(param.second.decode_string()) << std::noshowpoint; - } else if (param.second.flags & RTLIL::CONST_FLAG_STRING) { - f << escape_cxx_string(param.second.decode_string()); - } else { - f << param.second.as_int(/*is_signed=*/param.second.flags & RTLIL::CONST_FLAG_SIGNED); - if (!(param.second.flags & RTLIL::CONST_FLAG_SIGNED)) - f << "u"; - } - f << " },\n"; - } - dec_indent(); - f << indent << "})"; - } else { - f << "parameter_map()"; - } + dump_metadata_map(cell->parameters); + f << ", "; + dump_metadata_map(cell->attributes); f << ");\n"; } else { f << indent << mangle(cell_module) << " " << mangle(cell) << ";\n"; @@ -1964,7 +1970,7 @@ struct CxxrtlBackend : public Backend { log("\n"); log("For this HDL interface, this backend will generate the following C++ interface:\n"); log("\n"); - log(" struct bb_debug : public module {\n"); + log(" struct bb_p_debug : public module {\n"); log(" wire<1> p_clk;\n"); log(" bool posedge_p_clk = false;\n"); log(" wire<1> p_en;\n"); @@ -1973,8 +1979,8 @@ struct CxxrtlBackend : public Backend { log(" void eval() override;\n"); log(" bool commit() override;\n"); log("\n"); - log(" static std::unique_ptr\n"); - log(" create(std::string name, parameter_map parameters);\n"); + log(" static std::unique_ptr\n"); + log(" create(std::string name, metadata_map parameters, metadata_map attributes);\n"); log(" };\n"); log("\n"); log("The `create' function must be implemented by the driver. For example, it could\n"); @@ -1982,16 +1988,17 @@ struct CxxrtlBackend : public Backend { log("\n"); log(" namespace cxxrtl_design {\n"); log("\n"); - log(" struct stderr_debug : public bb_debug {\n"); + log(" struct stderr_debug : public bb_p_debug {\n"); log(" void eval() override {\n"); log(" if (posedge_p_clk && p_en.curr)\n"); log(" fprintf(stderr, \"debug: %%02x\\n\", p_data.curr.data[0]);\n"); - log(" bb_debug::eval();\n"); + log(" bb_p_debug::eval();\n"); log(" }\n"); log(" };\n"); log("\n"); - log(" std::unique_ptr\n"); - log(" bb_debug::create(std::string name, cxxrtl::parameter_map parameters) {\n"); + log(" std::unique_ptr\n"); + log(" bb_p_debug::create(std::string name, cxxrtl::metadata_map parameters,\n"); + log(" cxxrtl::metadata_map attributes) {\n"); log(" return std::make_unique();\n"); log(" }\n"); log("\n"); @@ -2013,12 +2020,12 @@ struct CxxrtlBackend : public Backend { log("interface (only the differences are shown):\n"); log("\n"); log(" template\n"); - log(" struct bb_debug : public module {\n"); + log(" struct bb_p_debug : public module {\n"); log(" // ...\n"); log(" wire p_data;\n"); log(" // ...\n"); - log(" static std::unique_ptr>\n"); - log(" create(std::string name, parameter_map parameters);\n"); + log(" static std::unique_ptr>\n"); + log(" create(std::string name, metadata_map parameters, metadata_map attributes);\n"); log(" };\n"); log("\n"); log("The `create' function must be implemented by the driver, specialized for every\n"); @@ -2026,13 +2033,14 @@ struct CxxrtlBackend : public Backend { log("enable separate compilation of generated code and black box implementations.)\n"); log("\n"); log(" template\n"); - log(" struct stderr_debug : public bb_debug {\n"); + log(" struct stderr_debug : public bb_p_debug {\n"); log(" // ...\n"); log(" };\n"); log("\n"); log(" template<>\n"); - log(" std::unique_ptr>\n"); - log(" bb_debug<8>::create(std::string name, cxxrtl::parameter_map parameters) {\n"); + log(" std::unique_ptr>\n"); + log(" bb_p_debug<8>::create(std::string name, cxxrtl::metadata_map parameters,\n"); + log(" cxxrtl::metadata_map attributes) {\n"); log(" return std::make_unique>();\n"); log(" }\n"); log("\n"); diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h index 0b330fa8f..41e6290d1 100644 --- a/backends/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/cxxrtl.h @@ -659,7 +659,7 @@ struct memory { } }; -struct parameter { +struct metadata { const enum { MISSING = 0, UINT = 1, @@ -677,15 +677,15 @@ struct parameter { const std::string string_value = ""; const double double_value = 0.0; - parameter() : value_type(MISSING) {} - parameter(unsigned value) : value_type(UINT), uint_value(value) {} - parameter(signed value) : value_type(SINT), sint_value(value) {} - parameter(const std::string &value) : value_type(STRING), string_value(value) {} - parameter(const char *value) : value_type(STRING), string_value(value) {} - parameter(double value) : value_type(DOUBLE), double_value(value) {} + metadata() : value_type(MISSING) {} + metadata(unsigned value) : value_type(UINT), uint_value(value) {} + metadata(signed value) : value_type(SINT), sint_value(value) {} + metadata(const std::string &value) : value_type(STRING), string_value(value) {} + metadata(const char *value) : value_type(STRING), string_value(value) {} + metadata(double value) : value_type(DOUBLE), double_value(value) {} - parameter(const parameter &) = default; - parameter &operator=(const parameter &) = delete; + metadata(const metadata &) = default; + metadata &operator=(const metadata &) = delete; unsigned as_uint() const { assert(value_type == UINT); @@ -708,7 +708,7 @@ struct parameter { } }; -typedef std::map parameter_map; +typedef std::map metadata_map; struct module { module() {} -- 2.30.2