Run formatting on all plugins Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
diff --git a/bank_tiles.h b/bank_tiles.h index 3197ee0..3ff5220 100644 --- a/bank_tiles.h +++ b/bank_tiles.h
@@ -20,36 +20,34 @@ #include "kernel/log.h" #include "libs/json11/json11.hpp" - USING_YOSYS_NAMESPACE // Coordinates of HCLK_IOI tiles associated with a specified bank using BankTilesMap = std::unordered_map<int, std::string>; // Find the part's JSON file with information including the IO Banks // and extract the bank tiles. -inline BankTilesMap get_bank_tiles(const std::string json_file_name) { - BankTilesMap bank_tiles; - std::ifstream json_file(json_file_name); - if (!json_file.good()) { - log_cmd_error("Can't open JSON file %s", json_file_name.c_str()); - } - std::string json_str((std::istreambuf_iterator<char>(json_file)), - std::istreambuf_iterator<char>()); - std::string error; - auto json = json11::Json::parse(json_str, error); - if (!error.empty()) { - log_cmd_error("%s\n", error.c_str()); - } - auto json_objects = json.object_items(); - auto iobanks = json_objects.find("iobanks"); - if (iobanks == json_objects.end()) { - log_cmd_error("IO Bank information missing in the part's json: %s\n", json_file_name.c_str()); - } +inline BankTilesMap get_bank_tiles(const std::string json_file_name) +{ + BankTilesMap bank_tiles; + std::ifstream json_file(json_file_name); + if (!json_file.good()) { + log_cmd_error("Can't open JSON file %s", json_file_name.c_str()); + } + std::string json_str((std::istreambuf_iterator<char>(json_file)), std::istreambuf_iterator<char>()); + std::string error; + auto json = json11::Json::parse(json_str, error); + if (!error.empty()) { + log_cmd_error("%s\n", error.c_str()); + } + auto json_objects = json.object_items(); + auto iobanks = json_objects.find("iobanks"); + if (iobanks == json_objects.end()) { + log_cmd_error("IO Bank information missing in the part's json: %s\n", json_file_name.c_str()); + } - for (auto iobank : iobanks->second.object_items()) { - bank_tiles.emplace(std::atoi(iobank.first.c_str()), iobank.second.string_value()); - } + for (auto iobank : iobanks->second.object_items()) { + bank_tiles.emplace(std::atoi(iobank.first.c_str()), iobank.second.string_value()); + } - return bank_tiles; + return bank_tiles; } -
diff --git a/design_introspection-plugin/design_introspection.cc b/design_introspection-plugin/design_introspection.cc index 64fdbbc..4bd348d 100644 --- a/design_introspection-plugin/design_introspection.cc +++ b/design_introspection-plugin/design_introspection.cc
@@ -18,22 +18,21 @@ * */ -#include "get_nets.h" -#include "get_ports.h" #include "get_cells.h" +#include "get_nets.h" #include "get_pins.h" +#include "get_ports.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct DesignIntrospection { - DesignIntrospection(){} + DesignIntrospection() {} GetNets get_nets_cmd; GetPorts get_ports_cmd; GetCells get_cells_cmd; GetPins get_pins_cmd; } DesignIntrospection; - PRIVATE_NAMESPACE_END
diff --git a/design_introspection-plugin/get_cells.cc b/design_introspection-plugin/get_cells.cc index 937545d..d0e6ce0 100644 --- a/design_introspection-plugin/get_cells.cc +++ b/design_introspection-plugin/get_cells.cc
@@ -25,24 +25,24 @@ std::string GetCells::SelectionType() { return "c"; } -GetCells::SelectionObjects GetCells::ExtractSelection(RTLIL::Design* design, const CommandArgs& args) { +GetCells::SelectionObjects GetCells::ExtractSelection(RTLIL::Design *design, const CommandArgs &args) +{ SelectionObjects selected_objects; for (auto module : design->selected_modules()) { - for (auto cell : module->selected_cells()) { - if (args.filters.size() > 0) { - Filter filter = args.filters.at(0); - std::string attr_value = cell->get_string_attribute( - RTLIL::IdString(RTLIL::escape_id(filter.first))); - if (attr_value.compare(filter.second)) { - continue; - } - } - std::string object_name(RTLIL::unescape_id(cell->name)); - selected_objects.push_back(object_name); - } + for (auto cell : module->selected_cells()) { + if (args.filters.size() > 0) { + Filter filter = args.filters.at(0); + std::string attr_value = cell->get_string_attribute(RTLIL::IdString(RTLIL::escape_id(filter.first))); + if (attr_value.compare(filter.second)) { + continue; + } + } + std::string object_name(RTLIL::unescape_id(cell->name)); + selected_objects.push_back(object_name); + } } if (selected_objects.size() == 0 and !args.is_quiet) { - log_warning("Couldn't find matching cell.\n"); + log_warning("Couldn't find matching cell.\n"); } return selected_objects; }
diff --git a/design_introspection-plugin/get_cells.h b/design_introspection-plugin/get_cells.h index 205d50b..c9ba621 100644 --- a/design_introspection-plugin/get_cells.h +++ b/design_introspection-plugin/get_cells.h
@@ -29,8 +29,7 @@ std::string TypeName() override; std::string SelectionType() override; - SelectionObjects ExtractSelection(RTLIL::Design* design, - const CommandArgs& args) override; + SelectionObjects ExtractSelection(RTLIL::Design *design, const CommandArgs &args) override; }; -#endif // GET_CELLS_H_ +#endif // GET_CELLS_H_
diff --git a/design_introspection-plugin/get_cmd.cc b/design_introspection-plugin/get_cmd.cc index 4b54ded..66401a6 100644 --- a/design_introspection-plugin/get_cmd.cc +++ b/design_introspection-plugin/get_cmd.cc
@@ -2,7 +2,8 @@ USING_YOSYS_NAMESPACE -void GetCmd::help() { +void GetCmd::help() +{ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" get_%ss [-quiet] [-filter filter_expression] " @@ -30,106 +31,94 @@ log("\n"); } -void GetCmd::ExecuteSelection(RTLIL::Design* design, const CommandArgs& args) { +void GetCmd::ExecuteSelection(RTLIL::Design *design, const CommandArgs &args) +{ std::vector<std::string> selection_args; // Add name of top module to selection string - std::transform(args.selection_objects.begin(), args.selection_objects.end(), - std::back_inserter(selection_args), - [&](const std::string& obj) { - return RTLIL::unescape_id(design->top_module()->name) + - "/" + SelectionType() + ":" + obj; - }); + std::transform(args.selection_objects.begin(), args.selection_objects.end(), std::back_inserter(selection_args), + [&](const std::string &obj) { return RTLIL::unescape_id(design->top_module()->name) + "/" + SelectionType() + ":" + obj; }); extra_args(selection_args, 0, design); if (design->selected_modules().empty()) { - if (!args.is_quiet) { - log_warning("Specified %s not found in design\n", - TypeName().c_str()); - } + if (!args.is_quiet) { + log_warning("Specified %s not found in design\n", TypeName().c_str()); + } } } -void GetCmd::PackToTcl(const SelectionObjects& objects) { - Tcl_Obj* tcl_result; +void GetCmd::PackToTcl(const SelectionObjects &objects) +{ + Tcl_Obj *tcl_result; if (objects.size() == 1) { - tcl_result = Tcl_NewStringObj(objects.at(0).c_str(), -1); + tcl_result = Tcl_NewStringObj(objects.at(0).c_str(), -1); } else { - tcl_result = Tcl_NewListObj(0, NULL); - for (const auto& object : objects) { - Tcl_Obj* value_obj = Tcl_NewStringObj(object.c_str(), -1); - Tcl_ListObjAppendElement(yosys_get_tcl_interp(), tcl_result, - value_obj); - } + tcl_result = Tcl_NewListObj(0, NULL); + for (const auto &object : objects) { + Tcl_Obj *value_obj = Tcl_NewStringObj(object.c_str(), -1); + Tcl_ListObjAppendElement(yosys_get_tcl_interp(), tcl_result, value_obj); + } } Tcl_SetObjResult(yosys_get_tcl_interp(), tcl_result); } -GetCmd::CommandArgs GetCmd::ParseCommand(const std::vector<std::string>& args) { - CommandArgs parsed_args{.filters = Filters(), - .is_quiet = false, - .selection_objects = SelectionObjects()}; +GetCmd::CommandArgs GetCmd::ParseCommand(const std::vector<std::string> &args) +{ + CommandArgs parsed_args{.filters = Filters(), .is_quiet = false, .selection_objects = SelectionObjects()}; size_t argidx(0); for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-quiet") { - parsed_args.is_quiet = true; - continue; - } + std::string arg = args[argidx]; + if (arg == "-quiet") { + parsed_args.is_quiet = true; + continue; + } - if (arg == "-filter" and argidx + 1 < args.size()) { - std::string filter_arg = args[++argidx]; + if (arg == "-filter" and argidx + 1 < args.size()) { + std::string filter_arg = args[++argidx]; - // Remove spaces - filter_arg.erase( - std::remove_if(filter_arg.begin(), filter_arg.end(), isspace), - filter_arg.end()); + // Remove spaces + filter_arg.erase(std::remove_if(filter_arg.begin(), filter_arg.end(), isspace), filter_arg.end()); - // Parse filters - // TODO Add support for multiple condition expression - // Currently only a single == is supported - std::regex filter_attr_regex("(\\w+\\s?==\\s?\\w+)([(||)(&&)]*)"); - std::regex_token_iterator<std::string::iterator> regex_end; - std::regex_token_iterator<std::string::iterator> matches( - filter_arg.begin(), filter_arg.end(), filter_attr_regex, 1); - if (matches == regex_end) { - log_warning( - "Currently -filter switch supports only a single " - "'equal(==)' condition expression, the rest will be " - "ignored\n"); - } + // Parse filters + // TODO Add support for multiple condition expression + // Currently only a single == is supported + std::regex filter_attr_regex("(\\w+\\s?==\\s?\\w+)([(||)(&&)]*)"); + std::regex_token_iterator<std::string::iterator> regex_end; + std::regex_token_iterator<std::string::iterator> matches(filter_arg.begin(), filter_arg.end(), filter_attr_regex, 1); + if (matches == regex_end) { + log_warning("Currently -filter switch supports only a single " + "'equal(==)' condition expression, the rest will be " + "ignored\n"); + } - while (matches != regex_end) { - std::string filter(*matches++); - auto separator = filter.find("=="); - if (separator == std::string::npos) { - log_cmd_error("Incorrect filter expression: %s\n", - args[argidx].c_str()); - } - parsed_args.filters.emplace_back(filter.substr(0, separator), - filter.substr(separator + 2)); - } - if (parsed_args.filters.size() > 1) { - log_warning( - "Currently -filter switch supports only a single " - "'equal(==)' condition expression, the rest will be " - "ignored\n"); - } - continue; - } + while (matches != regex_end) { + std::string filter(*matches++); + auto separator = filter.find("=="); + if (separator == std::string::npos) { + log_cmd_error("Incorrect filter expression: %s\n", args[argidx].c_str()); + } + parsed_args.filters.emplace_back(filter.substr(0, separator), filter.substr(separator + 2)); + } + if (parsed_args.filters.size() > 1) { + log_warning("Currently -filter switch supports only a single " + "'equal(==)' condition expression, the rest will be " + "ignored\n"); + } + continue; + } - if (arg.size() > 0 and arg[0] == '-') { - log_cmd_error("Unknown option %s.\n", arg.c_str()); - } + if (arg.size() > 0 and arg[0] == '-') { + log_cmd_error("Unknown option %s.\n", arg.c_str()); + } - break; + break; } - std::copy(args.begin() + argidx, args.end(), - std::back_inserter(parsed_args.selection_objects)); + std::copy(args.begin() + argidx, args.end(), std::back_inserter(parsed_args.selection_objects)); return parsed_args; } -void GetCmd::execute(std::vector<std::string> args, RTLIL::Design* design) { +void GetCmd::execute(std::vector<std::string> args, RTLIL::Design *design) +{ if (design->top_module() == nullptr) { - log_cmd_error("No top module detected\n"); + log_cmd_error("No top module detected\n"); } CommandArgs parsed_args(ParseCommand(args));
diff --git a/design_introspection-plugin/get_cmd.h b/design_introspection-plugin/get_cmd.h index 983a50d..5d1a120 100644 --- a/design_introspection-plugin/get_cmd.h +++ b/design_introspection-plugin/get_cmd.h
@@ -29,27 +29,25 @@ using Filters = std::vector<Filter>; using SelectionObjects = std::vector<std::string>; struct CommandArgs { - Filters filters; - bool is_quiet; - SelectionObjects selection_objects; + Filters filters; + bool is_quiet; + SelectionObjects selection_objects; }; - GetCmd(const std::string& name, const std::string& description) - : Pass(name, description) {} + GetCmd(const std::string &name, const std::string &description) : Pass(name, description) {} void help() override; - void execute(std::vector<std::string> args, RTLIL::Design* design) override; + void execute(std::vector<std::string> args, RTLIL::Design *design) override; - protected: - CommandArgs ParseCommand(const std::vector<std::string>& args); - void PackToTcl(const SelectionObjects& objects); + protected: + CommandArgs ParseCommand(const std::vector<std::string> &args); + void PackToTcl(const SelectionObjects &objects); - private: + private: virtual std::string TypeName() = 0; virtual std::string SelectionType() = 0; - virtual SelectionObjects ExtractSelection(RTLIL::Design* design, const CommandArgs& args) = 0; - virtual void ExecuteSelection(RTLIL::Design* design, - const CommandArgs& args); + virtual SelectionObjects ExtractSelection(RTLIL::Design *design, const CommandArgs &args) = 0; + virtual void ExecuteSelection(RTLIL::Design *design, const CommandArgs &args); }; -#endif // GET_CMD_H_ +#endif // GET_CMD_H_
diff --git a/design_introspection-plugin/get_nets.cc b/design_introspection-plugin/get_nets.cc index db5d375..09e5ed4 100644 --- a/design_introspection-plugin/get_nets.cc +++ b/design_introspection-plugin/get_nets.cc
@@ -25,25 +25,24 @@ std::string GetNets::SelectionType() { return "w"; } -GetNets::SelectionObjects GetNets::ExtractSelection(RTLIL::Design* design, - const CommandArgs& args) { +GetNets::SelectionObjects GetNets::ExtractSelection(RTLIL::Design *design, const CommandArgs &args) +{ SelectionObjects selected_objects; for (auto module : design->selected_modules()) { - for (auto wire : module->selected_wires()) { - if (args.filters.size() > 0) { - Filter filter = args.filters.at(0); - std::string attr_value = wire->get_string_attribute( - RTLIL::IdString(RTLIL::escape_id(filter.first))); - if (attr_value.compare(filter.second)) { - continue; - } - } - std::string object_name(RTLIL::unescape_id(wire->name)); - selected_objects.push_back(object_name); - } + for (auto wire : module->selected_wires()) { + if (args.filters.size() > 0) { + Filter filter = args.filters.at(0); + std::string attr_value = wire->get_string_attribute(RTLIL::IdString(RTLIL::escape_id(filter.first))); + if (attr_value.compare(filter.second)) { + continue; + } + } + std::string object_name(RTLIL::unescape_id(wire->name)); + selected_objects.push_back(object_name); + } } if (selected_objects.size() == 0 and !args.is_quiet) { - log_warning("Couldn't find matching net.\n"); + log_warning("Couldn't find matching net.\n"); } return selected_objects; }
diff --git a/design_introspection-plugin/get_nets.h b/design_introspection-plugin/get_nets.h index 11f7502..d9f5850 100644 --- a/design_introspection-plugin/get_nets.h +++ b/design_introspection-plugin/get_nets.h
@@ -29,8 +29,7 @@ std::string TypeName() override; std::string SelectionType() override; - SelectionObjects ExtractSelection(RTLIL::Design* design, - const CommandArgs& args) override; + SelectionObjects ExtractSelection(RTLIL::Design *design, const CommandArgs &args) override; }; -#endif // GET_NETS_H_ +#endif // GET_NETS_H_
diff --git a/design_introspection-plugin/get_pins.cc b/design_introspection-plugin/get_pins.cc index d39f6bc..e94e3ae 100644 --- a/design_introspection-plugin/get_pins.cc +++ b/design_introspection-plugin/get_pins.cc
@@ -25,57 +25,50 @@ std::string GetPins::SelectionType() { return "c"; } -void GetPins::ExecuteSelection(RTLIL::Design* design, const CommandArgs& args) { +void GetPins::ExecuteSelection(RTLIL::Design *design, const CommandArgs &args) +{ (void)design; (void)args; } -GetPins::SelectionObjects GetPins::ExtractSelection(RTLIL::Design* design, - const CommandArgs& args) { +GetPins::SelectionObjects GetPins::ExtractSelection(RTLIL::Design *design, const CommandArgs &args) +{ SelectionObjects selected_objects; for (auto obj : args.selection_objects) { - size_t port_separator = obj.find_last_of("/"); - std::string cell = obj.substr(0, port_separator); - std::string port = obj.substr(port_separator + 1); - SelectionObjects selection{ - RTLIL::unescape_id(design->top_module()->name) + "/" + - SelectionType() + ":" + cell}; - extra_args(selection, 0, design); - ExtractSingleSelection(selected_objects, design, port, args); + size_t port_separator = obj.find_last_of("/"); + std::string cell = obj.substr(0, port_separator); + std::string port = obj.substr(port_separator + 1); + SelectionObjects selection{RTLIL::unescape_id(design->top_module()->name) + "/" + SelectionType() + ":" + cell}; + extra_args(selection, 0, design); + ExtractSingleSelection(selected_objects, design, port, args); } if (selected_objects.size() == 0 and !args.is_quiet) { - log_warning("Couldn't find matching pin.\n"); + log_warning("Couldn't find matching pin.\n"); } return selected_objects; } -void GetPins::ExtractSingleSelection(SelectionObjects& objects, - RTLIL::Design* design, - const std::string& port_name, - const CommandArgs& args) { +void GetPins::ExtractSingleSelection(SelectionObjects &objects, RTLIL::Design *design, const std::string &port_name, const CommandArgs &args) +{ if (design->selected_modules().empty()) { - if (!args.is_quiet) { - log_warning("Specified %s not found in design\n", - TypeName().c_str()); - } + if (!args.is_quiet) { + log_warning("Specified %s not found in design\n", TypeName().c_str()); + } } for (auto module : design->selected_modules()) { - for (auto cell : module->selected_cells()) { - if (!cell->hasPort(RTLIL::escape_id(port_name))) { - continue; - } - if (args.filters.size() > 0) { - Filter filter = args.filters.at(0); - std::string attr_value = cell->get_string_attribute( - RTLIL::IdString(RTLIL::escape_id(filter.first))); - if (attr_value.compare(filter.second)) { - continue; - } - } - std::string pin_name(RTLIL::unescape_id(cell->name) + "/" + - port_name); - objects.push_back(pin_name); - } + for (auto cell : module->selected_cells()) { + if (!cell->hasPort(RTLIL::escape_id(port_name))) { + continue; + } + if (args.filters.size() > 0) { + Filter filter = args.filters.at(0); + std::string attr_value = cell->get_string_attribute(RTLIL::IdString(RTLIL::escape_id(filter.first))); + if (attr_value.compare(filter.second)) { + continue; + } + } + std::string pin_name(RTLIL::unescape_id(cell->name) + "/" + port_name); + objects.push_back(pin_name); + } } } -
diff --git a/design_introspection-plugin/get_pins.h b/design_introspection-plugin/get_pins.h index f7ebe14..5d2cde0 100644 --- a/design_introspection-plugin/get_pins.h +++ b/design_introspection-plugin/get_pins.h
@@ -27,17 +27,12 @@ struct GetPins : public GetCmd { GetPins() : GetCmd("get_pins", "Print matching pins") {} - private: + private: std::string TypeName() override; std::string SelectionType() override; - SelectionObjects ExtractSelection(RTLIL::Design* design, - const CommandArgs& args) override; - void ExecuteSelection(RTLIL::Design* design, - const CommandArgs& args) override; - void ExtractSingleSelection(SelectionObjects& objects, - RTLIL::Design* design, - const std::string& port_name, - const CommandArgs& args); + SelectionObjects ExtractSelection(RTLIL::Design *design, const CommandArgs &args) override; + void ExecuteSelection(RTLIL::Design *design, const CommandArgs &args) override; + void ExtractSingleSelection(SelectionObjects &objects, RTLIL::Design *design, const std::string &port_name, const CommandArgs &args); }; -#endif // GET_PINS_H_ +#endif // GET_PINS_H_
diff --git a/design_introspection-plugin/get_ports.cc b/design_introspection-plugin/get_ports.cc index ef29b95..042ada7 100644 --- a/design_introspection-plugin/get_ports.cc +++ b/design_introspection-plugin/get_ports.cc
@@ -25,33 +25,29 @@ std::string GetPorts::SelectionType() { return "x"; } -void GetPorts::ExecuteSelection([[gnu::unused]] RTLIL::Design* design, - [[gnu::unused]] const CommandArgs& args) { -} +void GetPorts::ExecuteSelection([[gnu::unused]] RTLIL::Design *design, [[gnu::unused]] const CommandArgs &args) {} -GetPorts::SelectionObjects GetPorts::ExtractSelection(RTLIL::Design* design, - const CommandArgs& args) { +GetPorts::SelectionObjects GetPorts::ExtractSelection(RTLIL::Design *design, const CommandArgs &args) +{ std::string port_name = args.selection_objects.at(0); std::string port_str(port_name.size(), '\0'); int bit(0); if (!sscanf(port_name.c_str(), "%[^[][%d]", &port_str[0], &bit)) { - log_error("Couldn't find port %s\n", port_name.c_str()); + log_error("Couldn't find port %s\n", port_name.c_str()); } port_str.resize(strlen(port_str.c_str())); RTLIL::IdString port_id(RTLIL::escape_id(port_str)); SelectionObjects objects; if (auto wire = design->top_module()->wire(port_id)) { - if (wire->port_input || wire->port_output) { - if (bit >= wire->start_offset && - bit < wire->start_offset + wire->width) { - objects.push_back(port_name); - } - } + if (wire->port_input || wire->port_output) { + if (bit >= wire->start_offset && bit < wire->start_offset + wire->width) { + objects.push_back(port_name); + } + } } if (objects.size() == 0 and !args.is_quiet) { - log_warning("Couldn't find port matching %s\n", port_name.c_str()); + log_warning("Couldn't find port matching %s\n", port_name.c_str()); } return objects; } -
diff --git a/design_introspection-plugin/get_ports.h b/design_introspection-plugin/get_ports.h index 89ba49a..b1ccb0b 100644 --- a/design_introspection-plugin/get_ports.h +++ b/design_introspection-plugin/get_ports.h
@@ -27,14 +27,12 @@ struct GetPorts : public GetCmd { GetPorts() : GetCmd("get_ports", "Print matching ports") {} - private: + private: std::string TypeName() override; std::string SelectionType() override; /* void execute(std::vector<std::string> args, RTLIL::Design* design) override; */ - SelectionObjects ExtractSelection(RTLIL::Design* design, - const CommandArgs& args) override; - void ExecuteSelection(RTLIL::Design* design, - const CommandArgs& args) override; + SelectionObjects ExtractSelection(RTLIL::Design *design, const CommandArgs &args) override; + void ExecuteSelection(RTLIL::Design *design, const CommandArgs &args) override; }; -#endif // GET_PORTS_H_ +#endif // GET_PORTS_H_
diff --git a/fasm-plugin/fasm.cc b/fasm-plugin/fasm.cc index 4ddfdb2..5ab4c1a 100644 --- a/fasm-plugin/fasm.cc +++ b/fasm-plugin/fasm.cc
@@ -24,62 +24,65 @@ * annotations on the design cells. */ +#include "../bank_tiles.h" +#include "kernel/log.h" #include "kernel/register.h" #include "kernel/rtlil.h" -#include "kernel/log.h" -#include "../bank_tiles.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct WriteFasm : public Backend { - WriteFasm() : Backend("fasm", "Write out FASM features") {} + WriteFasm() : Backend("fasm", "Write out FASM features") {} + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" write_fasm -part_json <part_json_filename> <filename>\n"); + log("\n"); + log("Write out a file with vref FASM features.\n"); + log("\n"); + } - void help() override { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" write_fasm -part_json <part_json_filename> <filename>\n"); - log("\n"); - log("Write out a file with vref FASM features.\n"); - log("\n"); - } + void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override + { + size_t argidx = 1; + std::string part_json; + if (args[argidx] == "-part_json" && argidx + 1 < args.size()) { + part_json = args[++argidx]; + argidx++; + } + extra_args(f, filename, args, argidx); + extract_fasm_features(f, design, part_json); + } - void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override { - size_t argidx = 1; - std::string part_json; - if (args[argidx] == "-part_json" && argidx + 1 < args.size()) { - part_json = args[++argidx]; - argidx++; - } - extra_args(f, filename, args, argidx); - extract_fasm_features(f, design, part_json); - } - - void extract_fasm_features(std::ostream *&f, RTLIL::Design* design, const std::string& part_json) { - RTLIL::Module* top_module(design->top_module()); - if (top_module == nullptr) { - log_cmd_error("%s: No top module detected.\n", pass_name.c_str()); - } - auto bank_tiles = get_bank_tiles(part_json); - // Generate a fasm feature associated with the INTERNAL_VREF value per bank - // e.g. VREF value of 0.675 for bank 34 is associated with tile HCLK_IOI3_X113Y26 - // hence we need to emit the following fasm feature: HCLK_IOI3_X113Y26.VREF.V_675_MV - for (auto cell : top_module->cells()) { - if (!cell->hasParam(ID(FASM_EXTRA))) continue; - if (cell->getParam(ID(FASM_EXTRA)) == RTLIL::Const("INTERNAL_VREF")) { - if (bank_tiles.size() == 0) { - log_cmd_error("%s: No bank tiles available on the target part.\n", pass_name.c_str()); - } - int bank_number(cell->getParam(ID(NUMBER)).as_int()); - if (bank_tiles.count(bank_number) == 0) { - log_cmd_error("%s: No IO bank number %d on the target part.\n", pass_name.c_str(), bank_number); - } - int bank_vref(cell->getParam(ID(INTERNAL_VREF)).as_int()); - *f << "HCLK_IOI3_" << bank_tiles[bank_number] <<".VREF.V_" << bank_vref << "_MV\n"; - } - } - } + void extract_fasm_features(std::ostream *&f, RTLIL::Design *design, const std::string &part_json) + { + RTLIL::Module *top_module(design->top_module()); + if (top_module == nullptr) { + log_cmd_error("%s: No top module detected.\n", pass_name.c_str()); + } + auto bank_tiles = get_bank_tiles(part_json); + // Generate a fasm feature associated with the INTERNAL_VREF value per bank + // e.g. VREF value of 0.675 for bank 34 is associated with tile HCLK_IOI3_X113Y26 + // hence we need to emit the following fasm feature: HCLK_IOI3_X113Y26.VREF.V_675_MV + for (auto cell : top_module->cells()) { + if (!cell->hasParam(ID(FASM_EXTRA))) + continue; + if (cell->getParam(ID(FASM_EXTRA)) == RTLIL::Const("INTERNAL_VREF")) { + if (bank_tiles.size() == 0) { + log_cmd_error("%s: No bank tiles available on the target part.\n", pass_name.c_str()); + } + int bank_number(cell->getParam(ID(NUMBER)).as_int()); + if (bank_tiles.count(bank_number) == 0) { + log_cmd_error("%s: No IO bank number %d on the target part.\n", pass_name.c_str(), bank_number); + } + int bank_vref(cell->getParam(ID(INTERNAL_VREF)).as_int()); + *f << "HCLK_IOI3_" << bank_tiles[bank_number] << ".VREF.V_" << bank_vref << "_MV\n"; + } + } + } } WriteFasm; PRIVATE_NAMESPACE_END
diff --git a/get_count-plugin/get_count.cc b/get_count-plugin/get_count.cc index b78f9b8..5faff16 100644 --- a/get_count-plugin/get_count.cc +++ b/get_count-plugin/get_count.cc
@@ -30,18 +30,12 @@ struct GetCount : public Pass { - enum class ObjectType { - NONE, - MODULE, - CELL, - WIRE - }; + enum class ObjectType { NONE, MODULE, CELL, WIRE }; - GetCount () : - Pass("get_count", "Returns count of various selected object types to the TCL interpreter") { - } + GetCount() : Pass("get_count", "Returns count of various selected object types to the TCL interpreter") {} - void help() YS_OVERRIDE { + void help() YS_OVERRIDE + { log("\n"); log(" get_count <options> [selection]"); log("\n"); @@ -59,8 +53,9 @@ log(" Returns the count of wires in selection\n"); log("\n"); } - - void execute(std::vector<std::string> a_Args, RTLIL::Design* a_Design) YS_OVERRIDE { + + void execute(std::vector<std::string> a_Args, RTLIL::Design *a_Design) YS_OVERRIDE + { // Parse args ObjectType type = ObjectType::NONE; @@ -70,29 +65,25 @@ if (a_Args[1] == "-modules") { type = ObjectType::MODULE; - } - else if (a_Args[1] == "-cells") { + } else if (a_Args[1] == "-cells") { type = ObjectType::CELL; - } - else if (a_Args[1] == "-wires") { + } else if (a_Args[1] == "-wires") { type = ObjectType::WIRE; - } - else if (a_Args[1][0] == '-') { + } else if (a_Args[1][0] == '-') { log_error("Invalid argument '%s'!\n", a_Args[1].c_str()); - } - else { + } else { log_error("Object type not specified!\n"); } extra_args(a_Args, 2, a_Design); // Get the TCL interpreter - Tcl_Interp* tclInterp = yosys_get_tcl_interp(); + Tcl_Interp *tclInterp = yosys_get_tcl_interp(); // Count objects size_t moduleCount = 0; - size_t cellCount = 0; - size_t wireCount = 0; + size_t cellCount = 0; + size_t wireCount = 0; moduleCount += a_Design->selected_modules().size(); for (auto module : a_Design->selected_modules()) { @@ -101,8 +92,7 @@ } size_t count = 0; - switch (type) - { + switch (type) { case ObjectType::MODULE: count = moduleCount; break; @@ -119,7 +109,7 @@ // Return the value as string to the TCL interpreter std::string value = std::to_string(count); - Tcl_Obj* tclStr = Tcl_NewStringObj(value.c_str(), value.size()); + Tcl_Obj *tclStr = Tcl_NewStringObj(value.c_str(), value.size()); Tcl_SetObjResult(tclInterp, tclStr); }
diff --git a/integrateinv-plugin/integrateinv.cc b/integrateinv-plugin/integrateinv.cc index 4a4f693..f3d5690 100644 --- a/integrateinv-plugin/integrateinv.cc +++ b/integrateinv-plugin/integrateinv.cc
@@ -27,315 +27,315 @@ /// A structure representing a pin struct Pin { - RTLIL::Cell *cell; /// Cell pointer - RTLIL::IdString port; /// Cell port name - int bit; /// Port bit index + RTLIL::Cell *cell; /// Cell pointer + RTLIL::IdString port; /// Cell port name + int bit; /// Port bit index - Pin(RTLIL::Cell *_cell, const RTLIL::IdString &_port, int _bit = 0) - : cell(_cell), port(_port), bit(_bit) {} + Pin(RTLIL::Cell *_cell, const RTLIL::IdString &_port, int _bit = 0) : cell(_cell), port(_port), bit(_bit) {} - Pin(const Pin &ref) = default; + Pin(const Pin &ref) = default; - unsigned int hash() const { - if (cell == nullptr) { - return mkhash_add(port.hash(), bit); - } else { - return mkhash_add(mkhash(cell->hash(), port.hash()), bit); - } - }; + unsigned int hash() const + { + if (cell == nullptr) { + return mkhash_add(port.hash(), bit); + } else { + return mkhash_add(mkhash(cell->hash(), port.hash()), bit); + } + }; }; -bool operator==(const Pin &lhs, const Pin &rhs) { - return (lhs.cell == rhs.cell) && (lhs.port == rhs.port) && - (lhs.bit == rhs.bit); -} +bool operator==(const Pin &lhs, const Pin &rhs) { return (lhs.cell == rhs.cell) && (lhs.port == rhs.port) && (lhs.bit == rhs.bit); } struct IntegrateInv : public Pass { - /// Temporary SigBit to SigBit helper map. - SigMap m_SigMap; - /// Map of SigBit objects to inverter cells. - dict<RTLIL::SigBit, RTLIL::Cell *> m_InvMap; - /// Map of inverter cells that can potentially be integrated and invertable - /// pins that they are connected to - dict<RTLIL::Cell *, pool<Pin>> m_Inverters; - /// Map of invertable pins and names of parameters controlling inversions - dict<Pin, RTLIL::IdString> m_InvParams; + /// Temporary SigBit to SigBit helper map. + SigMap m_SigMap; + /// Map of SigBit objects to inverter cells. + dict<RTLIL::SigBit, RTLIL::Cell *> m_InvMap; + /// Map of inverter cells that can potentially be integrated and invertable + /// pins that they are connected to + dict<RTLIL::Cell *, pool<Pin>> m_Inverters; + /// Map of invertable pins and names of parameters controlling inversions + dict<Pin, RTLIL::IdString> m_InvParams; - IntegrateInv() - : Pass("integrateinv", "Integrates inverters ($_NOT_ cells) into ports " - "with 'invertible_pin' attribute set") {} - - void help() override { - log("\n"); - log(" integrateinv [selection]"); - log("\n"); - log("This pass integrates inverters into cells that have ports with the\n"); - log("'invertible_pin' attribute set. The attribute should contain the name\n"); - log("of a parameter controlling the inversion.\n"); - log("\n"); - log("This pass is essentially the opposite of the 'extractinv' pass.\n"); - log("\n"); - } - - void execute(std::vector<std::string> a_Args, - RTLIL::Design *a_Design) override { - log_header(a_Design, - "Executing INTEGRATEINV pass (integrating pin inverters).\n"); - - extra_args(a_Args, 1, a_Design); - - // Process modules - for (auto module : a_Design->selected_modules()) { - - // Setup the SigMap - m_SigMap.clear(); - m_SigMap.set(module); - - m_Inverters.clear(); - m_InvParams.clear(); - - // Setup inverter map - buildInverterMap(module); - - // Identify inverters that can be integrated and assign them with - // lists of cells and ports to integrate with - for (auto cell : module->selected_cells()) { - collectInverters(cell); - } - - // Integrate inverters - integrateInverters(); + IntegrateInv() + : Pass("integrateinv", "Integrates inverters ($_NOT_ cells) into ports " + "with 'invertible_pin' attribute set") + { } - // Clear maps - m_SigMap.clear(); - - m_InvMap.clear(); - m_Inverters.clear(); - m_InvParams.clear(); - } - - void buildInverterMap(RTLIL::Module *a_Module) { - m_InvMap.clear(); - - for (auto cell : a_Module->cells()) { - - // Skip non-inverters - if (cell->type != RTLIL::escape_id("$_NOT_")) { - continue; - } - - // Get output connection - auto sigspec = cell->getPort(RTLIL::escape_id("Y")); - auto sigbit = m_SigMap(sigspec.bits().at(0)); - - // Store - log_assert(m_InvMap.count(sigbit) == 0); - m_InvMap[sigbit] = cell; - } - } - - void collectInverters(RTLIL::Cell *a_Cell) { - auto module = a_Cell->module; - auto design = module->design; - - for (auto conn : a_Cell->connections()) { - auto port = conn.first; - auto sigspec = conn.second; - - // Consider only inputs. - if (!a_Cell->input(port)) { - continue; - } - - // Get the cell module - auto cellModule = design->module(a_Cell->type); - if (!cellModule) { - continue; - } - - // Get wire. - auto wire = cellModule->wire(port); - if (!wire) { - continue; - } - - // Check if the pin has an embedded inverter. - auto it = wire->attributes.find(ID::invertible_pin); - if (it == wire->attributes.end()) { - continue; - } - - // Decode the parameter name. - RTLIL::IdString paramName = RTLIL::escape_id(it->second.decode_string()); - - // Look for connected inverters - auto sigbits = sigspec.bits(); - for (size_t bit = 0; bit < sigbits.size(); ++bit) { - - auto sigbit = sigbits[bit]; - if (!sigbit.wire) { - continue; - } - - sigbit = m_SigMap(sigbit); - - // Get the inverter if any - if (!m_InvMap.count(sigbit)) { - continue; - } - auto inv = m_InvMap.at(sigbit); - - // Save the inverter pin and the parameter name - auto pin = Pin(a_Cell, port, bit); - - auto &list = m_Inverters[inv]; - list.insert(pin); - - log_assert(m_InvParams.count(pin) == 0); - m_InvParams[pin] = paramName; - } - } - } - - void integrateInverters() { - - for (auto it : m_Inverters) { - auto inv = it.first; - auto pins = it.second; - - // List all sinks of the inverter - auto sinks = getSinksForDriver(Pin(inv, RTLIL::escape_id("Y"))); - - // If the inverter drives only invertable pins then integrate it - if (sinks == pins) { - log("Integrating inverter %s into:\n", log_id(inv->name)); - - // Integrate into each pin - for (auto pin : pins) { - log_assert(pin.cell != nullptr); - log(" %s.%s[%d]\n", log_id(pin.cell->name), log_id(pin.port), - pin.bit); - - // Change the connection - auto sigspec = pin.cell->getPort(pin.port); - auto sigbits = sigspec.bits(); - - log_assert((size_t)pin.bit < sigbits.size()); - sigbits[pin.bit] = - RTLIL::SigBit(inv->getPort(RTLIL::escape_id("A"))[0]); - pin.cell->setPort(pin.port, RTLIL::SigSpec(sigbits)); - - // Get the control parameter - log_assert(m_InvParams.count(pin) != 0); - auto paramName = m_InvParams[pin]; - - RTLIL::Const invMask; - auto param = pin.cell->parameters.find(paramName); - if (param == pin.cell->parameters.end()) { - invMask = RTLIL::Const(0, sigspec.size()); - } else { - invMask = RTLIL::Const(param->second); - } - - // Check width. - if (invMask.size() != sigspec.size()) { - log_error("The inversion parameter needs to be the same width as " - "the port (%s port %s parameter %s)", - log_id(pin.cell->name), log_id(pin.port), - log_id(paramName)); - } - - // Toggle bit in the control parameter bitmask - if (invMask[pin.bit] == RTLIL::State::S0) { - invMask[pin.bit] = RTLIL::State::S1; - } else if (invMask[pin.bit] == RTLIL::State::S1) { - invMask[pin.bit] = RTLIL::State::S0; - } else { - log_error("The inversion parameter must contain only 0s and 1s (%s " - "parameter %s)\n", - log_id(pin.cell->name), log_id(paramName)); - } - - // Set the parameter back - pin.cell->setParam(paramName, invMask); - } - - // Remove the inverter - inv->module->remove(inv); - } - } - } - - pool<Pin> getSinksForDriver(const Pin &a_Driver) { - auto module = a_Driver.cell->module; - pool<Pin> sinks; - - // The driver has to be an output pin - if (!a_Driver.cell->output(a_Driver.port)) { - return sinks; + void help() override + { + log("\n"); + log(" integrateinv [selection]"); + log("\n"); + log("This pass integrates inverters into cells that have ports with the\n"); + log("'invertible_pin' attribute set. The attribute should contain the name\n"); + log("of a parameter controlling the inversion.\n"); + log("\n"); + log("This pass is essentially the opposite of the 'extractinv' pass.\n"); + log("\n"); } - // Get the driver sigbit - auto driverSigspec = a_Driver.cell->getPort(a_Driver.port); - auto driverSigbit = m_SigMap(driverSigspec.bits().at(a_Driver.bit)); + void execute(std::vector<std::string> a_Args, RTLIL::Design *a_Design) override + { + log_header(a_Design, "Executing INTEGRATEINV pass (integrating pin inverters).\n"); - // Look for connected sinks - for (auto cell : module->cells()) { - for (auto conn : cell->connections()) { - auto port = conn.first; - auto sigspec = conn.second; + extra_args(a_Args, 1, a_Design); - // Consider only sinks (inputs) - if (!cell->input(port)) { - continue; + // Process modules + for (auto module : a_Design->selected_modules()) { + + // Setup the SigMap + m_SigMap.clear(); + m_SigMap.set(module); + + m_Inverters.clear(); + m_InvParams.clear(); + + // Setup inverter map + buildInverterMap(module); + + // Identify inverters that can be integrated and assign them with + // lists of cells and ports to integrate with + for (auto cell : module->selected_cells()) { + collectInverters(cell); + } + + // Integrate inverters + integrateInverters(); } - // Check all sigbits - auto sigbits = sigspec.bits(); - for (size_t bit = 0; bit < sigbits.size(); ++bit) { + // Clear maps + m_SigMap.clear(); - auto sigbit = sigbits[bit]; - if (!sigbit.wire) { - continue; - } - - // Got a sink pin of another cell - sigbit = m_SigMap(sigbit); - if (sigbit == driverSigbit) { - sinks.insert(Pin(cell, port, bit)); - } - } - } + m_InvMap.clear(); + m_Inverters.clear(); + m_InvParams.clear(); } - // Look for connected top-level output ports - for (auto conn : module->connections()) { - auto dst = conn.first; - auto src = conn.second; + void buildInverterMap(RTLIL::Module *a_Module) + { + m_InvMap.clear(); - auto sigbits = dst.bits(); - for (size_t bit = 0; bit < sigbits.size(); ++bit) { + for (auto cell : a_Module->cells()) { - auto sigbit = sigbits[bit]; - if (!sigbit.wire) { - continue; + // Skip non-inverters + if (cell->type != RTLIL::escape_id("$_NOT_")) { + continue; + } + + // Get output connection + auto sigspec = cell->getPort(RTLIL::escape_id("Y")); + auto sigbit = m_SigMap(sigspec.bits().at(0)); + + // Store + log_assert(m_InvMap.count(sigbit) == 0); + m_InvMap[sigbit] = cell; } - - if (!sigbit.wire->port_output) { - continue; - } - - sigbit = m_SigMap(sigbit); - if (sigbit == driverSigbit) { - sinks.insert(Pin(nullptr, sigbit.wire->name, bit)); - } - } } - return sinks; - } + void collectInverters(RTLIL::Cell *a_Cell) + { + auto module = a_Cell->module; + auto design = module->design; + + for (auto conn : a_Cell->connections()) { + auto port = conn.first; + auto sigspec = conn.second; + + // Consider only inputs. + if (!a_Cell->input(port)) { + continue; + } + + // Get the cell module + auto cellModule = design->module(a_Cell->type); + if (!cellModule) { + continue; + } + + // Get wire. + auto wire = cellModule->wire(port); + if (!wire) { + continue; + } + + // Check if the pin has an embedded inverter. + auto it = wire->attributes.find(ID::invertible_pin); + if (it == wire->attributes.end()) { + continue; + } + + // Decode the parameter name. + RTLIL::IdString paramName = RTLIL::escape_id(it->second.decode_string()); + + // Look for connected inverters + auto sigbits = sigspec.bits(); + for (size_t bit = 0; bit < sigbits.size(); ++bit) { + + auto sigbit = sigbits[bit]; + if (!sigbit.wire) { + continue; + } + + sigbit = m_SigMap(sigbit); + + // Get the inverter if any + if (!m_InvMap.count(sigbit)) { + continue; + } + auto inv = m_InvMap.at(sigbit); + + // Save the inverter pin and the parameter name + auto pin = Pin(a_Cell, port, bit); + + auto &list = m_Inverters[inv]; + list.insert(pin); + + log_assert(m_InvParams.count(pin) == 0); + m_InvParams[pin] = paramName; + } + } + } + + void integrateInverters() + { + + for (auto it : m_Inverters) { + auto inv = it.first; + auto pins = it.second; + + // List all sinks of the inverter + auto sinks = getSinksForDriver(Pin(inv, RTLIL::escape_id("Y"))); + + // If the inverter drives only invertable pins then integrate it + if (sinks == pins) { + log("Integrating inverter %s into:\n", log_id(inv->name)); + + // Integrate into each pin + for (auto pin : pins) { + log_assert(pin.cell != nullptr); + log(" %s.%s[%d]\n", log_id(pin.cell->name), log_id(pin.port), pin.bit); + + // Change the connection + auto sigspec = pin.cell->getPort(pin.port); + auto sigbits = sigspec.bits(); + + log_assert((size_t)pin.bit < sigbits.size()); + sigbits[pin.bit] = RTLIL::SigBit(inv->getPort(RTLIL::escape_id("A"))[0]); + pin.cell->setPort(pin.port, RTLIL::SigSpec(sigbits)); + + // Get the control parameter + log_assert(m_InvParams.count(pin) != 0); + auto paramName = m_InvParams[pin]; + + RTLIL::Const invMask; + auto param = pin.cell->parameters.find(paramName); + if (param == pin.cell->parameters.end()) { + invMask = RTLIL::Const(0, sigspec.size()); + } else { + invMask = RTLIL::Const(param->second); + } + + // Check width. + if (invMask.size() != sigspec.size()) { + log_error("The inversion parameter needs to be the same width as " + "the port (%s port %s parameter %s)", + log_id(pin.cell->name), log_id(pin.port), log_id(paramName)); + } + + // Toggle bit in the control parameter bitmask + if (invMask[pin.bit] == RTLIL::State::S0) { + invMask[pin.bit] = RTLIL::State::S1; + } else if (invMask[pin.bit] == RTLIL::State::S1) { + invMask[pin.bit] = RTLIL::State::S0; + } else { + log_error("The inversion parameter must contain only 0s and 1s (%s " + "parameter %s)\n", + log_id(pin.cell->name), log_id(paramName)); + } + + // Set the parameter back + pin.cell->setParam(paramName, invMask); + } + + // Remove the inverter + inv->module->remove(inv); + } + } + } + + pool<Pin> getSinksForDriver(const Pin &a_Driver) + { + auto module = a_Driver.cell->module; + pool<Pin> sinks; + + // The driver has to be an output pin + if (!a_Driver.cell->output(a_Driver.port)) { + return sinks; + } + + // Get the driver sigbit + auto driverSigspec = a_Driver.cell->getPort(a_Driver.port); + auto driverSigbit = m_SigMap(driverSigspec.bits().at(a_Driver.bit)); + + // Look for connected sinks + for (auto cell : module->cells()) { + for (auto conn : cell->connections()) { + auto port = conn.first; + auto sigspec = conn.second; + + // Consider only sinks (inputs) + if (!cell->input(port)) { + continue; + } + + // Check all sigbits + auto sigbits = sigspec.bits(); + for (size_t bit = 0; bit < sigbits.size(); ++bit) { + + auto sigbit = sigbits[bit]; + if (!sigbit.wire) { + continue; + } + + // Got a sink pin of another cell + sigbit = m_SigMap(sigbit); + if (sigbit == driverSigbit) { + sinks.insert(Pin(cell, port, bit)); + } + } + } + } + + // Look for connected top-level output ports + for (auto conn : module->connections()) { + auto dst = conn.first; + auto src = conn.second; + + auto sigbits = dst.bits(); + for (size_t bit = 0; bit < sigbits.size(); ++bit) { + + auto sigbit = sigbits[bit]; + if (!sigbit.wire) { + continue; + } + + if (!sigbit.wire->port_output) { + continue; + } + + sigbit = m_SigMap(sigbit); + if (sigbit == driverSigbit) { + sinks.insert(Pin(nullptr, sigbit.wire->name, bit)); + } + } + } + + return sinks; + } } IntegrateInv;
diff --git a/params-plugin/params.cc b/params-plugin/params.cc index c4f169b..cddc737 100644 --- a/params-plugin/params.cc +++ b/params-plugin/params.cc
@@ -16,66 +16,64 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "kernel/log.h" #include "kernel/register.h" #include "kernel/rtlil.h" -#include "kernel/log.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN - -void register_in_tcl_interpreter(const std::string& command) { - Tcl_Interp* interp = yosys_get_tcl_interp(); - std::string tcl_script = stringf("proc %s args { return [yosys %s {*}$args] }", command.c_str(), command.c_str()); - Tcl_Eval(interp, tcl_script.c_str()); +void register_in_tcl_interpreter(const std::string &command) +{ + Tcl_Interp *interp = yosys_get_tcl_interp(); + std::string tcl_script = stringf("proc %s args { return [yosys %s {*}$args] }", command.c_str(), command.c_str()); + Tcl_Eval(interp, tcl_script.c_str()); } struct GetParam : public Pass { - GetParam() : Pass("getparam", "get parameter on object") { - register_in_tcl_interpreter(pass_name); - } + GetParam() : Pass("getparam", "get parameter on object") { register_in_tcl_interpreter(pass_name); } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" getparam name selection\n"); - log("\n"); - log("Get the given parameter on the selected object. \n"); - log("\n"); - } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" getparam name selection\n"); + log("\n"); + log("Get the given parameter on the selected object. \n"); + log("\n"); + } - void execute(std::vector<std::string> args, RTLIL::Design* design) override - { - if (args.size() == 1) { - log_error("Incorrect number of arguments"); - } - extra_args(args, 2, design); + void execute(std::vector<std::string> args, RTLIL::Design *design) override + { + if (args.size() == 1) { + log_error("Incorrect number of arguments"); + } + extra_args(args, 2, design); - auto param = RTLIL::IdString(RTLIL::escape_id(args.at(1))); - Tcl_Interp *interp = yosys_get_tcl_interp(); - Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL); + auto param = RTLIL::IdString(RTLIL::escape_id(args.at(1))); + Tcl_Interp *interp = yosys_get_tcl_interp(); + Tcl_Obj *tcl_list = Tcl_NewListObj(0, NULL); - for (auto module : design->selected_modules()) { - for (auto cell : module->selected_cells()) { - auto params = cell->parameters; - auto it = params.find(param); - if (it != params.end()) { - std::string value; - auto param_obj = it->second; - if (param_obj.flags & RTLIL::CONST_FLAG_STRING) { - value = param_obj.decode_string(); - } else { - value = std::to_string(param_obj.as_int()); - } - Tcl_Obj* value_obj = Tcl_NewStringObj(value.c_str(), value.size()); - Tcl_ListObjAppendElement(interp, tcl_list, value_obj); - } - } - } - Tcl_SetObjResult(interp, tcl_list); - } + for (auto module : design->selected_modules()) { + for (auto cell : module->selected_cells()) { + auto params = cell->parameters; + auto it = params.find(param); + if (it != params.end()) { + std::string value; + auto param_obj = it->second; + if (param_obj.flags & RTLIL::CONST_FLAG_STRING) { + value = param_obj.decode_string(); + } else { + value = std::to_string(param_obj.as_int()); + } + Tcl_Obj *value_obj = Tcl_NewStringObj(value.c_str(), value.size()); + Tcl_ListObjAppendElement(interp, tcl_list, value_obj); + } + } + } + Tcl_SetObjResult(interp, tcl_list); + } } GetParam;
diff --git a/ql-iob-plugin/pcf_parser.cc b/ql-iob-plugin/pcf_parser.cc index c7a9309..f8e1aeb 100644 --- a/ql-iob-plugin/pcf_parser.cc +++ b/ql-iob-plugin/pcf_parser.cc
@@ -23,7 +23,8 @@ // ============================================================================ -bool PcfParser::parse (const std::string& a_FileName) { +bool PcfParser::parse(const std::string &a_FileName) +{ // Open the file std::ifstream file(a_FileName.c_str()); @@ -32,14 +33,12 @@ return parse(file); } -const std::vector<PcfParser::Constraint> PcfParser::getConstraints () const { - return m_Constraints; -} - +const std::vector<PcfParser::Constraint> PcfParser::getConstraints() const { return m_Constraints; } // ============================================================================ -bool PcfParser::parse (std::ifstream& a_Stream) { +bool PcfParser::parse(std::ifstream &a_Stream) +{ if (!a_Stream.good()) { return false; @@ -58,13 +57,7 @@ // Match against regex std::cmatch cm; if (std::regex_match(line.c_str(), cm, re)) { - m_Constraints.push_back( - Constraint( - cm[1].str(), - cm[2].str(), - cm[3].str() - ) - ); + m_Constraints.push_back(Constraint(cm[1].str(), cm[2].str(), cm[3].str())); } }
diff --git a/ql-iob-plugin/pinmap_parser.cc b/ql-iob-plugin/pinmap_parser.cc index 77e3662..ceaf30a 100644 --- a/ql-iob-plugin/pinmap_parser.cc +++ b/ql-iob-plugin/pinmap_parser.cc
@@ -23,7 +23,8 @@ // ============================================================================ -bool PinmapParser::parse (const std::string& a_FileName) { +bool PinmapParser::parse(const std::string &a_FileName) +{ // Open the file std::ifstream file(a_FileName.c_str()); @@ -32,13 +33,12 @@ return parse(file); } -const std::vector<PinmapParser::Entry> PinmapParser::getEntries() const { - return m_Entries; -} +const std::vector<PinmapParser::Entry> PinmapParser::getEntries() const { return m_Entries; } // ============================================================================ -std::vector<std::string> PinmapParser::getFields (const std::string& a_String) { +std::vector<std::string> PinmapParser::getFields(const std::string &a_String) +{ std::vector<std::string> fields; std::stringstream ss(a_String); @@ -53,7 +53,8 @@ return fields; } -bool PinmapParser::parseHeader (std::ifstream& a_Stream) { +bool PinmapParser::parseHeader(std::ifstream &a_Stream) +{ // Get the header line std::string header; @@ -68,7 +69,8 @@ return true; } -bool PinmapParser::parseData (std::ifstream& a_Stream) { +bool PinmapParser::parseData(std::ifstream &a_Stream) +{ // Parse lines as they come while (a_Stream.good()) { @@ -84,7 +86,7 @@ // Assign data fields to columns Entry entry; - for (size_t i=0; i<data.size(); ++i) { + for (size_t i = 0; i < data.size(); ++i) { if (i >= m_Fields.size()) { return false; @@ -99,7 +101,8 @@ return true; } -bool PinmapParser::parse (std::ifstream& a_Stream) { +bool PinmapParser::parse(std::ifstream &a_Stream) +{ if (!a_Stream.good()) { return false;
diff --git a/ql-iob-plugin/ql-iob.cc b/ql-iob-plugin/ql-iob.cc index 6574535..d6aeefc 100644 --- a/ql-iob-plugin/ql-iob.cc +++ b/ql-iob-plugin/ql-iob.cc
@@ -41,18 +41,16 @@ std::string port; // Name of the port that goes to a pad std::vector<std::string> preferredTypes; // A list of preferred IO cell types - IoCellType (const std::string& _type, const std::string& _port, const std::vector<std::string> _preferredTypes = std::vector<std::string>()) : - type(_type), - port(_port), - preferredTypes(_preferredTypes) - {} + IoCellType(const std::string &_type, const std::string &_port, const std::vector<std::string> _preferredTypes = std::vector<std::string>()) + : type(_type), port(_port), preferredTypes(_preferredTypes) + { + } }; - QuicklogicIob () : - Pass("quicklogic_iob", "Map IO buffers to cells that correspond to their assigned locations") { - } + QuicklogicIob() : Pass("quicklogic_iob", "Map IO buffers to cells that correspond to their assigned locations") {} - void help() YS_OVERRIDE { + void help() YS_OVERRIDE + { log("\n"); log(" quicklogic_iob <PCF file> <pinmap file> [<io cell specs>]"); log("\n"); @@ -82,8 +80,9 @@ log(" types in order of preference.\n"); log("\n"); } - - void execute(std::vector<std::string> a_Args, RTLIL::Design* a_Design) YS_OVERRIDE { + + void execute(std::vector<std::string> a_Args, RTLIL::Design *a_Design) YS_OVERRIDE + { if (a_Args.size() < 3) { log_cmd_error(" Usage: quicklogic_iob <PCF file> <pinmap file> [<io cell specs>]"); } @@ -91,7 +90,6 @@ // A map of IO cell types and their port names that should go to a pad std::unordered_map<std::string, IoCellType> ioCellTypes; - // Parse io cell specification if (a_Args.size() > 3) { @@ -100,7 +98,7 @@ std::regex re1("^([\\w$]+):([\\w$]+)$"); std::regex re2("^([\\w$]+):([\\w$]+):([\\w,$]+)$"); - for (size_t i=3; i<a_Args.size(); ++i) { + for (size_t i = 3; i < a_Args.size(); ++i) { std::cmatch cm; // No preffered IO cell types @@ -119,7 +117,7 @@ preferredTypes.push_back(field); } - + ioCellTypes.emplace(cm[1].str(), IoCellType(cm[1], cm[2], preferredTypes)); } @@ -132,14 +130,14 @@ // Use the default IO cells for QuickLogic FPGAs else { - ioCellTypes.emplace("inpad", IoCellType("inpad", "P", {"BIDIR", "SDIOMUX"})); + ioCellTypes.emplace("inpad", IoCellType("inpad", "P", {"BIDIR", "SDIOMUX"})); ioCellTypes.emplace("outpad", IoCellType("outpad", "P", {"BIDIR", "SDIOMUX"})); - ioCellTypes.emplace("bipad", IoCellType("bipad", "P", {"BIDIR", "SDIOMUX"})); - ioCellTypes.emplace("ckpad", IoCellType("ckpad", "P", {"CLOCK", "BIDIR", "SDIOMUX"})); + ioCellTypes.emplace("bipad", IoCellType("bipad", "P", {"BIDIR", "SDIOMUX"})); + ioCellTypes.emplace("ckpad", IoCellType("ckpad", "P", {"CLOCK", "BIDIR", "SDIOMUX"})); } // Get the top module of the design - RTLIL::Module* topModule = a_Design->top_module(); + RTLIL::Module *topModule = a_Design->top_module(); if (topModule == nullptr) { log_cmd_error("No top module detected!\n"); } @@ -153,7 +151,7 @@ // Build a map of net names to constraints std::unordered_map<std::string, const PcfParser::Constraint> constraintMap; - for (auto& constraint : pcfParser.getConstraints()) { + for (auto &constraint : pcfParser.getConstraints()) { if (constraintMap.count(constraint.netName) != 0) { log_cmd_error("The net '%s' is constrained twice!", constraint.netName.c_str()); } @@ -169,9 +167,9 @@ // Build a map of pad names to entries std::unordered_map<std::string, std::vector<PinmapParser::Entry>> pinmapMap; - for (auto& entry : pinmapParser.getEntries()) { + for (auto &entry : pinmapParser.getEntries()) { if (entry.count("name") != 0) { - auto& name = entry.at("name"); + auto &name = entry.at("name"); if (pinmapMap.count(name) == 0) { pinmapMap[name] = std::vector<PinmapParser::Entry>(); @@ -187,7 +185,7 @@ log(" type | net | pad | loc | type | instance\n"); log(" ------------+------------+------------+----------+----------+-----------\n"); for (auto cell : topModule->cells()) { - auto ysCellType = RTLIL::unescape_id(cell->type); + auto ysCellType = RTLIL::unescape_id(cell->type); // Not an IO cell if (ioCellTypes.count(ysCellType) == 0) { @@ -202,7 +200,7 @@ std::string cellType; // Get connections to the specified port - const auto& ioCellType = ioCellTypes.at(ysCellType); + const auto &ioCellType = ioCellTypes.at(ysCellType); const std::string port = RTLIL::escape_id(ioCellType.port); if (cell->connections().count(port)) { @@ -220,15 +218,15 @@ // Check if the wire is constrained. Get pad name. std::string baseName = RTLIL::unescape_id(wire->name); std::string netNames[] = { - baseName, - stringf("%s[%d]", baseName.c_str(), sigbit.offset), - stringf("%s(%d)", baseName.c_str(), sigbit.offset), + baseName, + stringf("%s[%d]", baseName.c_str(), sigbit.offset), + stringf("%s(%d)", baseName.c_str(), sigbit.offset), }; padName = ""; netName = ""; - for (auto& name : netNames) { + for (auto &name : netNames) { if (constraintMap.count(name)) { auto constraint = constraintMap.at(name); padName = constraint.padName; @@ -241,17 +239,11 @@ if (pinmapMap.count(padName)) { // Choose a correct entry for the cell - auto entry = choosePinmapEntry( - pinmapMap.at(padName), - ioCellType - ); + auto entry = choosePinmapEntry(pinmapMap.at(padName), ioCellType); // Location string if (entry.count("x") && entry.count("y")) { - locName = stringf("X%sY%s", - entry.at("x").c_str(), - entry.at("y").c_str() - ); + locName = stringf("X%sY%s", entry.at("x").c_str(), entry.at("y").c_str()); } // Cell type @@ -264,24 +256,16 @@ } } - log("| %-10s | %-10s | %-8s | %-8s | %s\n", - netName.c_str(), - padName.c_str(), - locName.c_str(), - cellType.c_str(), - cell->name.c_str() - ); + log("| %-10s | %-10s | %-8s | %-8s | %s\n", netName.c_str(), padName.c_str(), locName.c_str(), cellType.c_str(), cell->name.c_str()); // Annotate the cell by setting its parameters - cell->setParam(RTLIL::escape_id("IO_PAD"), padName); - cell->setParam(RTLIL::escape_id("IO_LOC"), locName); + cell->setParam(RTLIL::escape_id("IO_PAD"), padName); + cell->setParam(RTLIL::escape_id("IO_LOC"), locName); cell->setParam(RTLIL::escape_id("IO_TYPE"), cellType); } } - PinmapParser::Entry choosePinmapEntry( - const std::vector<PinmapParser::Entry>& a_Entries, - const IoCellType& a_IoCellType) + PinmapParser::Entry choosePinmapEntry(const std::vector<PinmapParser::Entry> &a_Entries, const IoCellType &a_IoCellType) { // No preferred types, pick the first one if (a_IoCellType.preferredTypes.empty()) { @@ -289,10 +273,10 @@ } // Loop over preferred types - for (auto& type : a_IoCellType.preferredTypes) { - + for (auto &type : a_IoCellType.preferredTypes) { + // Find an entry for that type. If found then return it. - for (auto& entry : a_Entries) { + for (auto &entry : a_Entries) { if (type == entry.at("type")) { return entry; }
diff --git a/sdc-plugin/buffers.cc b/sdc-plugin/buffers.cc index a48a26a..33aceee 100644 --- a/sdc-plugin/buffers.cc +++ b/sdc-plugin/buffers.cc
@@ -20,14 +20,12 @@ #include <cmath> const std::vector<std::string> Pll::inputs = {"CLKIN1", "CLKIN2"}; -const std::vector<std::string> Pll::outputs = {"CLKOUT0", "CLKOUT1", "CLKOUT2", - "CLKOUT3", "CLKOUT4", "CLKOUT5"}; +const std::vector<std::string> Pll::outputs = {"CLKOUT0", "CLKOUT1", "CLKOUT2", "CLKOUT3", "CLKOUT4", "CLKOUT5"}; const float Pll::delay = 0; const std::string Pll::name = "PLLE2_ADV"; -Pll::Pll(RTLIL::Cell* cell, float input_clock_period, - float input_clock_rising_edge) - : ClockDivider({"PLLE2_ADV"}) { +Pll::Pll(RTLIL::Cell *cell, float input_clock_period, float input_clock_rising_edge) : ClockDivider({"PLLE2_ADV"}) +{ assert(RTLIL::unescape_id(cell->type) == "PLLE2_ADV"); FetchParams(cell); CheckInputClockPeriod(cell, input_clock_period); @@ -35,73 +33,67 @@ CalculateOutputClockWaveforms(input_clock_rising_edge); } -void Pll::CheckInputClockPeriod(RTLIL::Cell* cell, float input_clock_period) { +void Pll::CheckInputClockPeriod(RTLIL::Cell *cell, float input_clock_period) +{ float abs_diff = fabs(ClkinPeriod() - input_clock_period); - bool approx_equal = abs_diff < std::max(ClkinPeriod(), input_clock_period) * - 10 * - std::numeric_limits<float>::epsilon(); + bool approx_equal = abs_diff < std::max(ClkinPeriod(), input_clock_period) * 10 * std::numeric_limits<float>::epsilon(); if (!approx_equal) { - log_cmd_error( - "CLKIN[1/2]_PERIOD doesn't match the virtual clock constraint " - "propagated to the CLKIN[1/2] input of the clock divider cell: " - "%s.\nInput clock period: %f, CLKIN[1/2]_PERIOD: %f\n", - RTLIL::id2cstr(cell->name), input_clock_period, ClkinPeriod()); + log_cmd_error("CLKIN[1/2]_PERIOD doesn't match the virtual clock constraint " + "propagated to the CLKIN[1/2] input of the clock divider cell: " + "%s.\nInput clock period: %f, CLKIN[1/2]_PERIOD: %f\n", + RTLIL::id2cstr(cell->name), input_clock_period, ClkinPeriod()); } } -void Pll::FetchParams(RTLIL::Cell* cell) { +void Pll::FetchParams(RTLIL::Cell *cell) +{ clkin1_period = FetchParam(cell, "CLKIN1_PERIOD", 0.0); clkin2_period = FetchParam(cell, "CLKIN2_PERIOD", 0.0); clk_mult = FetchParam(cell, "CLKFBOUT_MULT", 5.0); clk_fbout_phase = FetchParam(cell, "CLKFBOUT_PHASE", 0.0); divclk_divisor = FetchParam(cell, "DIVCLK_DIVIDE", 1.0); for (auto output : outputs) { - // CLKOUT[0-5]_DUTY_CYCLE - clkout_duty_cycle[output] = - FetchParam(cell, output + "_DUTY_CYCLE", 0.5); - // CLKOUT[0-5]_DIVIDE - clkout_divisor[output] = FetchParam(cell, output + "_DIVIDE", 1.0); - // CLKOUT[0-5]_PHASE - clkout_phase[output] = FetchParam(cell, output + "_PHASE", 0.0); + // CLKOUT[0-5]_DUTY_CYCLE + clkout_duty_cycle[output] = FetchParam(cell, output + "_DUTY_CYCLE", 0.5); + // CLKOUT[0-5]_DIVIDE + clkout_divisor[output] = FetchParam(cell, output + "_DIVIDE", 1.0); + // CLKOUT[0-5]_PHASE + clkout_phase[output] = FetchParam(cell, output + "_PHASE", 0.0); } } -void Pll::CalculateOutputClockPeriods() { +void Pll::CalculateOutputClockPeriods() +{ for (auto output : outputs) { - // CLKOUT[0-5]_PERIOD = CLKIN1_PERIOD * CLKOUT[0-5]_DIVIDE * - // DIVCLK_DIVIDE / CLKFBOUT_MULT - clkout_period[output] = ClkinPeriod() * clkout_divisor.at(output) / - clk_mult * divclk_divisor; + // CLKOUT[0-5]_PERIOD = CLKIN1_PERIOD * CLKOUT[0-5]_DIVIDE * + // DIVCLK_DIVIDE / CLKFBOUT_MULT + clkout_period[output] = ClkinPeriod() * clkout_divisor.at(output) / clk_mult * divclk_divisor; } } -void Pll::CalculateOutputClockWaveforms(float input_clock_rising_edge) { +void Pll::CalculateOutputClockWaveforms(float input_clock_rising_edge) +{ for (auto output : outputs) { - float output_clock_period = clkout_period.at(output); - clkout_rising_edge[output] = - fmod(input_clock_rising_edge - - (clk_fbout_phase / 360.0) * ClkinPeriod() + - output_clock_period * (clkout_phase[output] / 360.0), - output_clock_period); - clkout_falling_edge[output] = - fmod(clkout_rising_edge[output] + - clkout_duty_cycle[output] * output_clock_period, - output_clock_period); + float output_clock_period = clkout_period.at(output); + clkout_rising_edge[output] = + fmod(input_clock_rising_edge - (clk_fbout_phase / 360.0) * ClkinPeriod() + output_clock_period * (clkout_phase[output] / 360.0), + output_clock_period); + clkout_falling_edge[output] = fmod(clkout_rising_edge[output] + clkout_duty_cycle[output] * output_clock_period, output_clock_period); } } -float Pll::FetchParam(RTLIL::Cell* cell, std::string&& param_name, - float default_value) { +float Pll::FetchParam(RTLIL::Cell *cell, std::string &¶m_name, float default_value) +{ RTLIL::IdString param(RTLIL::escape_id(param_name)); if (cell->hasParam(param)) { - auto param_obj = cell->parameters.at(param); - std::string value; - if (param_obj.flags & RTLIL::CONST_FLAG_STRING) { - value = param_obj.decode_string(); - } else { - value = std::to_string(param_obj.as_int()); - } - return std::stof(value); + auto param_obj = cell->parameters.at(param); + std::string value; + if (param_obj.flags & RTLIL::CONST_FLAG_STRING) { + value = param_obj.decode_string(); + } else { + value = std::to_string(param_obj.as_int()); + } + return std::stof(value); } return default_value; }
diff --git a/sdc-plugin/buffers.h b/sdc-plugin/buffers.h index ba3faa4..bfa5a20 100644 --- a/sdc-plugin/buffers.h +++ b/sdc-plugin/buffers.h
@@ -18,16 +18,15 @@ #ifndef _BUFFERS_H_ #define _BUFFERS_H_ +#include "kernel/rtlil.h" #include <string> #include <unordered_map> #include <vector> -#include "kernel/rtlil.h" USING_YOSYS_NAMESPACE struct Buffer { - Buffer(float delay, const std::string& type, const std::string& output) - : delay(delay), type(type), output(output) {} + Buffer(float delay, const std::string &type, const std::string &output) : delay(delay), type(type), output(output) {} float delay; std::string type; std::string output; @@ -47,12 +46,10 @@ struct Pll : public ClockDivider { Pll() : ClockDivider({"PLLE2_ADV"}) {} - Pll(RTLIL::Cell* cell, float input_clock_period, - float input_clock_rising_edge); + Pll(RTLIL::Cell *cell, float input_clock_period, float input_clock_rising_edge); // Helper function to fetch a cell parameter or return a default value - static float FetchParam(RTLIL::Cell* cell, std::string&& param_name, - float default_value); + static float FetchParam(RTLIL::Cell *cell, std::string &¶m_name, float default_value); // Get the period of the input clock // TODO Add support for CLKINSEL @@ -65,13 +62,13 @@ std::unordered_map<std::string, float> clkout_rising_edge; std::unordered_map<std::string, float> clkout_falling_edge; - private: + private: // Approximate equality check of the input clock period and specified in // CLKIN[1/2]_PERIOD parameter - void CheckInputClockPeriod(RTLIL::Cell* cell, float input_clock_period); + void CheckInputClockPeriod(RTLIL::Cell *cell, float input_clock_period); // Fetch cell's parameters needed for further calculations - void FetchParams(RTLIL::Cell* cell); + void FetchParams(RTLIL::Cell *cell); // Calculate the period on the output clocks void CalculateOutputClockPeriods(); @@ -90,4 +87,4 @@ float clk_fbout_phase; }; -#endif // _BUFFERS_H_ +#endif // _BUFFERS_H_
diff --git a/sdc-plugin/clocks.cc b/sdc-plugin/clocks.cc index 865dd37..6dbb962 100644 --- a/sdc-plugin/clocks.cc +++ b/sdc-plugin/clocks.cc
@@ -16,141 +16,127 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "clocks.h" +#include "kernel/register.h" +#include "propagation.h" #include <cassert> #include <cmath> #include <regex> -#include "kernel/register.h" -#include "propagation.h" -void Clock::Add(const std::string& name, RTLIL::Wire* wire, float period, - float rising_edge, float falling_edge, ClockType type) { +void Clock::Add(const std::string &name, RTLIL::Wire *wire, float period, float rising_edge, float falling_edge, ClockType type) +{ wire->set_string_attribute(RTLIL::escape_id("CLOCK_SIGNAL"), "yes"); wire->set_bool_attribute(RTLIL::escape_id("IS_GENERATED"), type == GENERATED); wire->set_bool_attribute(RTLIL::escape_id("IS_EXPLICIT"), type == EXPLICIT); wire->set_bool_attribute(RTLIL::escape_id("IS_PROPAGATED"), type == PROPAGATED); wire->set_string_attribute(RTLIL::escape_id("CLASS"), "clock"); wire->set_string_attribute(RTLIL::escape_id("NAME"), name); - wire->set_string_attribute(RTLIL::escape_id("SOURCE_WIRES"), - Clock::WireName(wire)); - wire->set_string_attribute(RTLIL::escape_id("PERIOD"), - std::to_string(period)); - std::string waveform(std::to_string(rising_edge) + " " + - std::to_string(falling_edge)); + wire->set_string_attribute(RTLIL::escape_id("SOURCE_WIRES"), Clock::WireName(wire)); + wire->set_string_attribute(RTLIL::escape_id("PERIOD"), std::to_string(period)); + std::string waveform(std::to_string(rising_edge) + " " + std::to_string(falling_edge)); wire->set_string_attribute(RTLIL::escape_id("WAVEFORM"), waveform); } -void Clock::Add(const std::string& name, std::vector<RTLIL::Wire*> wires, - float period, float rising_edge, float falling_edge, ClockType type) { - std::for_each(wires.begin(), wires.end(), [&](RTLIL::Wire* wire) { - Add(name, wire, period, rising_edge, falling_edge, type); - }); +void Clock::Add(const std::string &name, std::vector<RTLIL::Wire *> wires, float period, float rising_edge, float falling_edge, ClockType type) +{ + std::for_each(wires.begin(), wires.end(), [&](RTLIL::Wire *wire) { Add(name, wire, period, rising_edge, falling_edge, type); }); } -void Clock::Add(RTLIL::Wire* wire, float period, float rising_edge, - float falling_edge, ClockType type) { +void Clock::Add(RTLIL::Wire *wire, float period, float rising_edge, float falling_edge, ClockType type) +{ Add(Clock::WireName(wire), wire, period, rising_edge, falling_edge, type); } -float Clock::Period(RTLIL::Wire* clock_wire) { +float Clock::Period(RTLIL::Wire *clock_wire) +{ if (!clock_wire->has_attribute(RTLIL::escape_id("PERIOD"))) { - log_cmd_error("PERIOD has not been specified on wire '%s'.\n", - WireName(clock_wire).c_str()); + log_cmd_error("PERIOD has not been specified on wire '%s'.\n", WireName(clock_wire).c_str()); } float period(0); std::string period_str; try { - period_str = - clock_wire->get_string_attribute(RTLIL::escape_id("PERIOD")); - period = std::stof(period_str); - } catch (const std::invalid_argument& e) { - log_cmd_error( - "Incorrect value '%s' specifed on PERIOD attribute for wire " - "'%s'.\nPERIOD needs to be a float value.\n", - period_str.c_str(), WireName(clock_wire).c_str()); + period_str = clock_wire->get_string_attribute(RTLIL::escape_id("PERIOD")); + period = std::stof(period_str); + } catch (const std::invalid_argument &e) { + log_cmd_error("Incorrect value '%s' specifed on PERIOD attribute for wire " + "'%s'.\nPERIOD needs to be a float value.\n", + period_str.c_str(), WireName(clock_wire).c_str()); } return period; } -std::pair<float, float> Clock::Waveform(RTLIL::Wire* clock_wire) { +std::pair<float, float> Clock::Waveform(RTLIL::Wire *clock_wire) +{ if (!clock_wire->has_attribute(RTLIL::escape_id("WAVEFORM"))) { - float period(Period(clock_wire)); - if (!period) { - log_cmd_error( - "Neither PERIOD nor WAVEFORM has been specified for wire %s\n", - WireName(clock_wire).c_str()); - return std::make_pair(0, 0); - } - float falling_edge = period / 2; - log_warning( - "Waveform has not been specified on wire '%s'.\nDefault value {0 %f} " - "will be used\n", - WireName(clock_wire).c_str(), falling_edge); - return std::make_pair(0, falling_edge); + float period(Period(clock_wire)); + if (!period) { + log_cmd_error("Neither PERIOD nor WAVEFORM has been specified for wire %s\n", WireName(clock_wire).c_str()); + return std::make_pair(0, 0); + } + float falling_edge = period / 2; + log_warning("Waveform has not been specified on wire '%s'.\nDefault value {0 %f} " + "will be used\n", + WireName(clock_wire).c_str(), falling_edge); + return std::make_pair(0, falling_edge); } float rising_edge(0); float falling_edge(0); - std::string waveform( - clock_wire->get_string_attribute(RTLIL::escape_id("WAVEFORM"))); - if (std::sscanf(waveform.c_str(), "%f %f", &rising_edge, &falling_edge) != - 2) { - log_cmd_error( - "Incorrect value '%s' specifed on WAVEFORM attribute for wire " - "'%s'.\nWAVEFORM needs to be specified in form of '<rising_edge> " - "<falling_edge>' where the edge values are floats.\n", - waveform.c_str(), WireName(clock_wire).c_str()); + std::string waveform(clock_wire->get_string_attribute(RTLIL::escape_id("WAVEFORM"))); + if (std::sscanf(waveform.c_str(), "%f %f", &rising_edge, &falling_edge) != 2) { + log_cmd_error("Incorrect value '%s' specifed on WAVEFORM attribute for wire " + "'%s'.\nWAVEFORM needs to be specified in form of '<rising_edge> " + "<falling_edge>' where the edge values are floats.\n", + waveform.c_str(), WireName(clock_wire).c_str()); } return std::make_pair(rising_edge, falling_edge); } -float Clock::RisingEdge(RTLIL::Wire* clock_wire) { - return Waveform(clock_wire).first; -} +float Clock::RisingEdge(RTLIL::Wire *clock_wire) { return Waveform(clock_wire).first; } -float Clock::FallingEdge(RTLIL::Wire* clock_wire) { - return Waveform(clock_wire).second; -} +float Clock::FallingEdge(RTLIL::Wire *clock_wire) { return Waveform(clock_wire).second; } -std::string Clock::Name(RTLIL::Wire* clock_wire) { +std::string Clock::Name(RTLIL::Wire *clock_wire) +{ if (clock_wire->has_attribute(RTLIL::escape_id("NAME"))) { - return clock_wire->get_string_attribute(RTLIL::escape_id("NAME")); + return clock_wire->get_string_attribute(RTLIL::escape_id("NAME")); } return WireName(clock_wire); } -std::string Clock::WireName(RTLIL::Wire* clock_wire) { +std::string Clock::WireName(RTLIL::Wire *clock_wire) +{ if (!clock_wire) { - return std::string(); + return std::string(); } return AddEscaping(RTLIL::unescape_id(clock_wire->name)); } -std::string Clock::SourceWireName(RTLIL::Wire* clock_wire) { +std::string Clock::SourceWireName(RTLIL::Wire *clock_wire) +{ if (clock_wire->has_attribute(RTLIL::escape_id("SOURCE_WIRES"))) { - return clock_wire->get_string_attribute(RTLIL::escape_id("SOURCE_WIRES")); + return clock_wire->get_string_attribute(RTLIL::escape_id("SOURCE_WIRES")); } return Name(clock_wire); } -bool Clock::GetClockWireBoolAttribute(RTLIL::Wire* wire, const std::string& attribute_name) { +bool Clock::GetClockWireBoolAttribute(RTLIL::Wire *wire, const std::string &attribute_name) +{ if (wire->has_attribute(RTLIL::escape_id(attribute_name))) { - return wire->get_bool_attribute(RTLIL::escape_id(attribute_name)); + return wire->get_bool_attribute(RTLIL::escape_id(attribute_name)); } return false; } -const std::map<std::string, RTLIL::Wire*> Clocks::GetClocks( - RTLIL::Design* design) { - std::map<std::string, RTLIL::Wire*> clock_wires; - RTLIL::Module* top_module = design->top_module(); - for (auto& wire_obj : top_module->wires_) { - auto& wire = wire_obj.second; - if (wire->has_attribute(RTLIL::escape_id("CLOCK_SIGNAL"))) { - if (wire->get_string_attribute(RTLIL::escape_id("CLOCK_SIGNAL")) == - "yes") { - clock_wires.insert(std::make_pair(Clock::WireName(wire), wire)); - } - } +const std::map<std::string, RTLIL::Wire *> Clocks::GetClocks(RTLIL::Design *design) +{ + std::map<std::string, RTLIL::Wire *> clock_wires; + RTLIL::Module *top_module = design->top_module(); + for (auto &wire_obj : top_module->wires_) { + auto &wire = wire_obj.second; + if (wire->has_attribute(RTLIL::escape_id("CLOCK_SIGNAL"))) { + if (wire->get_string_attribute(RTLIL::escape_id("CLOCK_SIGNAL")) == "yes") { + clock_wires.insert(std::make_pair(Clock::WireName(wire), wire)); + } + } } return clock_wires; } -
diff --git a/sdc-plugin/clocks.h b/sdc-plugin/clocks.h index f15858b..b11d1c0 100644 --- a/sdc-plugin/clocks.h +++ b/sdc-plugin/clocks.h
@@ -18,10 +18,10 @@ #ifndef _CLOCKS_H_ #define _CLOCKS_H_ -#include <map> -#include <vector> #include "buffers.h" #include "kernel/rtlil.h" +#include <map> +#include <vector> USING_YOSYS_NAMESPACE @@ -30,49 +30,40 @@ class ClockDividerPropagation; class Propagation; -class Clock { - public: +class Clock +{ + public: // We distinguish the following types of clock: // * EXPLICIT - added with create_clocks command // * GENERATED - propagated from explicit clocks changing the clock's parameters // * PROPAGATED - propagated from explicit clocks but with the same parameters as the driver enum ClockType { EXPLICIT, GENERATED, PROPAGATED }; - static void Add(const std::string& name, RTLIL::Wire* wire, float period, - float rising_edge, float falling_edge, ClockType type); - static void Add(const std::string& name, std::vector<RTLIL::Wire*> wires, - float period, float rising_edge, float falling_edge, ClockType type); - static void Add(RTLIL::Wire* wire, float period, float rising_edge, - float falling_edge, ClockType type); - static float Period(RTLIL::Wire* clock_wire); - static float RisingEdge(RTLIL::Wire* clock_wire); - static float FallingEdge(RTLIL::Wire* clock_wire); - static std::string Name(RTLIL::Wire* clock_wire); - static std::string WireName(RTLIL::Wire* wire); - static std::string AddEscaping(const std::string& name) { - return std::regex_replace(name, std::regex{"\\$"}, "\\$"); - } - static std::string SourceWireName(RTLIL::Wire* clock_wire); - static bool IsPropagated(RTLIL::Wire* wire) { - return GetClockWireBoolAttribute(wire, "IS_PROPAGATED"); - } + static void Add(const std::string &name, RTLIL::Wire *wire, float period, float rising_edge, float falling_edge, ClockType type); + static void Add(const std::string &name, std::vector<RTLIL::Wire *> wires, float period, float rising_edge, float falling_edge, ClockType type); + static void Add(RTLIL::Wire *wire, float period, float rising_edge, float falling_edge, ClockType type); + static float Period(RTLIL::Wire *clock_wire); + static float RisingEdge(RTLIL::Wire *clock_wire); + static float FallingEdge(RTLIL::Wire *clock_wire); + static std::string Name(RTLIL::Wire *clock_wire); + static std::string WireName(RTLIL::Wire *wire); + static std::string AddEscaping(const std::string &name) { return std::regex_replace(name, std::regex{"\\$"}, "\\$"); } + static std::string SourceWireName(RTLIL::Wire *clock_wire); + static bool IsPropagated(RTLIL::Wire *wire) { return GetClockWireBoolAttribute(wire, "IS_PROPAGATED"); } - static bool IsGenerated(RTLIL::Wire* wire) { - return GetClockWireBoolAttribute(wire, "IS_GENERATED"); - } + static bool IsGenerated(RTLIL::Wire *wire) { return GetClockWireBoolAttribute(wire, "IS_GENERATED"); } - static bool IsExplicit(RTLIL::Wire* wire) { - return GetClockWireBoolAttribute(wire, "IS_EXPLICIT"); - } + static bool IsExplicit(RTLIL::Wire *wire) { return GetClockWireBoolAttribute(wire, "IS_EXPLICIT"); } - private: - static std::pair<float, float> Waveform(RTLIL::Wire* clock_wire); + private: + static std::pair<float, float> Waveform(RTLIL::Wire *clock_wire); - static bool GetClockWireBoolAttribute(RTLIL::Wire* wire, const std::string& attribute_name); + static bool GetClockWireBoolAttribute(RTLIL::Wire *wire, const std::string &attribute_name); }; -class Clocks { - public: - static const std::map<std::string, RTLIL::Wire*> GetClocks(RTLIL::Design* design); +class Clocks +{ + public: + static const std::map<std::string, RTLIL::Wire *> GetClocks(RTLIL::Design *design); }; -#endif // _CLOCKS_H_ +#endif // _CLOCKS_H_
diff --git a/sdc-plugin/propagation.cc b/sdc-plugin/propagation.cc index 460efbf..cfee89a 100644 --- a/sdc-plugin/propagation.cc +++ b/sdc-plugin/propagation.cc
@@ -20,180 +20,156 @@ USING_YOSYS_NAMESPACE -void Propagation::PropagateThroughBuffers(Buffer buffer) { - for (auto& clock : Clocks::GetClocks(design_)) { - auto& clock_wire = clock.second; +void Propagation::PropagateThroughBuffers(Buffer buffer) +{ + for (auto &clock : Clocks::GetClocks(design_)) { + auto &clock_wire = clock.second; #ifdef SDC_DEBUG - log("Clock wire %s\n", Clock::WireName(clock_wire).c_str()); + log("Clock wire %s\n", Clock::WireName(clock_wire).c_str()); #endif - auto buf_wires = - FindSinkWiresForCellType(clock_wire, buffer.type, buffer.output); - int path_delay(0); - for (auto wire : buf_wires) { + auto buf_wires = FindSinkWiresForCellType(clock_wire, buffer.type, buffer.output); + int path_delay(0); + for (auto wire : buf_wires) { #ifdef SDC_DEBUG - log("%s wire: %s\n", buffer.type.c_str(), - RTLIL::id2cstr(wire->name)); + log("%s wire: %s\n", buffer.type.c_str(), RTLIL::id2cstr(wire->name)); #endif - path_delay += buffer.delay; - Clock::Add(wire, Clock::Period(clock_wire), - Clock::RisingEdge(clock_wire) + path_delay, - Clock::FallingEdge(clock_wire) + path_delay, Clock::PROPAGATED); - } + path_delay += buffer.delay; + Clock::Add(wire, Clock::Period(clock_wire), Clock::RisingEdge(clock_wire) + path_delay, Clock::FallingEdge(clock_wire) + path_delay, + Clock::PROPAGATED); + } } } -std::vector<RTLIL::Wire*> Propagation::FindSinkWiresForCellType( - RTLIL::Wire* driver_wire, const std::string& cell_type, - const std::string& cell_port) { - std::vector<RTLIL::Wire*> wires; +std::vector<RTLIL::Wire *> Propagation::FindSinkWiresForCellType(RTLIL::Wire *driver_wire, const std::string &cell_type, const std::string &cell_port) +{ + std::vector<RTLIL::Wire *> wires; if (!driver_wire) { - return wires; + return wires; } auto cell = FindSinkCellOfType(driver_wire, cell_type); - RTLIL::Wire* wire = FindSinkWireOnPort(cell, cell_port); + RTLIL::Wire *wire = FindSinkWireOnPort(cell, cell_port); if (wire) { - wires.push_back(wire); - auto further_wires = - FindSinkWiresForCellType(wire, cell_type, cell_port); - std::copy(further_wires.begin(), further_wires.end(), - std::back_inserter(wires)); + wires.push_back(wire); + auto further_wires = FindSinkWiresForCellType(wire, cell_type, cell_port); + std::copy(further_wires.begin(), further_wires.end(), std::back_inserter(wires)); } return wires; } -RTLIL::Cell* Propagation::FindSinkCellOfType(RTLIL::Wire* wire, - const std::string& type) { - RTLIL::Cell* sink_cell = NULL; +RTLIL::Cell *Propagation::FindSinkCellOfType(RTLIL::Wire *wire, const std::string &type) +{ + RTLIL::Cell *sink_cell = NULL; if (!wire) { - return sink_cell; + return sink_cell; } - RTLIL::Module* top_module = design_->top_module(); + RTLIL::Module *top_module = design_->top_module(); assert(top_module); - std::string base_selection = - top_module->name.str() + "/w:" + wire->name.str(); - pass_->extra_args(std::vector<std::string>{base_selection, "%co:+" + type, - base_selection, "%d"}, - 0, design_); + std::string base_selection = top_module->name.str() + "/w:" + wire->name.str(); + pass_->extra_args(std::vector<std::string>{base_selection, "%co:+" + type, base_selection, "%d"}, 0, design_); auto selected_cells = top_module->selected_cells(); // FIXME Handle more than one sink assert(selected_cells.size() <= 1); if (selected_cells.size() > 0) { - sink_cell = selected_cells.at(0); + sink_cell = selected_cells.at(0); #ifdef SDC_DEBUG - log("Found sink cell: %s\n", - RTLIL::unescape_id(sink_cell->name).c_str()); + log("Found sink cell: %s\n", RTLIL::unescape_id(sink_cell->name).c_str()); #endif } return sink_cell; } -RTLIL::Cell* Propagation::FindSinkCellOnPort(RTLIL::Wire* wire, - const std::string& port) { - RTLIL::Cell* sink_cell = NULL; +RTLIL::Cell *Propagation::FindSinkCellOnPort(RTLIL::Wire *wire, const std::string &port) +{ + RTLIL::Cell *sink_cell = NULL; if (!wire) { - return sink_cell; + return sink_cell; } - RTLIL::Module* top_module = design_->top_module(); + RTLIL::Module *top_module = design_->top_module(); assert(top_module); - std::string base_selection = - top_module->name.str() + "/w:" + wire->name.str(); - pass_->extra_args( - std::vector<std::string>{base_selection, "%co:+[" + port + "]", - base_selection, "%d"}, - 0, design_); + std::string base_selection = top_module->name.str() + "/w:" + wire->name.str(); + pass_->extra_args(std::vector<std::string>{base_selection, "%co:+[" + port + "]", base_selection, "%d"}, 0, design_); auto selected_cells = top_module->selected_cells(); // FIXME Handle more than one sink assert(selected_cells.size() <= 1); if (selected_cells.size() > 0) { - sink_cell = selected_cells.at(0); + sink_cell = selected_cells.at(0); #ifdef SDC_DEBUG - log("Found sink cell: %s\n", - RTLIL::unescape_id(sink_cell->name).c_str()); + log("Found sink cell: %s\n", RTLIL::unescape_id(sink_cell->name).c_str()); #endif } return sink_cell; } -bool Propagation::WireHasSinkCell(RTLIL::Wire* wire) { +bool Propagation::WireHasSinkCell(RTLIL::Wire *wire) +{ if (!wire) { - return false; + return false; } - RTLIL::Module* top_module = design_->top_module(); + RTLIL::Module *top_module = design_->top_module(); assert(top_module); - std::string base_selection = - top_module->name.str() + "/w:" + wire->name.str(); - pass_->extra_args( - std::vector<std::string>{base_selection, "%co:*", - base_selection, "%d"}, - 0, design_); + std::string base_selection = top_module->name.str() + "/w:" + wire->name.str(); + pass_->extra_args(std::vector<std::string>{base_selection, "%co:*", base_selection, "%d"}, 0, design_); auto selected_cells = top_module->selected_cells(); return selected_cells.size() > 0; } -RTLIL::Wire* Propagation::FindSinkWireOnPort(RTLIL::Cell* cell, - const std::string& port_name) { - RTLIL::Wire* sink_wire = NULL; +RTLIL::Wire *Propagation::FindSinkWireOnPort(RTLIL::Cell *cell, const std::string &port_name) +{ + RTLIL::Wire *sink_wire = NULL; if (!cell) { - return sink_wire; + return sink_wire; } - RTLIL::Module* top_module = design_->top_module(); + RTLIL::Module *top_module = design_->top_module(); assert(top_module); - std::string base_selection = - top_module->name.str() + "/c:" + cell->name.str(); - pass_->extra_args( - std::vector<std::string>{base_selection, "%co:+[" + port_name + "]", - base_selection, "%d"}, - 0, design_); + std::string base_selection = top_module->name.str() + "/c:" + cell->name.str(); + pass_->extra_args(std::vector<std::string>{base_selection, "%co:+[" + port_name + "]", base_selection, "%d"}, 0, design_); auto selected_wires = top_module->selected_wires(); // FIXME Handle more than one sink assert(selected_wires.size() <= 1); if (selected_wires.size() > 0) { - sink_wire = selected_wires.at(0); + sink_wire = selected_wires.at(0); #ifdef SDC_DEBUG - log("Found sink wire: %s\n", - RTLIL::unescape_id(sink_wire->name).c_str()); + log("Found sink wire: %s\n", RTLIL::unescape_id(sink_wire->name).c_str()); #endif } return sink_wire; } -void NaturalPropagation::Run() { +void NaturalPropagation::Run() +{ #ifdef SDC_DEBUG log("Start natural clock propagation\n"); #endif - for (auto& clock : Clocks::GetClocks(design_)) { - auto& clock_wire = clock.second; + for (auto &clock : Clocks::GetClocks(design_)) { + auto &clock_wire = clock.second; #ifdef SDC_DEBUG - log("Processing clock %s\n", RTLIL::id2cstr(clock_wire->name)); + log("Processing clock %s\n", RTLIL::id2cstr(clock_wire->name)); #endif - auto aliases = FindAliasWires(clock_wire); - Clock::Add(Clock::WireName(clock_wire), aliases, - Clock::Period(clock_wire), Clock::RisingEdge(clock_wire), - Clock::FallingEdge(clock_wire), Clock::PROPAGATED); + auto aliases = FindAliasWires(clock_wire); + Clock::Add(Clock::WireName(clock_wire), aliases, Clock::Period(clock_wire), Clock::RisingEdge(clock_wire), Clock::FallingEdge(clock_wire), + Clock::PROPAGATED); } #ifdef SDC_DEBUG log("Finish natural clock propagation\n\n"); #endif } -std::vector<RTLIL::Wire*> NaturalPropagation::FindAliasWires( - RTLIL::Wire* wire) { - RTLIL::Module* top_module = design_->top_module(); +std::vector<RTLIL::Wire *> NaturalPropagation::FindAliasWires(RTLIL::Wire *wire) +{ + RTLIL::Module *top_module = design_->top_module(); assert(top_module); - std::vector<RTLIL::Wire*> alias_wires; - pass_->extra_args( - std::vector<std::string>{ - top_module->name.str() + "/w:" + wire->name.str(), "%a"}, - 0, design_); + std::vector<RTLIL::Wire *> alias_wires; + pass_->extra_args(std::vector<std::string>{top_module->name.str() + "/w:" + wire->name.str(), "%a"}, 0, design_); for (auto module : design_->selected_modules()) { - for (auto wire : module->selected_wires()) { - alias_wires.push_back(wire); - } + for (auto wire : module->selected_wires()) { + alias_wires.push_back(wire); + } } return alias_wires; } -void BufferPropagation::Run() { +void BufferPropagation::Run() +{ #ifdef SDC_DEBUG log("Start buffer clock propagation\n"); log("IBUF pass\n"); @@ -208,7 +184,8 @@ #endif } -void ClockDividerPropagation::Run() { +void ClockDividerPropagation::Run() +{ #ifdef SDC_DEBUG log("Start clock divider clock propagation\n"); #endif @@ -219,45 +196,42 @@ #endif } -void ClockDividerPropagation::PropagateThroughClockDividers( - ClockDivider divider) { - for (auto& clock : Clocks::GetClocks(design_)) { - auto& clock_wire = clock.second; +void ClockDividerPropagation::PropagateThroughClockDividers(ClockDivider divider) +{ + for (auto &clock : Clocks::GetClocks(design_)) { + auto &clock_wire = clock.second; #ifdef SDC_DEBUG - log("Processing clock %s\n", Clock::WireName(clock_wire).c_str()); + log("Processing clock %s\n", Clock::WireName(clock_wire).c_str()); #endif - PropagateClocksForCellType(clock_wire, divider.type); + PropagateClocksForCellType(clock_wire, divider.type); } } -void ClockDividerPropagation::PropagateClocksForCellType( - RTLIL::Wire* driver_wire, const std::string& cell_type) { +void ClockDividerPropagation::PropagateClocksForCellType(RTLIL::Wire *driver_wire, const std::string &cell_type) +{ if (cell_type == "PLLE2_ADV") { - RTLIL::Cell* cell = NULL; - for (auto input : Pll::inputs) { - cell = FindSinkCellOnPort(driver_wire, input); - if (cell and RTLIL::unescape_id(cell->type) == cell_type) { - break; - } - } - if (!cell) { - return; - } - Pll pll(cell, Clock::Period(driver_wire), - Clock::RisingEdge(driver_wire)); - for (auto output : Pll::outputs) { - RTLIL::Wire* wire = FindSinkWireOnPort(cell, output); - // Don't add clocks on dangling wires - // TODO Remove the workaround with the WireHasSinkCell check once the following issue is fixed: - // https://github.com/SymbiFlow/yosys-symbiflow-plugins/issues/59 - if (wire && WireHasSinkCell(wire)) { - float clkout_period(pll.clkout_period.at(output)); - float clkout_rising_edge(pll.clkout_rising_edge.at(output)); - float clkout_falling_edge(pll.clkout_falling_edge.at(output)); - Clock::Add(wire, clkout_period, clkout_rising_edge, - clkout_falling_edge, Clock::GENERATED); - } - } + RTLIL::Cell *cell = NULL; + for (auto input : Pll::inputs) { + cell = FindSinkCellOnPort(driver_wire, input); + if (cell and RTLIL::unescape_id(cell->type) == cell_type) { + break; + } + } + if (!cell) { + return; + } + Pll pll(cell, Clock::Period(driver_wire), Clock::RisingEdge(driver_wire)); + for (auto output : Pll::outputs) { + RTLIL::Wire *wire = FindSinkWireOnPort(cell, output); + // Don't add clocks on dangling wires + // TODO Remove the workaround with the WireHasSinkCell check once the following issue is fixed: + // https://github.com/SymbiFlow/yosys-symbiflow-plugins/issues/59 + if (wire && WireHasSinkCell(wire)) { + float clkout_period(pll.clkout_period.at(output)); + float clkout_rising_edge(pll.clkout_rising_edge.at(output)); + float clkout_falling_edge(pll.clkout_falling_edge.at(output)); + Clock::Add(wire, clkout_period, clkout_rising_edge, clkout_falling_edge, Clock::GENERATED); + } + } } } -
diff --git a/sdc-plugin/propagation.h b/sdc-plugin/propagation.h index 3efd984..6b0f755 100644 --- a/sdc-plugin/propagation.h +++ b/sdc-plugin/propagation.h
@@ -22,56 +22,52 @@ USING_YOSYS_NAMESPACE -class Propagation { - public: - Propagation(RTLIL::Design* design, Pass* pass) - : design_(design), pass_(pass) {} +class Propagation +{ + public: + Propagation(RTLIL::Design *design, Pass *pass) : design_(design), pass_(pass) {} virtual ~Propagation() {} virtual void Run() = 0; - protected: - RTLIL::Design* design_; - Pass* pass_; + protected: + RTLIL::Design *design_; + Pass *pass_; // This propagation doesn't change the clock so the sink wire is only marked // as propagated clock signal, but has the properties of the driving clock void PropagateThroughBuffers(Buffer buffer); - std::vector<RTLIL::Wire*> FindSinkWiresForCellType( - RTLIL::Wire* driver_wire, const std::string& cell_type, - const std::string& cell_port); - RTLIL::Cell* FindSinkCellOfType(RTLIL::Wire* wire, const std::string& type); - RTLIL::Cell* FindSinkCellOnPort(RTLIL::Wire* wire, const std::string& port); - RTLIL::Wire* FindSinkWireOnPort(RTLIL::Cell* cell, - const std::string& port_name); - bool WireHasSinkCell(RTLIL::Wire* wire); + std::vector<RTLIL::Wire *> FindSinkWiresForCellType(RTLIL::Wire *driver_wire, const std::string &cell_type, const std::string &cell_port); + RTLIL::Cell *FindSinkCellOfType(RTLIL::Wire *wire, const std::string &type); + RTLIL::Cell *FindSinkCellOnPort(RTLIL::Wire *wire, const std::string &port); + RTLIL::Wire *FindSinkWireOnPort(RTLIL::Cell *cell, const std::string &port_name); + bool WireHasSinkCell(RTLIL::Wire *wire); }; -class NaturalPropagation : public Propagation { - public: - NaturalPropagation(RTLIL::Design* design, Pass* pass) - : Propagation(design, pass) {} +class NaturalPropagation : public Propagation +{ + public: + NaturalPropagation(RTLIL::Design *design, Pass *pass) : Propagation(design, pass) {} void Run() override; - std::vector<RTLIL::Wire*> FindAliasWires(RTLIL::Wire* wire); + std::vector<RTLIL::Wire *> FindAliasWires(RTLIL::Wire *wire); }; -class BufferPropagation : public Propagation { - public: - BufferPropagation(RTLIL::Design* design, Pass* pass) - : Propagation(design, pass) {} +class BufferPropagation : public Propagation +{ + public: + BufferPropagation(RTLIL::Design *design, Pass *pass) : Propagation(design, pass) {} void Run() override; }; -class ClockDividerPropagation : public Propagation { - public: - ClockDividerPropagation(RTLIL::Design* design, Pass* pass) - : Propagation(design, pass) {} +class ClockDividerPropagation : public Propagation +{ + public: + ClockDividerPropagation(RTLIL::Design *design, Pass *pass) : Propagation(design, pass) {} void Run() override; - void PropagateClocksForCellType(RTLIL::Wire* driver_wire, - const std::string& cell_type); + void PropagateClocksForCellType(RTLIL::Wire *driver_wire, const std::string &cell_type); void PropagateThroughClockDividers(ClockDivider divider); }; -#endif // PROPAGATION_H_ +#endif // PROPAGATION_H_
diff --git a/sdc-plugin/sdc.cc b/sdc-plugin/sdc.cc index 6ddaf01..dd058d9 100644 --- a/sdc-plugin/sdc.cc +++ b/sdc-plugin/sdc.cc
@@ -35,300 +35,290 @@ struct ReadSdcCmd : public Frontend { ReadSdcCmd() : Frontend("sdc", "Read SDC file") {} - void help() override { - log("\n"); - log(" read_sdc <filename>\n"); - log("\n"); - log("Read SDC file.\n"); - log("\n"); + void help() override + { + log("\n"); + log(" read_sdc <filename>\n"); + log("\n"); + log("Read SDC file.\n"); + log("\n"); } - void execute(std::istream*& f, std::string filename, - std::vector<std::string> args, RTLIL::Design*) override { - if (args.size() < 2) { - log_cmd_error("Missing script file.\n"); - } - log("\nReading clock constraints file(SDC)\n\n"); - size_t argidx = 1; - extra_args(f, filename, args, argidx); - std::string content{std::istreambuf_iterator<char>(*f), - std::istreambuf_iterator<char>()}; - log("%s\n", content.c_str()); - Tcl_Interp* interp = yosys_get_tcl_interp(); - if (Tcl_EvalFile(interp, args[argidx].c_str()) != TCL_OK) { - log_cmd_error("TCL interpreter returned an error: %s\n", - Tcl_GetStringResult(interp)); - } + void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *) override + { + if (args.size() < 2) { + log_cmd_error("Missing script file.\n"); + } + log("\nReading clock constraints file(SDC)\n\n"); + size_t argidx = 1; + extra_args(f, filename, args, argidx); + std::string content{std::istreambuf_iterator<char>(*f), std::istreambuf_iterator<char>()}; + log("%s\n", content.c_str()); + Tcl_Interp *interp = yosys_get_tcl_interp(); + if (Tcl_EvalFile(interp, args[argidx].c_str()) != TCL_OK) { + log_cmd_error("TCL interpreter returned an error: %s\n", Tcl_GetStringResult(interp)); + } } }; struct WriteSdcCmd : public Backend { - WriteSdcCmd(SdcWriter& sdc_writer) - : Backend("sdc", "Write SDC file"), sdc_writer_(sdc_writer) {} + WriteSdcCmd(SdcWriter &sdc_writer) : Backend("sdc", "Write SDC file"), sdc_writer_(sdc_writer) {} - void help() override { - log("\n"); - log(" write_sdc <filename>\n"); - log("\n"); - log("Write SDC file.\n"); - log("\n"); + void help() override + { + log("\n"); + log(" write_sdc <filename>\n"); + log("\n"); + log("Write SDC file.\n"); + log("\n"); } - void execute(std::ostream*& f, std::string filename, - std::vector<std::string> args, - RTLIL::Design* design) override { - if (args.size() < 2) { - log_cmd_error("Missing output file.\n"); - } - log("\nWriting out clock constraints file(SDC)\n"); - extra_args(f, filename, args, 1); - sdc_writer_.WriteSdc(design, *f); + void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override + { + if (args.size() < 2) { + log_cmd_error("Missing output file.\n"); + } + log("\nWriting out clock constraints file(SDC)\n"); + extra_args(f, filename, args, 1); + sdc_writer_.WriteSdc(design, *f); } - SdcWriter& sdc_writer_; + SdcWriter &sdc_writer_; }; struct CreateClockCmd : public Pass { CreateClockCmd() : Pass("create_clock", "Create clock object") {} - void help() override { - log("\n"); - log(" create_clock [ -name clock_name ] -period period_value " - "[-waveform <edge_list>] <target>\n"); - log("Define a clock.\n"); - log("If name is not specified then the name of the first target is " - "selected as the clock's name.\n"); - log("Period is expressed in nanoseconds.\n"); - log("The waveform option specifies the duty cycle (the rising a " - "falling edges) of the clock.\n"); - log("It is specified as a list of two elements/time values: the first " - "rising edge and the next falling edge.\n"); - log("\n"); + void help() override + { + log("\n"); + log(" create_clock [ -name clock_name ] -period period_value " + "[-waveform <edge_list>] <target>\n"); + log("Define a clock.\n"); + log("If name is not specified then the name of the first target is " + "selected as the clock's name.\n"); + log("Period is expressed in nanoseconds.\n"); + log("The waveform option specifies the duty cycle (the rising a " + "falling edges) of the clock.\n"); + log("It is specified as a list of two elements/time values: the first " + "rising edge and the next falling edge.\n"); + log("\n"); } - void execute(std::vector<std::string> args, - RTLIL::Design* design) override { - size_t argidx; - std::string name; - bool is_waveform_specified(false); - float rising_edge(0); - float falling_edge(0); - float period(0); - if (args.size() < 4) { - log_cmd_error("Incorrect number of arguments\n"); - } - for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-name" && argidx + 1 < args.size()) { - name = args[++argidx]; - continue; - } - if (arg == "-period" && argidx + 1 < args.size()) { - period = std::stof(args[++argidx]); - continue; - } - if (arg == "-waveform" && argidx + 1 < args.size()) { - std::string edges(args[++argidx]); - std::copy_if(edges.begin(), edges.end(), edges.begin(), - [](char c) { return c != '{' or c != '}'; }); - std::stringstream ss(edges); - ss >> rising_edge >> falling_edge; - is_waveform_specified = true; - continue; - } - break; - } - if (period <= 0) { - log_cmd_error("Incorrect period value\n"); - } - // Add "w:" prefix to selection arguments to enforce wire object - // selection - AddWirePrefix(args, argidx); - extra_args(args, argidx, design); - // If clock name is not specified then take the name of the first target - std::vector<RTLIL::Wire*> selected_wires; - for (auto module : design->modules()) { - if (!design->selected(module)) { - continue; - } - for (auto wire : module->wires()) { - if (design->selected(module, wire)) { + void execute(std::vector<std::string> args, RTLIL::Design *design) override + { + size_t argidx; + std::string name; + bool is_waveform_specified(false); + float rising_edge(0); + float falling_edge(0); + float period(0); + if (args.size() < 4) { + log_cmd_error("Incorrect number of arguments\n"); + } + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if (arg == "-name" && argidx + 1 < args.size()) { + name = args[++argidx]; + continue; + } + if (arg == "-period" && argidx + 1 < args.size()) { + period = std::stof(args[++argidx]); + continue; + } + if (arg == "-waveform" && argidx + 1 < args.size()) { + std::string edges(args[++argidx]); + std::copy_if(edges.begin(), edges.end(), edges.begin(), [](char c) { return c != '{' or c != '}'; }); + std::stringstream ss(edges); + ss >> rising_edge >> falling_edge; + is_waveform_specified = true; + continue; + } + break; + } + if (period <= 0) { + log_cmd_error("Incorrect period value\n"); + } + // Add "w:" prefix to selection arguments to enforce wire object + // selection + AddWirePrefix(args, argidx); + extra_args(args, argidx, design); + // If clock name is not specified then take the name of the first target + std::vector<RTLIL::Wire *> selected_wires; + for (auto module : design->modules()) { + if (!design->selected(module)) { + continue; + } + for (auto wire : module->wires()) { + if (design->selected(module, wire)) { #ifdef SDC_DEBUG - log("Selected wire %s\n", - RTLIL::unescape_id(wire->name).c_str()); + log("Selected wire %s\n", RTLIL::unescape_id(wire->name).c_str()); #endif - selected_wires.push_back(wire); - } - } - } - if (selected_wires.size() == 0) { - log_cmd_error("Target selection is empty\n"); - } - if (name.empty()) { - name = RTLIL::unescape_id(selected_wires.at(0)->name); - } - if (!is_waveform_specified) { - rising_edge = 0; - falling_edge = period / 2; - } - Clock::Add(name, selected_wires, period, rising_edge, falling_edge, Clock::EXPLICIT); + selected_wires.push_back(wire); + } + } + } + if (selected_wires.size() == 0) { + log_cmd_error("Target selection is empty\n"); + } + if (name.empty()) { + name = RTLIL::unescape_id(selected_wires.at(0)->name); + } + if (!is_waveform_specified) { + rising_edge = 0; + falling_edge = period / 2; + } + Clock::Add(name, selected_wires, period, rising_edge, falling_edge, Clock::EXPLICIT); } - void AddWirePrefix(std::vector<std::string>& args, size_t argidx) { - auto selection_begin = args.begin() + argidx; - std::transform(selection_begin, args.end(), selection_begin, - [](std::string& w) { return "w:" + w; }); + void AddWirePrefix(std::vector<std::string> &args, size_t argidx) + { + auto selection_begin = args.begin() + argidx; + std::transform(selection_begin, args.end(), selection_begin, [](std::string &w) { return "w:" + w; }); } }; struct GetClocksCmd : public Pass { GetClocksCmd() : Pass("get_clocks", "Create clock object") {} - void help() override { - log("\n"); - log(" get_clocks [-include_generated_clocks] [-of <nets>] " - "[<patterns>]\n"); - log("\n"); - log("Returns all clocks in the design.\n"); - log("\n"); - log(" -include_generated_clocks\n"); - log(" Include auto-generated clocks.\n"); - log("\n"); - log(" -of\n"); - log(" Get clocks of these nets.\n"); - log("\n"); - log(" <pattern>\n"); - log(" Pattern of clock names. Default are all clocks in the " - "design.\n"); - log("\n"); + void help() override + { + log("\n"); + log(" get_clocks [-include_generated_clocks] [-of <nets>] " + "[<patterns>]\n"); + log("\n"); + log("Returns all clocks in the design.\n"); + log("\n"); + log(" -include_generated_clocks\n"); + log(" Include auto-generated clocks.\n"); + log("\n"); + log(" -of\n"); + log(" Get clocks of these nets.\n"); + log("\n"); + log(" <pattern>\n"); + log(" Pattern of clock names. Default are all clocks in the " + "design.\n"); + log("\n"); } - std::vector<std::string> extract_list(const std::string& args) { - std::vector<std::string> port_list; - std::stringstream ss(args); - std::istream_iterator<std::string> begin(ss); - std::istream_iterator<std::string> end; - std::copy(begin, end, std::back_inserter(port_list)); - return port_list; + std::vector<std::string> extract_list(const std::string &args) + { + std::vector<std::string> port_list; + std::stringstream ss(args); + std::istream_iterator<std::string> begin(ss); + std::istream_iterator<std::string> end; + std::copy(begin, end, std::back_inserter(port_list)); + return port_list; } - void execute(std::vector<std::string> args, - RTLIL::Design* design) override { + void execute(std::vector<std::string> args, RTLIL::Design *design) override + { - // Parse command arguments - bool include_generated_clocks(false); - std::vector<std::string> clocks_nets; - size_t argidx(0); + // Parse command arguments + bool include_generated_clocks(false); + std::vector<std::string> clocks_nets; + size_t argidx(0); - // Parse command switches - for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-include_generated_clocks") { - include_generated_clocks = true; - continue; - } - if (arg == "-of" and argidx + 1 < args.size()) { - clocks_nets = extract_list(args[++argidx]); + // Parse command switches + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if (arg == "-include_generated_clocks") { + include_generated_clocks = true; + continue; + } + if (arg == "-of" and argidx + 1 < args.size()) { + clocks_nets = extract_list(args[++argidx]); #ifdef SDC_DEBUG - for (auto clock_net : clocks_nets) { - log("Clock filter %s\n", clock_net.c_str()); - } + for (auto clock_net : clocks_nets) { + log("Clock filter %s\n", clock_net.c_str()); + } #endif - continue; - } - if (arg.size() > 0 and arg[0] == '-') { - log_cmd_error("Unknown option %s.\n", arg.c_str()); - } + continue; + } + if (arg.size() > 0 and arg[0] == '-') { + log_cmd_error("Unknown option %s.\n", arg.c_str()); + } - break; - } + break; + } - // Parse object patterns - std::vector<std::string> clocks_list(args.begin() + argidx, args.end()); + // Parse object patterns + std::vector<std::string> clocks_list(args.begin() + argidx, args.end()); - // Fetch clocks in the design - std::map<std::string, RTLIL::Wire*> clocks(Clocks::GetClocks(design)); - if (clocks.size() == 0) { - log_warning("No clocks found in design\n"); - } + // Fetch clocks in the design + std::map<std::string, RTLIL::Wire *> clocks(Clocks::GetClocks(design)); + if (clocks.size() == 0) { + log_warning("No clocks found in design\n"); + } - // Extract clocks into tcl list - Tcl_Interp* interp = yosys_get_tcl_interp(); - Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL); - for (auto& clock : clocks) { - // Skip propagated clocks (i.e. clock wires with the same parameters - // as the master clocks they originate from - if (Clock::IsPropagated(clock.second)) { - continue; - } - // Skip generated clocks if -include_generated_clocks is not specified - if (Clock::IsGenerated(clock.second) and !include_generated_clocks) { - continue; - } - // Check if clock name is in the list of design clocks - if (clocks_list.size() > 0 and - std::find(clocks_list.begin(), clocks_list.end(), - clock.first) == clocks_list.end()) { - continue; - } - // Check if clock wire is in the -of list - if (clocks_nets.size() > 0 and - std::find(clocks_nets.begin(), clocks_nets.end(), - Clock::WireName(clock.second)) == clocks_nets.end()) { - continue; - } - auto& wire = clock.second; - const char* name = RTLIL::id2cstr(wire->name); - Tcl_Obj* name_obj = Tcl_NewStringObj(name, -1); - Tcl_ListObjAppendElement(interp, tcl_list, name_obj); - } - Tcl_SetObjResult(interp, tcl_list); + // Extract clocks into tcl list + Tcl_Interp *interp = yosys_get_tcl_interp(); + Tcl_Obj *tcl_list = Tcl_NewListObj(0, NULL); + for (auto &clock : clocks) { + // Skip propagated clocks (i.e. clock wires with the same parameters + // as the master clocks they originate from + if (Clock::IsPropagated(clock.second)) { + continue; + } + // Skip generated clocks if -include_generated_clocks is not specified + if (Clock::IsGenerated(clock.second) and !include_generated_clocks) { + continue; + } + // Check if clock name is in the list of design clocks + if (clocks_list.size() > 0 and std::find(clocks_list.begin(), clocks_list.end(), clock.first) == clocks_list.end()) { + continue; + } + // Check if clock wire is in the -of list + if (clocks_nets.size() > 0 and std::find(clocks_nets.begin(), clocks_nets.end(), Clock::WireName(clock.second)) == clocks_nets.end()) { + continue; + } + auto &wire = clock.second; + const char *name = RTLIL::id2cstr(wire->name); + Tcl_Obj *name_obj = Tcl_NewStringObj(name, -1); + Tcl_ListObjAppendElement(interp, tcl_list, name_obj); + } + Tcl_SetObjResult(interp, tcl_list); } }; struct PropagateClocksCmd : public Pass { - PropagateClocksCmd() - : Pass("propagate_clocks", "Propagate clock information") {} + PropagateClocksCmd() : Pass("propagate_clocks", "Propagate clock information") {} - void help() override { - log("\n"); - log(" propagate_clocks\n"); - log("\n"); - log("Propagate clock information throughout the design.\n"); - log("\n"); + void help() override + { + log("\n"); + log(" propagate_clocks\n"); + log("\n"); + log("Propagate clock information throughout the design.\n"); + log("\n"); } - void execute(std::vector<std::string> args, - RTLIL::Design* design) override { - if (args.size() > 1) { - log_warning( - "Command accepts no arguments.\nAll will be ignored.\n"); - } - if (!design->top_module()) { - log_cmd_error("No top module selected\n"); - } + void execute(std::vector<std::string> args, RTLIL::Design *design) override + { + if (args.size() > 1) { + log_warning("Command accepts no arguments.\nAll will be ignored.\n"); + } + if (!design->top_module()) { + log_cmd_error("No top module selected\n"); + } - std::array<std::unique_ptr<Propagation>, 2> passes{ - std::unique_ptr<Propagation>(new BufferPropagation(design, this)), - std::unique_ptr<Propagation>( - new ClockDividerPropagation(design, this))}; + std::array<std::unique_ptr<Propagation>, 2> passes{std::unique_ptr<Propagation>(new BufferPropagation(design, this)), + std::unique_ptr<Propagation>(new ClockDividerPropagation(design, this))}; - log("Perform clock propagation\n"); + log("Perform clock propagation\n"); - for (auto& pass : passes) { - pass->Run(); - } + for (auto &pass : passes) { + pass->Run(); + } } }; -class SdcPlugin { - public: - SdcPlugin() - : write_sdc_cmd_(sdc_writer_), - set_false_path_cmd_(sdc_writer_), - set_max_delay_cmd_(sdc_writer_), - set_clock_groups_cmd_(sdc_writer_) { - log("Loaded SDC plugin\n"); +class SdcPlugin +{ + public: + SdcPlugin() : write_sdc_cmd_(sdc_writer_), set_false_path_cmd_(sdc_writer_), set_max_delay_cmd_(sdc_writer_), set_clock_groups_cmd_(sdc_writer_) + { + log("Loaded SDC plugin\n"); } ReadSdcCmd read_sdc_cmd_; @@ -340,7 +330,7 @@ SetMaxDelay set_max_delay_cmd_; SetClockGroups set_clock_groups_cmd_; - private: + private: SdcWriter sdc_writer_; } SdcPlugin;
diff --git a/sdc-plugin/sdc_writer.cc b/sdc-plugin/sdc_writer.cc index b73e242..ed283a6 100644 --- a/sdc-plugin/sdc_writer.cc +++ b/sdc-plugin/sdc_writer.cc
@@ -20,94 +20,92 @@ USING_YOSYS_NAMESPACE const std::map<ClockGroups::ClockGroupRelation, std::string> ClockGroups::relation_name_map = { - {NONE, ""}, - {ASYNCHRONOUS, "asynchronous"}, - {PHYSICALLY_EXCLUSIVE, "physically_exclusive"}, - {LOGICALLY_EXCLUSIVE, "logically_exclusive"}}; + {NONE, ""}, {ASYNCHRONOUS, "asynchronous"}, {PHYSICALLY_EXCLUSIVE, "physically_exclusive"}, {LOGICALLY_EXCLUSIVE, "logically_exclusive"}}; -void SdcWriter::AddFalsePath(FalsePath false_path) { - false_paths_.push_back(false_path); -} +void SdcWriter::AddFalsePath(FalsePath false_path) { false_paths_.push_back(false_path); } -void SdcWriter::SetMaxDelay(TimingPath timing_path) { - timing_paths_.push_back(timing_path); -} +void SdcWriter::SetMaxDelay(TimingPath timing_path) { timing_paths_.push_back(timing_path); } -void SdcWriter::AddClockGroup(ClockGroups::ClockGroup clock_group, ClockGroups::ClockGroupRelation relation) { +void SdcWriter::AddClockGroup(ClockGroups::ClockGroup clock_group, ClockGroups::ClockGroupRelation relation) +{ clock_groups_.Add(clock_group, relation); } -void SdcWriter::WriteSdc(RTLIL::Design* design, std::ostream& file) { +void SdcWriter::WriteSdc(RTLIL::Design *design, std::ostream &file) +{ WriteClocks(design, file); WriteFalsePaths(file); WriteMaxDelay(file); WriteClockGroups(file); } -void SdcWriter::WriteClocks(RTLIL::Design* design, std::ostream& file) { - for (auto& clock : Clocks::GetClocks(design)) { - auto& clock_wire = clock.second; - // FIXME: Input port nets are not found in VPR - if (clock_wire->port_input) { - continue; - } - // Write out only GENERATED and EXPLICIT clocks - if (Clock::IsPropagated(clock_wire)) { - continue; - } - file << "create_clock -period " << Clock::Period(clock_wire); - file << " -waveform {" << Clock::RisingEdge(clock_wire) << " " - << Clock::FallingEdge(clock_wire) << "}"; - file << " " << Clock::SourceWireName(clock_wire); - file << std::endl; +void SdcWriter::WriteClocks(RTLIL::Design *design, std::ostream &file) +{ + for (auto &clock : Clocks::GetClocks(design)) { + auto &clock_wire = clock.second; + // FIXME: Input port nets are not found in VPR + if (clock_wire->port_input) { + continue; + } + // Write out only GENERATED and EXPLICIT clocks + if (Clock::IsPropagated(clock_wire)) { + continue; + } + file << "create_clock -period " << Clock::Period(clock_wire); + file << " -waveform {" << Clock::RisingEdge(clock_wire) << " " << Clock::FallingEdge(clock_wire) << "}"; + file << " " << Clock::SourceWireName(clock_wire); + file << std::endl; } } -void SdcWriter::WriteFalsePaths(std::ostream& file) { +void SdcWriter::WriteFalsePaths(std::ostream &file) +{ for (auto path : false_paths_) { - file << "set_false_path"; - if (!path.from_pin.empty()) { - file << " -from " << path.from_pin; - } - if (!path.through_pin.empty()) { - file << " -through " << path.through_pin; - } - if (!path.to_pin.empty()) { - file << " -to " << path.to_pin; - } - file << std::endl; + file << "set_false_path"; + if (!path.from_pin.empty()) { + file << " -from " << path.from_pin; + } + if (!path.through_pin.empty()) { + file << " -through " << path.through_pin; + } + if (!path.to_pin.empty()) { + file << " -to " << path.to_pin; + } + file << std::endl; } } -void SdcWriter::WriteMaxDelay(std::ostream& file) { +void SdcWriter::WriteMaxDelay(std::ostream &file) +{ for (auto path : timing_paths_) { - file << "set_max_delay " << path.max_delay; - if (!path.from_pin.empty()) { - file << " -from " << path.from_pin; - } - if (!path.to_pin.empty()) { - file << " -to " << path.to_pin; - } - file << std::endl; + file << "set_max_delay " << path.max_delay; + if (!path.from_pin.empty()) { + file << " -from " << path.from_pin; + } + if (!path.to_pin.empty()) { + file << " -to " << path.to_pin; + } + file << std::endl; } } -void SdcWriter::WriteClockGroups(std::ostream& file) { +void SdcWriter::WriteClockGroups(std::ostream &file) +{ for (size_t relation = 0; relation <= ClockGroups::CLOCK_GROUP_RELATION_SIZE; relation++) { - auto clock_groups = clock_groups_.GetGroups(static_cast<ClockGroups::ClockGroupRelation>(relation)); - if (clock_groups.size() == 0) { - continue; - } - file << "create_clock_groups "; - for (auto group : clock_groups) { - file << "-group "; - for (auto signal : group) { - file << signal << " "; - } - } - if (relation != ClockGroups::ClockGroupRelation::NONE) { - file << "-" + ClockGroups::relation_name_map.at(static_cast<ClockGroups::ClockGroupRelation>(relation)); - } - file << std::endl; + auto clock_groups = clock_groups_.GetGroups(static_cast<ClockGroups::ClockGroupRelation>(relation)); + if (clock_groups.size() == 0) { + continue; + } + file << "create_clock_groups "; + for (auto group : clock_groups) { + file << "-group "; + for (auto signal : group) { + file << signal << " "; + } + } + if (relation != ClockGroups::ClockGroupRelation::NONE) { + file << "-" + ClockGroups::relation_name_map.at(static_cast<ClockGroups::ClockGroupRelation>(relation)); + } + file << std::endl; } }
diff --git a/sdc-plugin/sdc_writer.h b/sdc-plugin/sdc_writer.h index 5cdf8a2..ec503a7 100644 --- a/sdc-plugin/sdc_writer.h +++ b/sdc-plugin/sdc_writer.h
@@ -39,39 +39,37 @@ using ClockGroup = std::vector<std::string>; static const std::map<ClockGroupRelation, std::string> relation_name_map; - void Add(ClockGroup& group, ClockGroupRelation relation) { - groups_[relation].push_back(group); + void Add(ClockGroup &group, ClockGroupRelation relation) { groups_[relation].push_back(group); } + std::vector<ClockGroup> GetGroups(ClockGroupRelation relation) + { + if (groups_.count(relation)) { + return groups_.at(relation); + } + return std::vector<ClockGroup>(); } - std::vector<ClockGroup> GetGroups(ClockGroupRelation relation) { - if (groups_.count(relation)) { - return groups_.at(relation); - } - return std::vector<ClockGroup>(); - } - size_t size() { - return groups_.size(); - } + size_t size() { return groups_.size(); } - private: - std::map<ClockGroupRelation,std::vector<ClockGroup>> groups_; + private: + std::map<ClockGroupRelation, std::vector<ClockGroup>> groups_; }; -class SdcWriter { - public: +class SdcWriter +{ + public: void AddFalsePath(FalsePath false_path); void SetMaxDelay(TimingPath timing_path); void AddClockGroup(ClockGroups::ClockGroup clock_group, ClockGroups::ClockGroupRelation relation); - void WriteSdc(RTLIL::Design* design, std::ostream& file); + void WriteSdc(RTLIL::Design *design, std::ostream &file); - private: - void WriteClocks(RTLIL::Design* design, std::ostream& file); - void WriteFalsePaths(std::ostream& file); - void WriteMaxDelay(std::ostream& file); - void WriteClockGroups(std::ostream& file); + private: + void WriteClocks(RTLIL::Design *design, std::ostream &file); + void WriteFalsePaths(std::ostream &file); + void WriteMaxDelay(std::ostream &file); + void WriteClockGroups(std::ostream &file); std::vector<FalsePath> false_paths_; std::vector<TimingPath> timing_paths_; ClockGroups clock_groups_; }; -#endif // _SDC_WRITER_H_ +#endif // _SDC_WRITER_H_
diff --git a/sdc-plugin/set_clock_groups.cc b/sdc-plugin/set_clock_groups.cc index 301ca96..e02047b 100644 --- a/sdc-plugin/set_clock_groups.cc +++ b/sdc-plugin/set_clock_groups.cc
@@ -16,12 +16,13 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "set_clock_groups.h" -#include <regex> #include "kernel/log.h" +#include <regex> USING_YOSYS_NAMESPACE -void SetClockGroups::help() { +void SetClockGroups::help() +{ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" set_clock_groups [-quiet] [-group <args>] [-asynchronous] \n"); @@ -42,11 +43,11 @@ log("\n"); } -void SetClockGroups::execute(std::vector<std::string> args, - RTLIL::Design* design) { - RTLIL::Module* top_module = design->top_module(); +void SetClockGroups::execute(std::vector<std::string> args, RTLIL::Design *design) +{ + RTLIL::Module *top_module = design->top_module(); if (top_module == nullptr) { - log_cmd_error("No top module detected\n"); + log_cmd_error("No top module detected\n"); } size_t argidx; @@ -56,61 +57,57 @@ // Parse command arguments for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-quiet") { - is_quiet = true; - continue; - } + std::string arg = args[argidx]; + if (arg == "-quiet") { + is_quiet = true; + continue; + } - // Parse clock groups relation: asynchronous, logically_exclusive, physically_exclusive - auto is_relation_arg = - [arg](std::pair<ClockGroups::ClockGroupRelation, std::string> - relation) { - if (arg.substr(1) == relation.second) { - return true; - } - return false; - }; - auto relation_map_it = - std::find_if(ClockGroups::relation_name_map.begin(), - ClockGroups::relation_name_map.end(), is_relation_arg); - if (relation_map_it != ClockGroups::relation_name_map.end()) { - clock_groups_relation = relation_map_it->first; - continue; - } + // Parse clock groups relation: asynchronous, logically_exclusive, physically_exclusive + auto is_relation_arg = [arg](std::pair<ClockGroups::ClockGroupRelation, std::string> relation) { + if (arg.substr(1) == relation.second) { + return true; + } + return false; + }; + auto relation_map_it = std::find_if(ClockGroups::relation_name_map.begin(), ClockGroups::relation_name_map.end(), is_relation_arg); + if (relation_map_it != ClockGroups::relation_name_map.end()) { + clock_groups_relation = relation_map_it->first; + continue; + } - if (arg == "-group" and argidx + 1 < args.size()) { - ClockGroups::ClockGroup clock_group; - while (argidx + 1 < args.size() and args[argidx+1][0] != '-') { - clock_group.push_back(args[++argidx]); - } - clock_groups.push_back(clock_group); - continue; - } + if (arg == "-group" and argidx + 1 < args.size()) { + ClockGroups::ClockGroup clock_group; + while (argidx + 1 < args.size() and args[argidx + 1][0] != '-') { + clock_group.push_back(args[++argidx]); + } + clock_groups.push_back(clock_group); + continue; + } - if (arg.size() > 0 and arg[0] == '-') { - log_cmd_error("Unknown option %s.\n", arg.c_str()); - } + if (arg.size() > 0 and arg[0] == '-') { + log_cmd_error("Unknown option %s.\n", arg.c_str()); + } - break; + break; } if (clock_groups.size()) { - if (!is_quiet) { - std::string msg = ClockGroups::relation_name_map.at(clock_groups_relation); - msg += (!msg.empty()) ? " " : ""; - log("Adding %sclock group with following clocks:\n", msg.c_str()); - } - size_t count(0); - for (auto& group : clock_groups) { - sdc_writer_.AddClockGroup(group, clock_groups_relation); - if (!is_quiet) { - log("%zu: ", count++); - for (auto clk : group) { - log("%s ", clk.c_str()); - } - log("\n"); - } - } + if (!is_quiet) { + std::string msg = ClockGroups::relation_name_map.at(clock_groups_relation); + msg += (!msg.empty()) ? " " : ""; + log("Adding %sclock group with following clocks:\n", msg.c_str()); + } + size_t count(0); + for (auto &group : clock_groups) { + sdc_writer_.AddClockGroup(group, clock_groups_relation); + if (!is_quiet) { + log("%zu: ", count++); + for (auto clk : group) { + log("%s ", clk.c_str()); + } + log("\n"); + } + } } }
diff --git a/sdc-plugin/set_clock_groups.h b/sdc-plugin/set_clock_groups.h index 3114578..29062fa 100644 --- a/sdc-plugin/set_clock_groups.h +++ b/sdc-plugin/set_clock_groups.h
@@ -25,15 +25,13 @@ USING_YOSYS_NAMESPACE struct SetClockGroups : public Pass { - SetClockGroups(SdcWriter& sdc_writer) - : Pass("set_clock_groups", "Set exclusive or asynchronous clock groups"), - sdc_writer_(sdc_writer) {} + SetClockGroups(SdcWriter &sdc_writer) : Pass("set_clock_groups", "Set exclusive or asynchronous clock groups"), sdc_writer_(sdc_writer) {} void help() override; - void execute(std::vector<std::string> args, RTLIL::Design* design) override; + void execute(std::vector<std::string> args, RTLIL::Design *design) override; - SdcWriter& sdc_writer_; + SdcWriter &sdc_writer_; }; -#endif //_SET_CLOCK_GROUPS_H_ +#endif //_SET_CLOCK_GROUPS_H_
diff --git a/sdc-plugin/set_false_path.cc b/sdc-plugin/set_false_path.cc index 18262d0..e5083b4 100644 --- a/sdc-plugin/set_false_path.cc +++ b/sdc-plugin/set_false_path.cc
@@ -16,13 +16,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "set_false_path.h" -#include <regex> #include "kernel/log.h" #include "sdc_writer.h" +#include <regex> USING_YOSYS_NAMESPACE -void SetFalsePath::help() { +void SetFalsePath::help() +{ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" set_false_path [-quiet] [-from <net_name>] [-to <net_name>] \n"); @@ -46,11 +47,11 @@ log("\n"); } -void SetFalsePath::execute(std::vector<std::string> args, - RTLIL::Design* design) { - RTLIL::Module* top_module = design->top_module(); +void SetFalsePath::execute(std::vector<std::string> args, RTLIL::Design *design) +{ + RTLIL::Module *top_module = design->top_module(); if (top_module == nullptr) { - log_cmd_error("No top module detected\n"); + log_cmd_error("No top module detected\n"); } size_t argidx; @@ -61,39 +62,38 @@ // Parse command arguments for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-quiet") { - is_quiet = true; - continue; - } + std::string arg = args[argidx]; + if (arg == "-quiet") { + is_quiet = true; + continue; + } - if (arg == "-from" and argidx + 1 < args.size()) { - from_pin = args[++argidx]; - continue; - } + if (arg == "-from" and argidx + 1 < args.size()) { + from_pin = args[++argidx]; + continue; + } - if (arg == "-to" and argidx + 1 < args.size()) { - to_pin = args[++argidx]; - continue; - } + if (arg == "-to" and argidx + 1 < args.size()) { + to_pin = args[++argidx]; + continue; + } - if (arg == "-through" and argidx + 1 < args.size()) { - through_pin = args[++argidx]; - continue; - } + if (arg == "-through" and argidx + 1 < args.size()) { + through_pin = args[++argidx]; + continue; + } - if (arg.size() > 0 and arg[0] == '-') { - log_cmd_error("Unknown option %s.\n", arg.c_str()); - } + if (arg.size() > 0 and arg[0] == '-') { + log_cmd_error("Unknown option %s.\n", arg.c_str()); + } - break; + break; } if (!is_quiet) { - std::string msg = (from_pin.empty()) ? "" : "-from " + from_pin; - msg += (through_pin.empty()) ? "" : " -through " + through_pin; - msg += (to_pin.empty()) ? "" : " -to " + to_pin; - log("Adding false path %s\n", msg.c_str()); + std::string msg = (from_pin.empty()) ? "" : "-from " + from_pin; + msg += (through_pin.empty()) ? "" : " -through " + through_pin; + msg += (to_pin.empty()) ? "" : " -to " + to_pin; + log("Adding false path %s\n", msg.c_str()); } - sdc_writer_.AddFalsePath(FalsePath{ - .from_pin = from_pin, .to_pin = to_pin, .through_pin = through_pin}); + sdc_writer_.AddFalsePath(FalsePath{.from_pin = from_pin, .to_pin = to_pin, .through_pin = through_pin}); }
diff --git a/sdc-plugin/set_false_path.h b/sdc-plugin/set_false_path.h index 47bf08a..de36aa4 100644 --- a/sdc-plugin/set_false_path.h +++ b/sdc-plugin/set_false_path.h
@@ -25,15 +25,13 @@ USING_YOSYS_NAMESPACE struct SetFalsePath : public Pass { - SetFalsePath(SdcWriter& sdc_writer) - : Pass("set_false_path", "Set false path on net"), - sdc_writer_(sdc_writer) {} + SetFalsePath(SdcWriter &sdc_writer) : Pass("set_false_path", "Set false path on net"), sdc_writer_(sdc_writer) {} void help() override; - void execute(std::vector<std::string> args, RTLIL::Design* design) override; + void execute(std::vector<std::string> args, RTLIL::Design *design) override; - SdcWriter& sdc_writer_; + SdcWriter &sdc_writer_; }; -#endif //_SET_FALSE_PATH_H_ +#endif //_SET_FALSE_PATH_H_
diff --git a/sdc-plugin/set_max_delay.cc b/sdc-plugin/set_max_delay.cc index 055e342..c517dec 100644 --- a/sdc-plugin/set_max_delay.cc +++ b/sdc-plugin/set_max_delay.cc
@@ -21,7 +21,8 @@ USING_YOSYS_NAMESPACE -void SetMaxDelay::help() { +void SetMaxDelay::help() +{ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" set_max_delay [-quiet] [-from <arg>] [-to <arg>] \n"); @@ -42,11 +43,11 @@ log("\n"); } -void SetMaxDelay::execute(std::vector<std::string> args, - RTLIL::Design* design) { - RTLIL::Module* top_module = design->top_module(); +void SetMaxDelay::execute(std::vector<std::string> args, RTLIL::Design *design) +{ + RTLIL::Module *top_module = design->top_module(); if (top_module == nullptr) { - log_cmd_error("No top module detected\n"); + log_cmd_error("No top module detected\n"); } size_t argidx; @@ -57,36 +58,35 @@ // Parse command arguments for (argidx = 1; argidx < args.size(); argidx++) { - std::string arg = args[argidx]; - if (arg == "-quiet") { - is_quiet = true; - continue; - } + std::string arg = args[argidx]; + if (arg == "-quiet") { + is_quiet = true; + continue; + } - if (arg == "-from" and argidx + 1 < args.size()) { - from_pin = args[++argidx]; - log("From: %s\n", from_pin.c_str()); - continue; - } + if (arg == "-from" and argidx + 1 < args.size()) { + from_pin = args[++argidx]; + log("From: %s\n", from_pin.c_str()); + continue; + } - if (arg == "-to" and argidx + 1 < args.size()) { - to_pin = args[++argidx]; - log("To: %s\n", to_pin.c_str()); - continue; - } + if (arg == "-to" and argidx + 1 < args.size()) { + to_pin = args[++argidx]; + log("To: %s\n", to_pin.c_str()); + continue; + } - if (arg.size() > 0 and arg[0] == '-') { - log_cmd_error("Unknown option %s.\n", arg.c_str()); - } + if (arg.size() > 0 and arg[0] == '-') { + log_cmd_error("Unknown option %s.\n", arg.c_str()); + } - max_delay = std::stof(args[argidx]); + max_delay = std::stof(args[argidx]); } if (!is_quiet) { - std::string msg = (from_pin.empty()) ? "" : "-from " + from_pin; - msg += (to_pin.empty()) ? "" : " -to " + to_pin; - log("Adding max path delay of %f on path %s\n", max_delay, msg.c_str()); + std::string msg = (from_pin.empty()) ? "" : "-from " + from_pin; + msg += (to_pin.empty()) ? "" : " -to " + to_pin; + log("Adding max path delay of %f on path %s\n", max_delay, msg.c_str()); } - sdc_writer_.SetMaxDelay(TimingPath{ - .from_pin = from_pin, .to_pin = to_pin, .max_delay = max_delay}); + sdc_writer_.SetMaxDelay(TimingPath{.from_pin = from_pin, .to_pin = to_pin, .max_delay = max_delay}); }
diff --git a/sdc-plugin/set_max_delay.h b/sdc-plugin/set_max_delay.h index 7272839..2602643 100644 --- a/sdc-plugin/set_max_delay.h +++ b/sdc-plugin/set_max_delay.h
@@ -25,15 +25,13 @@ USING_YOSYS_NAMESPACE struct SetMaxDelay : public Pass { - SetMaxDelay(SdcWriter& sdc_writer) - : Pass("set_max_delay", "Specify maximum delay for timing paths"), - sdc_writer_(sdc_writer) {} + SetMaxDelay(SdcWriter &sdc_writer) : Pass("set_max_delay", "Specify maximum delay for timing paths"), sdc_writer_(sdc_writer) {} void help() override; - void execute(std::vector<std::string> args, RTLIL::Design* design) override; + void execute(std::vector<std::string> args, RTLIL::Design *design) override; - SdcWriter& sdc_writer_; + SdcWriter &sdc_writer_; }; -#endif //_SET_MAX_DELAY_H_ +#endif //_SET_MAX_DELAY_H_
diff --git a/sdc-plugin/tests/escaping/escaping.test.cc b/sdc-plugin/tests/escaping/escaping.test.cc index e17eef6..a26a849 100644 --- a/sdc-plugin/tests/escaping/escaping.test.cc +++ b/sdc-plugin/tests/escaping/escaping.test.cc
@@ -2,10 +2,10 @@ #include <gtest/gtest.h> -TEST(ClockTest, EscapeDollarSign) { - // convert wire_name to wire_name, i.e. unchanged - EXPECT_EQ(Clock::AddEscaping("wire_name"), "wire_name"); - // convert $wire_name to \$wire_name - EXPECT_EQ(Clock::AddEscaping("$wire_name"), "\\$wire_name"); +TEST(ClockTest, EscapeDollarSign) +{ + // convert wire_name to wire_name, i.e. unchanged + EXPECT_EQ(Clock::AddEscaping("wire_name"), "wire_name"); + // convert $wire_name to \$wire_name + EXPECT_EQ(Clock::AddEscaping("$wire_name"), "\\$wire_name"); } -
diff --git a/selection-plugin/selection.cc b/selection-plugin/selection.cc index 6f224ff..30a0222 100644 --- a/selection-plugin/selection.cc +++ b/selection-plugin/selection.cc
@@ -16,75 +16,75 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "kernel/log.h" #include "kernel/register.h" #include "kernel/rtlil.h" -#include "kernel/log.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN - struct SelectionToTclList : public Pass { - SelectionToTclList() : Pass("selection_to_tcl_list", "Extract selection to TCL list") {} + SelectionToTclList() : Pass("selection_to_tcl_list", "Extract selection to TCL list") {} - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" selection_to_tcl_list selection\n"); - log("\n"); - log("Extract the current selection to a Tcl List with selection object names. \n"); - log("\n"); - } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" selection_to_tcl_list selection\n"); + log("\n"); + log("Extract the current selection to a Tcl List with selection object names. \n"); + log("\n"); + } - void AddObjectNameToTclList(RTLIL::IdString& module, RTLIL::IdString& object, Tcl_Obj* tcl_list) { - std::string name = RTLIL::unescape_id(module) + "/" + RTLIL::unescape_id(object); - Tcl_Obj* value_obj = Tcl_NewStringObj(name.c_str(), name.size()); - Tcl_ListObjAppendElement(yosys_get_tcl_interp(), tcl_list, value_obj); - } + void AddObjectNameToTclList(RTLIL::IdString &module, RTLIL::IdString &object, Tcl_Obj *tcl_list) + { + std::string name = RTLIL::unescape_id(module) + "/" + RTLIL::unescape_id(object); + Tcl_Obj *value_obj = Tcl_NewStringObj(name.c_str(), name.size()); + Tcl_ListObjAppendElement(yosys_get_tcl_interp(), tcl_list, value_obj); + } - void execute(std::vector<std::string> args, RTLIL::Design* design) override - { - if (args.size() == 1) { - log_error("Incorrect number of arguments"); - } - extra_args(args, 1, design); + void execute(std::vector<std::string> args, RTLIL::Design *design) override + { + if (args.size() == 1) { + log_error("Incorrect number of arguments"); + } + extra_args(args, 1, design); - Tcl_Interp *interp = yosys_get_tcl_interp(); - Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL); + Tcl_Interp *interp = yosys_get_tcl_interp(); + Tcl_Obj *tcl_list = Tcl_NewListObj(0, NULL); - auto& selection = design->selection(); - if (selection.empty()) { - log_warning("Selection is empty\n"); - } + auto &selection = design->selection(); + if (selection.empty()) { + log_warning("Selection is empty\n"); + } - for (auto mod : design->modules()) { - if (selection.selected_module(mod->name)) { - for (auto wire : mod->wires()) { - if (selection.selected_member(mod->name, wire->name)) { - AddObjectNameToTclList(mod->name, wire->name, tcl_list); - } - } - for (auto &it : mod->memories) { - if (selection.selected_member(mod->name, it.first)) { - AddObjectNameToTclList(mod->name, it.first, tcl_list); - } - } - for (auto cell : mod->cells()) { - if (selection.selected_member(mod->name, cell->name)) { - AddObjectNameToTclList(mod->name, cell->name, tcl_list); - } - } - for (auto &it : mod->processes) { - if (selection.selected_member(mod->name, it.first)) { - AddObjectNameToTclList(mod->name, it.first, tcl_list); - } - } - } + for (auto mod : design->modules()) { + if (selection.selected_module(mod->name)) { + for (auto wire : mod->wires()) { + if (selection.selected_member(mod->name, wire->name)) { + AddObjectNameToTclList(mod->name, wire->name, tcl_list); + } } - Tcl_SetObjResult(interp, tcl_list); - } + for (auto &it : mod->memories) { + if (selection.selected_member(mod->name, it.first)) { + AddObjectNameToTclList(mod->name, it.first, tcl_list); + } + } + for (auto cell : mod->cells()) { + if (selection.selected_member(mod->name, cell->name)) { + AddObjectNameToTclList(mod->name, cell->name, tcl_list); + } + } + for (auto &it : mod->processes) { + if (selection.selected_member(mod->name, it.first)) { + AddObjectNameToTclList(mod->name, it.first, tcl_list); + } + } + } + } + Tcl_SetObjResult(interp, tcl_list); + } } SelectionToTclList;
diff --git a/xdc-plugin/xdc.cc b/xdc-plugin/xdc.cc index a27bdf7..3d792dd 100644 --- a/xdc-plugin/xdc.cc +++ b/xdc-plugin/xdc.cc
@@ -26,400 +26,392 @@ * Tcl interpreter and processed by the new XDC commands imported to the * Tcl interpreter. */ -#include <cassert> +#include "../bank_tiles.h" +#include "kernel/log.h" #include "kernel/register.h" #include "kernel/rtlil.h" -#include "kernel/log.h" #include "libs/json11/json11.hpp" -#include "../bank_tiles.h" +#include <cassert> USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -static bool isInputPort(RTLIL::Wire* wire) { - return wire->port_input; -} -static bool isOutputPort(RTLIL::Wire* wire) { - return wire->port_output; -} +static bool isInputPort(RTLIL::Wire *wire) { return wire->port_input; } +static bool isOutputPort(RTLIL::Wire *wire) { return wire->port_output; } enum class SetPropertyOptions { INTERNAL_VREF, IOSTANDARD, SLEW, DRIVE, IN_TERM, IO_LOC_PAIRS }; -const std::unordered_map<std::string, SetPropertyOptions> set_property_options_map = { - {"INTERNAL_VREF", SetPropertyOptions::INTERNAL_VREF}, - {"IOSTANDARD", SetPropertyOptions::IOSTANDARD}, - {"SLEW", SetPropertyOptions::SLEW}, - {"DRIVE", SetPropertyOptions::DRIVE}, - {"IN_TERM", SetPropertyOptions::IN_TERM}, - {"LOC", SetPropertyOptions::IO_LOC_PAIRS}, - {"PACKAGE_PIN", SetPropertyOptions::IO_LOC_PAIRS} -}; +const std::unordered_map<std::string, SetPropertyOptions> set_property_options_map = {{"INTERNAL_VREF", SetPropertyOptions::INTERNAL_VREF}, + {"IOSTANDARD", SetPropertyOptions::IOSTANDARD}, + {"SLEW", SetPropertyOptions::SLEW}, + {"DRIVE", SetPropertyOptions::DRIVE}, + {"IN_TERM", SetPropertyOptions::IN_TERM}, + {"LOC", SetPropertyOptions::IO_LOC_PAIRS}, + {"PACKAGE_PIN", SetPropertyOptions::IO_LOC_PAIRS}}; -const std::unordered_map<std::string, std::vector<std::string>> supported_primitive_parameters = { - {"OBUF", {"IO_LOC_PAIRS", "IOSTANDARD", "DRIVE", "SLEW", "IN_TERM"}}, - {"OBUFDS", {"IO_LOC_PAIRS", "IOSTANDARD", "SLEW", "IN_TERM"}}, - {"OBUFTDS", {"IO_LOC_PAIRS", "IOSTANDARD", "SLEW", "IN_TERM"}}, - {"IBUF", {"IO_LOC_PAIRS", "IOSTANDARD"}}, - {"IOBUF", {"IO_LOC_PAIRS", "IOSTANDARD", "DRIVE", "SLEW", "IN_TERM"}}, - {"IOBUFDS", {"IO_LOC_PAIRS", "IOSTANDARD", "SLEW", "IN_TERM"}} -}; +const std::unordered_map<std::string, std::vector<std::string>> supported_primitive_parameters = { + {"OBUF", {"IO_LOC_PAIRS", "IOSTANDARD", "DRIVE", "SLEW", "IN_TERM"}}, {"OBUFDS", {"IO_LOC_PAIRS", "IOSTANDARD", "SLEW", "IN_TERM"}}, + {"OBUFTDS", {"IO_LOC_PAIRS", "IOSTANDARD", "SLEW", "IN_TERM"}}, {"IBUF", {"IO_LOC_PAIRS", "IOSTANDARD"}}, + {"IOBUF", {"IO_LOC_PAIRS", "IOSTANDARD", "DRIVE", "SLEW", "IN_TERM"}}, {"IOBUFDS", {"IO_LOC_PAIRS", "IOSTANDARD", "SLEW", "IN_TERM"}}}; -void register_in_tcl_interpreter(const std::string& command) { - Tcl_Interp* interp = yosys_get_tcl_interp(); - std::string tcl_script = stringf("proc %s args { return [yosys %s {*}$args] }", command.c_str(), command.c_str()); - Tcl_Eval(interp, tcl_script.c_str()); +void register_in_tcl_interpreter(const std::string &command) +{ + Tcl_Interp *interp = yosys_get_tcl_interp(); + std::string tcl_script = stringf("proc %s args { return [yosys %s {*}$args] }", command.c_str(), command.c_str()); + Tcl_Eval(interp, tcl_script.c_str()); } struct GetIOBanks : public Pass { - GetIOBanks(std::function<const BankTilesMap&()> get_bank_tiles) - : Pass("get_iobanks", "Set IO Bank number") - , get_bank_tiles(get_bank_tiles) { - register_in_tcl_interpreter(pass_name); - } + GetIOBanks(std::function<const BankTilesMap &()> get_bank_tiles) : Pass("get_iobanks", "Set IO Bank number"), get_bank_tiles(get_bank_tiles) + { + register_in_tcl_interpreter(pass_name); + } - void help() override { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" get_iobanks <bank_number>\n"); - log("\n"); - log("Get IO Bank number\n"); - log("\n"); - } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" get_iobanks <bank_number>\n"); + log("\n"); + log("Get IO Bank number\n"); + log("\n"); + } - void execute(std::vector<std::string> args, RTLIL::Design* ) override { - if (args.size() < 2) { - log_cmd_error("%s: Missing bank number.\n", pass_name.c_str()); - } - auto bank_tiles = get_bank_tiles(); - if (bank_tiles.count(std::atoi(args[1].c_str())) == 0) { - log_cmd_error("%s:Bank number %s is not present in the target device.\n", args[1].c_str(), pass_name.c_str()); - } + void execute(std::vector<std::string> args, RTLIL::Design *) override + { + if (args.size() < 2) { + log_cmd_error("%s: Missing bank number.\n", pass_name.c_str()); + } + auto bank_tiles = get_bank_tiles(); + if (bank_tiles.count(std::atoi(args[1].c_str())) == 0) { + log_cmd_error("%s:Bank number %s is not present in the target device.\n", args[1].c_str(), pass_name.c_str()); + } - Tcl_Interp *interp = yosys_get_tcl_interp(); - Tcl_SetResult(interp, const_cast<char*>(args[1].c_str()), NULL); - log("%s\n", args[1].c_str()); - } + Tcl_Interp *interp = yosys_get_tcl_interp(); + Tcl_SetResult(interp, const_cast<char *>(args[1].c_str()), NULL); + log("%s\n", args[1].c_str()); + } - std::function<const BankTilesMap&()> get_bank_tiles; + std::function<const BankTilesMap &()> get_bank_tiles; }; struct SetProperty : public Pass { - SetProperty(std::function<const BankTilesMap&()> get_bank_tiles) - : Pass("set_property", "Set a given property") - , get_bank_tiles(get_bank_tiles) { - register_in_tcl_interpreter(pass_name); - } + SetProperty(std::function<const BankTilesMap &()> get_bank_tiles) : Pass("set_property", "Set a given property"), get_bank_tiles(get_bank_tiles) + { + register_in_tcl_interpreter(pass_name); + } - void help() override { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" set_property PROPERTY VALUE OBJECT\n"); - log("\n"); - log("Set the given property to the specified value on an object\n"); - log("\n"); - } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" set_property PROPERTY VALUE OBJECT\n"); + log("\n"); + log("Set the given property to the specified value on an object\n"); + log("\n"); + } - void execute(std::vector<std::string> args, RTLIL::Design* design) override { - if (design->top_module() == nullptr) { - log_cmd_error("No top module detected\n"); - } + void execute(std::vector<std::string> args, RTLIL::Design *design) override + { + if (design->top_module() == nullptr) { + log_cmd_error("No top module detected\n"); + } - std::string option(args[1]); - if (set_property_options_map.count(option) == 0) { - log_warning("set_property: %s option is currently not supported\n", option.c_str()); - return; - } + std::string option(args[1]); + if (set_property_options_map.count(option) == 0) { + log_warning("set_property: %s option is currently not supported\n", option.c_str()); + return; + } - switch (set_property_options_map.at(option)) { - case SetPropertyOptions::INTERNAL_VREF: - process_vref(std::vector<std::string>(args.begin() + 2, args.end()), design); - break; - case SetPropertyOptions::IOSTANDARD: - case SetPropertyOptions::SLEW: - case SetPropertyOptions::DRIVE: - case SetPropertyOptions::IN_TERM: - process_port_parameter(std::vector<std::string>(args.begin() + 1, args.end()), design); - break; - case SetPropertyOptions::IO_LOC_PAIRS: { - // args "set_property LOC PAD PORT" become "IO_LOC_PAIRS PORT:PAD PORT" - std::vector<std::string> new_args(args.begin() + 1, args.end()); - new_args.at(0) = "IO_LOC_PAIRS"; - new_args.at(1) = new_args.at(2) + ":" + new_args.at(1); - process_port_parameter(new_args, design); - break; - } - default: - assert(false); - } - } + switch (set_property_options_map.at(option)) { + case SetPropertyOptions::INTERNAL_VREF: + process_vref(std::vector<std::string>(args.begin() + 2, args.end()), design); + break; + case SetPropertyOptions::IOSTANDARD: + case SetPropertyOptions::SLEW: + case SetPropertyOptions::DRIVE: + case SetPropertyOptions::IN_TERM: + process_port_parameter(std::vector<std::string>(args.begin() + 1, args.end()), design); + break; + case SetPropertyOptions::IO_LOC_PAIRS: { + // args "set_property LOC PAD PORT" become "IO_LOC_PAIRS PORT:PAD PORT" + std::vector<std::string> new_args(args.begin() + 1, args.end()); + new_args.at(0) = "IO_LOC_PAIRS"; + new_args.at(1) = new_args.at(2) + ":" + new_args.at(1); + process_port_parameter(new_args, design); + break; + } + default: + assert(false); + } + } - void process_vref(std::vector<std::string> args, RTLIL::Design* design) { - if (args.size() < 2) { - log_error("set_property INTERNAL_VREF: Incorrect number of arguments.\n"); - } - int iobank = std::atoi(args[1].c_str()); - auto bank_tiles = get_bank_tiles(); - if (bank_tiles.count(iobank) == 0) { - log_cmd_error("set_property INTERNAL_VREF: Invalid IO bank.\n"); - } + void process_vref(std::vector<std::string> args, RTLIL::Design *design) + { + if (args.size() < 2) { + log_error("set_property INTERNAL_VREF: Incorrect number of arguments.\n"); + } + int iobank = std::atoi(args[1].c_str()); + auto bank_tiles = get_bank_tiles(); + if (bank_tiles.count(iobank) == 0) { + log_cmd_error("set_property INTERNAL_VREF: Invalid IO bank.\n"); + } - int internal_vref = 1000 * std::atof(args[0].c_str()); - if (internal_vref != 600 && - internal_vref != 675 && - internal_vref != 750 && - internal_vref != 900) { - log("set_property INTERNAL_VREF: Incorrect INTERNAL_VREF value\n"); - return; - } + int internal_vref = 1000 * std::atof(args[0].c_str()); + if (internal_vref != 600 && internal_vref != 675 && internal_vref != 750 && internal_vref != 900) { + log("set_property INTERNAL_VREF: Incorrect INTERNAL_VREF value\n"); + return; + } - // Create a new BANK module if it hasn't been created so far - RTLIL::Module* top_module = design->top_module(); - if (!design->has(ID(BANK))) { - std::string fasm_extra_modules_dir(proc_share_dirname() + "/plugins/fasm_extra_modules"); - Pass::call(design, "read_verilog " + fasm_extra_modules_dir + "/BANK.v"); - } + // Create a new BANK module if it hasn't been created so far + RTLIL::Module *top_module = design->top_module(); + if (!design->has(ID(BANK))) { + std::string fasm_extra_modules_dir(proc_share_dirname() + "/plugins/fasm_extra_modules"); + Pass::call(design, "read_verilog " + fasm_extra_modules_dir + "/BANK.v"); + } - // Set parameters on a new bank instance or update an existing one - char bank_cell_name[16]; - snprintf(bank_cell_name, 16, "\\bank_cell_%d", iobank); - RTLIL::Cell* bank_cell = top_module->cell(RTLIL::IdString(bank_cell_name)); - if (!bank_cell) { - bank_cell = top_module->addCell(RTLIL::IdString(bank_cell_name), ID(BANK)); - } - bank_cell->setParam(ID(FASM_EXTRA), RTLIL::Const("INTERNAL_VREF")); - bank_cell->setParam(ID(NUMBER), RTLIL::Const(iobank)); - bank_cell->setParam(ID(INTERNAL_VREF), RTLIL::Const(internal_vref)); - } + // Set parameters on a new bank instance or update an existing one + char bank_cell_name[16]; + snprintf(bank_cell_name, 16, "\\bank_cell_%d", iobank); + RTLIL::Cell *bank_cell = top_module->cell(RTLIL::IdString(bank_cell_name)); + if (!bank_cell) { + bank_cell = top_module->addCell(RTLIL::IdString(bank_cell_name), ID(BANK)); + } + bank_cell->setParam(ID(FASM_EXTRA), RTLIL::Const("INTERNAL_VREF")); + bank_cell->setParam(ID(NUMBER), RTLIL::Const(iobank)); + bank_cell->setParam(ID(INTERNAL_VREF), RTLIL::Const(internal_vref)); + } - void process_port_parameter(std::vector<std::string> args, RTLIL::Design* design) { - if (args.size() < 1) { - log_error("set_property: Incorrect number of arguments.\n"); - } + void process_port_parameter(std::vector<std::string> args, RTLIL::Design *design) + { + if (args.size() < 1) { + log_error("set_property: Incorrect number of arguments.\n"); + } - std::string parameter(args.at(0)); - if (args.size() < 3 || args.at(2).size() == 0) { - log_error("set_property %s: Incorrect number of arguments.\n", parameter.c_str()); - } + std::string parameter(args.at(0)); + if (args.size() < 3 || args.at(2).size() == 0) { + log_error("set_property %s: Incorrect number of arguments.\n", parameter.c_str()); + } - std::string port_name(args.at(2)); - std::string value(args.at(1)); + std::string port_name(args.at(2)); + std::string value(args.at(1)); - auto port_signal = extract_signal(port_name); - std::string port(port_signal.first); - int port_bit = port_signal.second; + auto port_signal = extract_signal(port_name); + std::string port(port_signal.first); + int port_bit = port_signal.second; - RTLIL::Wire* wire = design->top_module()->wire(RTLIL::escape_id(port)); - if (wire == nullptr) { - log_error("Couldn't find port %s\n", port_name.c_str()); - } + RTLIL::Wire *wire = design->top_module()->wire(RTLIL::escape_id(port)); + if (wire == nullptr) { + log_error("Couldn't find port %s\n", port_name.c_str()); + } - if (!isInputPort(wire) && !isOutputPort(wire)) { - log_error("Port %s is not a top port\n", port_name.c_str()); - } + if (!isInputPort(wire) && !isOutputPort(wire)) { + log_error("Port %s is not a top port\n", port_name.c_str()); + } - if (port_bit < wire->start_offset || port_bit >= wire->start_offset + wire->width) { - log_error("Incorrect top port index %d in port %s\n", port_bit, port_name.c_str()); - } + if (port_bit < wire->start_offset || port_bit >= wire->start_offset + wire->width) { + log_error("Incorrect top port index %d in port %s\n", port_bit, port_name.c_str()); + } - // Traverse the port wire - traverse_wire(port_name, design->top_module()); + // Traverse the port wire + traverse_wire(port_name, design->top_module()); - RTLIL::IdString parameter_id(RTLIL::escape_id(parameter)); - for (auto cell_obj : design->top_module()->cells_) { - RTLIL::IdString cell_id = cell_obj.first; - RTLIL::Cell* cell = cell_obj.second; + RTLIL::IdString parameter_id(RTLIL::escape_id(parameter)); + for (auto cell_obj : design->top_module()->cells_) { + RTLIL::IdString cell_id = cell_obj.first; + RTLIL::Cell *cell = cell_obj.second; - // Check if the cell is of the type we are looking for - auto cell_type_str = RTLIL::unescape_id(cell->type.str()); - auto primitive_parameters_iter = supported_primitive_parameters.find(cell_type_str); - if (primitive_parameters_iter == supported_primitive_parameters.end()) { - continue; - } + // Check if the cell is of the type we are looking for + auto cell_type_str = RTLIL::unescape_id(cell->type.str()); + auto primitive_parameters_iter = supported_primitive_parameters.find(cell_type_str); + if (primitive_parameters_iter == supported_primitive_parameters.end()) { + continue; + } - // Set the parameter on the cell connected to the selected port - for (auto connection : cell->connections_) { - RTLIL::SigSpec cell_signal = connection.second; - if (is_signal_port(cell_signal, port_name)) { - // Check if the attribute is allowed for this module - auto primitive_parameters = primitive_parameters_iter->second; - if (std::find(primitive_parameters.begin(), primitive_parameters.end(), parameter) == primitive_parameters.end()) { - log_error("Cell %s of type %s doesn't support the %s attribute\n", - cell->name.c_str(), cell->type.c_str(), - parameter_id.c_str()); - } - if (parameter_id == ID(IO_LOC_PAIRS) and cell->hasParam(parameter_id)) { - std::string cur_value(cell->getParam(parameter_id).decode_string()); - value = cur_value + "," + value; - } - cell->setParam(parameter_id, RTLIL::Const(value)); - log("Setting parameter %s to value %s on cell %s \n", parameter_id.c_str(), value.c_str(), cell_obj.first.c_str()); - } - } - } - log("\n"); - } + // Set the parameter on the cell connected to the selected port + for (auto connection : cell->connections_) { + RTLIL::SigSpec cell_signal = connection.second; + if (is_signal_port(cell_signal, port_name)) { + // Check if the attribute is allowed for this module + auto primitive_parameters = primitive_parameters_iter->second; + if (std::find(primitive_parameters.begin(), primitive_parameters.end(), parameter) == primitive_parameters.end()) { + log_error("Cell %s of type %s doesn't support the %s attribute\n", cell->name.c_str(), cell->type.c_str(), + parameter_id.c_str()); + } + if (parameter_id == ID(IO_LOC_PAIRS) and cell->hasParam(parameter_id)) { + std::string cur_value(cell->getParam(parameter_id).decode_string()); + value = cur_value + "," + value; + } + cell->setParam(parameter_id, RTLIL::Const(value)); + log("Setting parameter %s to value %s on cell %s \n", parameter_id.c_str(), value.c_str(), cell_obj.first.c_str()); + } + } + } + log("\n"); + } - // Search module's connections for the specified destination port - // and traverse from the specified destination wire to the source wire - void traverse_wire(std::string& port_name, RTLIL::Module* module) { - auto port_signal = extract_signal(port_name); - std::string signal_name(port_signal.first); - auto signal_name_idstr = RTLIL::IdString(RTLIL::escape_id(signal_name)); - int port_bit = port_signal.second; - for (auto connection : module->connections_) { - auto dst_sig = connection.first; - auto src_sig = connection.second; - if (dst_sig.is_chunk()) { - auto chunk = dst_sig.as_chunk(); - if (chunk.wire) { - if (chunk.wire->name != signal_name_idstr) { - continue; - } - if (port_bit < chunk.offset || port_bit >= (chunk.offset + chunk.width)) { - continue; - } - auto src_wires = src_sig.to_sigbit_vector(); - auto src_wire_sigbit = src_wires.at(port_bit - chunk.offset); - if (src_wire_sigbit.wire) { - port_name = src_wires.at(port_bit - chunk.offset).wire->name.str(); - if (src_wire_sigbit.offset > 0) { - port_name += "[" + std::to_string(src_wire_sigbit.offset) + "]"; - } - return; - } - } - } - } - } + // Search module's connections for the specified destination port + // and traverse from the specified destination wire to the source wire + void traverse_wire(std::string &port_name, RTLIL::Module *module) + { + auto port_signal = extract_signal(port_name); + std::string signal_name(port_signal.first); + auto signal_name_idstr = RTLIL::IdString(RTLIL::escape_id(signal_name)); + int port_bit = port_signal.second; + for (auto connection : module->connections_) { + auto dst_sig = connection.first; + auto src_sig = connection.second; + if (dst_sig.is_chunk()) { + auto chunk = dst_sig.as_chunk(); + if (chunk.wire) { + if (chunk.wire->name != signal_name_idstr) { + continue; + } + if (port_bit < chunk.offset || port_bit >= (chunk.offset + chunk.width)) { + continue; + } + auto src_wires = src_sig.to_sigbit_vector(); + auto src_wire_sigbit = src_wires.at(port_bit - chunk.offset); + if (src_wire_sigbit.wire) { + port_name = src_wires.at(port_bit - chunk.offset).wire->name.str(); + if (src_wire_sigbit.offset > 0) { + port_name += "[" + std::to_string(src_wire_sigbit.offset) + "]"; + } + return; + } + } + } + } + } - // Extract signal name and port bit information from port name - std::pair<std::string, int> extract_signal(const std::string& port_name) { - int port_bit(0); - std::string port_str(port_name.size(), '\0'); - sscanf(port_name.c_str(), "%[^[][%d]", &port_str[0], &port_bit); - port_str.resize(strlen(port_str.c_str())); - return std::make_pair(port_str, port_bit); - } + // Extract signal name and port bit information from port name + std::pair<std::string, int> extract_signal(const std::string &port_name) + { + int port_bit(0); + std::string port_str(port_name.size(), '\0'); + sscanf(port_name.c_str(), "%[^[][%d]", &port_str[0], &port_bit); + port_str.resize(strlen(port_str.c_str())); + return std::make_pair(port_str, port_bit); + } - // Check if the specified port name is part of the provided connection signal - bool is_signal_port(RTLIL::SigSpec signal, const std::string& port_name) { - auto port_signal = extract_signal(port_name); - std::string port(port_signal.first); - int port_bit = port_signal.second; - if (signal.is_chunk()) { - auto chunk = signal.as_chunk(); - if (chunk.wire) { - return (chunk.wire->name == RTLIL::IdString(RTLIL::escape_id(port))) && - (port_bit == chunk.offset); - } - } - return false; - } + // Check if the specified port name is part of the provided connection signal + bool is_signal_port(RTLIL::SigSpec signal, const std::string &port_name) + { + auto port_signal = extract_signal(port_name); + std::string port(port_signal.first); + int port_bit = port_signal.second; + if (signal.is_chunk()) { + auto chunk = signal.as_chunk(); + if (chunk.wire) { + return (chunk.wire->name == RTLIL::IdString(RTLIL::escape_id(port))) && (port_bit == chunk.offset); + } + } + return false; + } - std::function<const BankTilesMap&()> get_bank_tiles; + std::function<const BankTilesMap &()> get_bank_tiles; }; struct ReadXdc : public Frontend { - ReadXdc() - : Frontend("xdc", "Read XDC file") - , GetIOBanks(std::bind(&ReadXdc::get_bank_tiles, this)) - , SetProperty(std::bind(&ReadXdc::get_bank_tiles, this)) {} + ReadXdc() + : Frontend("xdc", "Read XDC file"), GetIOBanks(std::bind(&ReadXdc::get_bank_tiles, this)), + SetProperty(std::bind(&ReadXdc::get_bank_tiles, this)) + { + } - void help() override { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" read_xdc -part_json <part_json_filename> <filename>\n"); - log("\n"); - log("Read XDC file.\n"); - log("\n"); - } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" read_xdc -part_json <part_json_filename> <filename>\n"); + log("\n"); + log("Read XDC file.\n"); + log("\n"); + } - void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*) override { - if (args.size() < 2) { - log_cmd_error("Missing script file.\n"); - } - size_t argidx = 1; - bank_tiles.clear(); - if (args[argidx] == "-part_json" && argidx + 1 < args.size()) { - bank_tiles = ::get_bank_tiles(args[++argidx]); - argidx++; - } - extra_args(f, filename, args, argidx); - std::string content{std::istreambuf_iterator<char>(*f), std::istreambuf_iterator<char>()}; - log("%s\n", content.c_str()); + void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *) override + { + if (args.size() < 2) { + log_cmd_error("Missing script file.\n"); + } + size_t argidx = 1; + bank_tiles.clear(); + if (args[argidx] == "-part_json" && argidx + 1 < args.size()) { + bank_tiles = ::get_bank_tiles(args[++argidx]); + argidx++; + } + extra_args(f, filename, args, argidx); + std::string content{std::istreambuf_iterator<char>(*f), std::istreambuf_iterator<char>()}; + log("%s\n", content.c_str()); - // According to page 6 of UG903 XDC is tcl, hence quoting of bracketed numbers, - // such as bus indexes, is required. For example "signal[5]" would be typically - // expanded to the concatenation of the string "signal" and result of the function call "5" - // with no arguments. Therefore in TCL the signal indices have to be wrapped in curly braces - // e.g "{signal[5]}" in order for the interpreter to not perform any variable substitution - // or function calls on the wrapped content. - // - // Nevertheless, it's quite common for EDA tools to allow for specifying signal indices - // (e.g. "signal[5]") without using non-expanding quotes. - // Possible TCL implementations of such a feature include registering a TCL command - // for each integer which returns itself but surrounded with brackets or using the 'unknown' - // command which is invoked by the Tcl interpreter whenever a script tries to invoke a command - // that does not exist. In the XDC plugin the latter approach is used, however it's limited to - // the 'read_xdc' command, hence the 'unknown' command works solely on the content of the XDC file. - // - // In this implementation the signal "signal[5]" is expanded in TCL to the concatenation of a string - // and function call, however this time the handling of the non-existent command '5' is passed by - // the interpreter to the 'unknown' command which returns a string that consists of the indice - // integer surrounded by square brackets, i.e. "[5]", effectively expanding the signal to "signal[5]" - // string. - // - Tcl_Interp* interp = yosys_get_tcl_interp(); - Tcl_Eval(interp, "rename unknown _original_unknown"); - Tcl_Eval(interp, "proc unknown args { return \\[[lindex $args 0]\\] }"); - if (Tcl_EvalFile(interp, args[argidx].c_str()) != TCL_OK) { - log_cmd_error("TCL interpreter returned an error: %s\n", Tcl_GetStringResult(interp)); - } - Tcl_Eval(interp, "rename unknown \"\""); - Tcl_Eval(interp, "rename _original_unknown unknown"); - } - const BankTilesMap& get_bank_tiles() { - return bank_tiles; - } + // According to page 6 of UG903 XDC is tcl, hence quoting of bracketed numbers, + // such as bus indexes, is required. For example "signal[5]" would be typically + // expanded to the concatenation of the string "signal" and result of the function call "5" + // with no arguments. Therefore in TCL the signal indices have to be wrapped in curly braces + // e.g "{signal[5]}" in order for the interpreter to not perform any variable substitution + // or function calls on the wrapped content. + // + // Nevertheless, it's quite common for EDA tools to allow for specifying signal indices + // (e.g. "signal[5]") without using non-expanding quotes. + // Possible TCL implementations of such a feature include registering a TCL command + // for each integer which returns itself but surrounded with brackets or using the 'unknown' + // command which is invoked by the Tcl interpreter whenever a script tries to invoke a command + // that does not exist. In the XDC plugin the latter approach is used, however it's limited to + // the 'read_xdc' command, hence the 'unknown' command works solely on the content of the XDC file. + // + // In this implementation the signal "signal[5]" is expanded in TCL to the concatenation of a string + // and function call, however this time the handling of the non-existent command '5' is passed by + // the interpreter to the 'unknown' command which returns a string that consists of the indice + // integer surrounded by square brackets, i.e. "[5]", effectively expanding the signal to "signal[5]" + // string. + // + Tcl_Interp *interp = yosys_get_tcl_interp(); + Tcl_Eval(interp, "rename unknown _original_unknown"); + Tcl_Eval(interp, "proc unknown args { return \\[[lindex $args 0]\\] }"); + if (Tcl_EvalFile(interp, args[argidx].c_str()) != TCL_OK) { + log_cmd_error("TCL interpreter returned an error: %s\n", Tcl_GetStringResult(interp)); + } + Tcl_Eval(interp, "rename unknown \"\""); + Tcl_Eval(interp, "rename _original_unknown unknown"); + } + const BankTilesMap &get_bank_tiles() { return bank_tiles; } - BankTilesMap bank_tiles; - struct GetIOBanks GetIOBanks; - struct SetProperty SetProperty; + BankTilesMap bank_tiles; + struct GetIOBanks GetIOBanks; + struct SetProperty SetProperty; } ReadXdc; struct GetBankTiles : public Pass { - GetBankTiles() - : Pass("get_bank_tiles", "Inspect IO Bank tiles") { - register_in_tcl_interpreter(pass_name); - } + GetBankTiles() : Pass("get_bank_tiles", "Inspect IO Bank tiles") { register_in_tcl_interpreter(pass_name); } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" get_bank_tiles <part_json_file>\n"); - log("\n"); - log("Inspect IO Bank tiles for the specified part based on the provided JSON file.\n"); - log("\n"); - } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" get_bank_tiles <part_json_file>\n"); + log("\n"); + log("Inspect IO Bank tiles for the specified part based on the provided JSON file.\n"); + log("\n"); + } - void execute(std::vector<std::string> args, RTLIL::Design* ) override { - if (args.size() < 2) { - log_cmd_error("Missing JSON file.\n"); - } - // Check if the part has the specified bank - auto bank_tiles = get_bank_tiles(args[1]); - if (bank_tiles.size()) { - log("Available bank tiles:\n"); - for (auto bank : bank_tiles) { - log("Bank: %d, Tile: %s\n", bank.first, bank.second.c_str()); - } - log("\n"); - } else { - log("No bank tiles available.\n"); - } - } + void execute(std::vector<std::string> args, RTLIL::Design *) override + { + if (args.size() < 2) { + log_cmd_error("Missing JSON file.\n"); + } + // Check if the part has the specified bank + auto bank_tiles = get_bank_tiles(args[1]); + if (bank_tiles.size()) { + log("Available bank tiles:\n"); + for (auto bank : bank_tiles) { + log("Bank: %d, Tile: %s\n", bank.first, bank.second.c_str()); + } + log("\n"); + } else { + log("No bank tiles available.\n"); + } + } } GetBankTiles; PRIVATE_NAMESPACE_END