3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-13 04:28:18 +00:00

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.
This commit is contained in:
whitequark 2020-04-19 16:22:02 +00:00
parent c98cde8842
commit bf0f96b847
2 changed files with 57 additions and 49 deletions

View file

@ -1429,6 +1429,33 @@ struct CxxrtlWorker {
dec_indent(); dec_indent();
} }
void dump_metadata_map(const dict<RTLIL::IdString, RTLIL::Const> &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) void dump_module_intf(RTLIL::Module *module)
{ {
dump_attrs(module); dump_attrs(module);
@ -1452,7 +1479,7 @@ struct CxxrtlWorker {
f << "\n"; f << "\n";
f << indent << "static std::unique_ptr<" << mangle(module); f << indent << "static std::unique_ptr<" << mangle(module);
f << template_params(module, /*is_decl=*/false) << "> "; 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(); dec_indent();
f << indent << "}; // struct " << mangle(module) << "\n"; f << indent << "}; // struct " << mangle(module) << "\n";
f << "\n"; f << "\n";
@ -1471,7 +1498,7 @@ struct CxxrtlWorker {
f << indent << "template<>\n"; f << indent << "template<>\n";
f << indent << "std::unique_ptr<" << mangle(module) << specialization << "> "; f << indent << "std::unique_ptr<" << mangle(module) << specialization << "> ";
f << 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"; f << "\n";
} }
} }
@ -1499,30 +1526,9 @@ struct CxxrtlWorker {
f << indent << "std::unique_ptr<" << mangle(cell_module) << template_args(cell) << "> "; f << indent << "std::unique_ptr<" << mangle(cell_module) << template_args(cell) << "> ";
f << mangle(cell) << " = " << mangle(cell_module) << template_args(cell); f << mangle(cell) << " = " << mangle(cell_module) << template_args(cell);
f << "::create(" << escape_cxx_string(cell->name.str()) << ", "; f << "::create(" << escape_cxx_string(cell->name.str()) << ", ";
if (!cell->parameters.empty()) { dump_metadata_map(cell->parameters);
f << "parameter_map({\n"; f << ", ";
inc_indent(); dump_metadata_map(cell->attributes);
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()";
}
f << ");\n"; f << ");\n";
} else { } else {
f << indent << mangle(cell_module) << " " << mangle(cell) << ";\n"; f << indent << mangle(cell_module) << " " << mangle(cell) << ";\n";
@ -1964,7 +1970,7 @@ struct CxxrtlBackend : public Backend {
log("\n"); log("\n");
log("For this HDL interface, this backend will generate the following C++ interface:\n"); log("For this HDL interface, this backend will generate the following C++ interface:\n");
log("\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(" wire<1> p_clk;\n");
log(" bool posedge_p_clk = false;\n"); log(" bool posedge_p_clk = false;\n");
log(" wire<1> p_en;\n"); log(" wire<1> p_en;\n");
@ -1973,8 +1979,8 @@ struct CxxrtlBackend : public Backend {
log(" void eval() override;\n"); log(" void eval() override;\n");
log(" bool commit() override;\n"); log(" bool commit() override;\n");
log("\n"); log("\n");
log(" static std::unique_ptr<bb_debug>\n"); log(" static std::unique_ptr<bb_p_debug>\n");
log(" create(std::string name, parameter_map parameters);\n"); log(" create(std::string name, metadata_map parameters, metadata_map attributes);\n");
log(" };\n"); log(" };\n");
log("\n"); log("\n");
log("The `create' function must be implemented by the driver. For example, it could\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("\n");
log(" namespace cxxrtl_design {\n"); log(" namespace cxxrtl_design {\n");
log("\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(" void eval() override {\n");
log(" if (posedge_p_clk && p_en.curr)\n"); log(" if (posedge_p_clk && p_en.curr)\n");
log(" fprintf(stderr, \"debug: %%02x\\n\", p_data.curr.data[0]);\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(" };\n");
log("\n"); log("\n");
log(" std::unique_ptr<bb_debug>\n"); log(" std::unique_ptr<bb_p_debug>\n");
log(" bb_debug::create(std::string name, cxxrtl::parameter_map parameters) {\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<stderr_debug>();\n"); log(" return std::make_unique<stderr_debug>();\n");
log(" }\n"); log(" }\n");
log("\n"); log("\n");
@ -2013,12 +2020,12 @@ struct CxxrtlBackend : public Backend {
log("interface (only the differences are shown):\n"); log("interface (only the differences are shown):\n");
log("\n"); log("\n");
log(" template<size_t WIDTH>\n"); log(" template<size_t WIDTH>\n");
log(" struct bb_debug : public module {\n"); log(" struct bb_p_debug : public module {\n");
log(" // ...\n"); log(" // ...\n");
log(" wire<WIDTH> p_data;\n"); log(" wire<WIDTH> p_data;\n");
log(" // ...\n"); log(" // ...\n");
log(" static std::unique_ptr<bb_debug<WIDTH>>\n"); log(" static std::unique_ptr<bb_p_debug<WIDTH>>\n");
log(" create(std::string name, parameter_map parameters);\n"); log(" create(std::string name, metadata_map parameters, metadata_map attributes);\n");
log(" };\n"); log(" };\n");
log("\n"); log("\n");
log("The `create' function must be implemented by the driver, specialized for every\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("enable separate compilation of generated code and black box implementations.)\n");
log("\n"); log("\n");
log(" template<size_t SIZE>\n"); log(" template<size_t SIZE>\n");
log(" struct stderr_debug : public bb_debug<SIZE> {\n"); log(" struct stderr_debug : public bb_p_debug<SIZE> {\n");
log(" // ...\n"); log(" // ...\n");
log(" };\n"); log(" };\n");
log("\n"); log("\n");
log(" template<>\n"); log(" template<>\n");
log(" std::unique_ptr<bb_debug<8>>\n"); log(" std::unique_ptr<bb_p_debug<8>>\n");
log(" bb_debug<8>::create(std::string name, cxxrtl::parameter_map parameters) {\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<stderr_debug<8>>();\n"); log(" return std::make_unique<stderr_debug<8>>();\n");
log(" }\n"); log(" }\n");
log("\n"); log("\n");

View file

@ -659,7 +659,7 @@ struct memory {
} }
}; };
struct parameter { struct metadata {
const enum { const enum {
MISSING = 0, MISSING = 0,
UINT = 1, UINT = 1,
@ -677,15 +677,15 @@ struct parameter {
const std::string string_value = ""; const std::string string_value = "";
const double double_value = 0.0; const double double_value = 0.0;
parameter() : value_type(MISSING) {} metadata() : value_type(MISSING) {}
parameter(unsigned value) : value_type(UINT), uint_value(value) {} metadata(unsigned value) : value_type(UINT), uint_value(value) {}
parameter(signed value) : value_type(SINT), sint_value(value) {} metadata(signed value) : value_type(SINT), sint_value(value) {}
parameter(const std::string &value) : value_type(STRING), string_value(value) {} metadata(const std::string &value) : value_type(STRING), string_value(value) {}
parameter(const char *value) : value_type(STRING), string_value(value) {} metadata(const char *value) : value_type(STRING), string_value(value) {}
parameter(double value) : value_type(DOUBLE), double_value(value) {} metadata(double value) : value_type(DOUBLE), double_value(value) {}
parameter(const parameter &) = default; metadata(const metadata &) = default;
parameter &operator=(const parameter &) = delete; metadata &operator=(const metadata &) = delete;
unsigned as_uint() const { unsigned as_uint() const {
assert(value_type == UINT); assert(value_type == UINT);
@ -708,7 +708,7 @@ struct parameter {
} }
}; };
typedef std::map<std::string, parameter> parameter_map; typedef std::map<std::string, metadata> metadata_map;
struct module { struct module {
module() {} module() {}