SDC: Add -of and -include_generated_clocks switches to get_clocks Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
diff --git a/sdc-plugin/sdc.cc b/sdc-plugin/sdc.cc index 880eeb2..14478cc 100644 --- a/sdc-plugin/sdc.cc +++ b/sdc-plugin/sdc.cc
@@ -21,10 +21,10 @@ #include "kernel/register.h" #include "kernel/rtlil.h" #include "propagation.h" +#include "sdc_writer.h" +#include "set_clock_groups.h" #include "set_false_path.h" #include "set_max_delay.h" -#include "set_clock_groups.h" -#include "sdc_writer.h" USING_YOSYS_NAMESPACE @@ -73,7 +73,8 @@ } void execute(std::ostream*& f, std::string filename, - std::vector<std::string> args, RTLIL::Design* design) override { + std::vector<std::string> args, + RTLIL::Design* design) override { if (args.size() < 2) { log_cmd_error("Missing output file.\n"); } @@ -86,8 +87,7 @@ }; struct CreateClockCmd : public Pass { - CreateClockCmd() - : Pass("create_clock", "Create clock object") {} + CreateClockCmd() : Pass("create_clock", "Create clock object") {} void help() override { log("\n"); @@ -169,8 +169,7 @@ rising_edge = 0; falling_edge = period / 2; } - Clock::Add(name, selected_wires, period, rising_edge, - falling_edge); + Clock::Add(name, selected_wires, period, rising_edge, falling_edge); } void AddWirePrefix(std::vector<std::string>& args, size_t argidx) { @@ -181,29 +180,92 @@ }; struct GetClocksCmd : public Pass { - GetClocksCmd() - : Pass("get_clocks", "Create clock object") {} + GetClocksCmd() : Pass("get_clocks", "Create clock object") {} void help() override { log("\n"); - log(" get_clocks\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; + } + + // TODO Check for GENERATED_CLOCK clock wire attribute + // For now don't treat any of the added clocks as auto-generated + bool IsGeneratedClock(RTLIL::Wire* clock_wire) { + (void)clock_wire; + return false; } void execute(std::vector<std::string> args, RTLIL::Design* design) override { - if (args.size() > 1) { - log_warning("Command doesn't support arguments, so they will be ignored.\n"); + bool generated_clocks(false); + std::vector<std::string> clocks_nets; + size_t argidx(0); + for (argidx = 1; argidx < args.size(); argidx++) { + std::string arg = args[argidx]; + if (arg == "-include_generated_clocks") { + generated_clocks = true; + continue; + } + if (arg == "-of" and argidx + 1 < args.size()) { + clocks_nets = extract_list(args[++argidx]); + continue; + } + if (arg.size() > 0 and arg[0] == '-') { + log_cmd_error("Unknown option %s.\n", arg.c_str()); + } + + break; } + std::vector<std::string> clocks_list(args.begin() + argidx, args.end()); std::map<std::string, RTLIL::Wire*> clocks(Clocks::GetClocks(design)); if (clocks.size() == 0) { log_warning("No clocks found in design\n"); } +#ifdef SDC_DEBUG + for (auto clock_net : clocks_nets) { + log("Clock filter %s\n", clock_net.c_str()); + } +#endif Tcl_Interp* interp = yosys_get_tcl_interp(); Tcl_Obj* tcl_list = Tcl_NewListObj(0, NULL); for (auto& clock : clocks) { + if (IsGeneratedClock(clock.second) and !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); @@ -228,15 +290,15 @@ 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"); + 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 BufferPropagation(design, this)), std::unique_ptr<Propagation>( new ClockDividerPropagation(design, this))};