diff --git a/kernel/tclapi.cc b/kernel/tclapi.cc index 8541b8d20..f8520331b 100644 --- a/kernel/tclapi.cc +++ b/kernel/tclapi.cc @@ -532,64 +532,6 @@ static int tcl_set_param(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *cons return TCL_OK; } -static int sdc_get_pins_cmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) -{ - (void)interp; - bool hierarchical_flag = false; - bool regexp_flag = false; - bool nocase_flag = false; - std::string separator = "/"; - Tcl_Obj* of_objects; - std::vector patterns; - int i = 1; - for (; i < objc; i++) { - FLAG2(hierarchical) - FLAG2(regexp) - FLAG2(nocase) - if (!strcmp(Tcl_GetString(objv[i]), "-hsc")) { - i++; - separator = Tcl_GetString(objv[i]); - continue; - } - if (!strcmp(Tcl_GetString(objv[i]), "-of_objects")) { - i++; - of_objects = objv[i]; - continue; - } - // Onto the next loop - break; - } - for (; i < objc; i++) { - patterns.push_back(Tcl_GetString(objv[i])); - } - log("get_pins patterns:\n"); - for (auto pat : patterns) { - log("\t%s\n", pat.c_str()); - } - (void)hierarchical_flag; - (void)regexp_flag; - (void)nocase_flag; - (void)separator; - (void)of_objects; - return TCL_OK; -} -static int sdc_dummy_cmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) -{ - (void)interp; - (void)objc; - log("Ignoring known SDC command %s\n", Tcl_GetString(objv[0])); - return TCL_OK; -} - -int yosys_sdc_interp_init(Tcl_Interp *interp) -{ - if (Tcl_Init(interp)!=TCL_OK) - log_warning("Tcl_Init() call failed - %s\n",Tcl_ErrnoMsg(Tcl_GetErrno())); - Tcl_CreateObjCommand(interp, "set_false_path", sdc_dummy_cmd, NULL, NULL); - Tcl_CreateObjCommand(interp, "get_pins", sdc_get_pins_cmd, NULL, NULL); - return TCL_OK; -} - int yosys_tcl_interp_init(Tcl_Interp *interp) { if (Tcl_Init(interp)!=TCL_OK) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 0de242805..33345c3b1 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -363,7 +363,6 @@ void rewrite_filename(std::string &filename) // defined in tclapi.cc extern int yosys_tcl_interp_init(Tcl_Interp *interp); -extern int yosys_sdc_interp_init(Tcl_Interp *interp); extern Tcl_Interp *yosys_get_tcl_interp() { @@ -373,15 +372,8 @@ extern Tcl_Interp *yosys_get_tcl_interp() } return yosys_tcl_interp; } -extern Tcl_Interp *yosys_get_sdc_interp() -{ - if (yosys_sdc_interp == NULL) { - yosys_sdc_interp = Tcl_CreateInterp(); - yosys_sdc_interp_init(yosys_sdc_interp); - } - return yosys_sdc_interp; -} +// Also see SdcPass struct TclPass : public Pass { TclPass() : Pass("tcl", "execute a TCL script file") { } void help() override { @@ -424,26 +416,7 @@ struct TclPass : public Pass { Tcl_Release(interp); } } TclPass; -struct SdcPass : public Pass { - SdcPass() : Pass("sdc", "sniff at some SDC") { } - void execute(std::vector args, RTLIL::Design *) override { - if (args.size() < 2) - log_cmd_error("Missing script file.\n"); - std::vector script_args; - for (auto it = args.begin() + 2; it != args.end(); ++it) - script_args.push_back(Tcl_NewStringObj((*it).c_str(), (*it).size())); - - Tcl_Interp *interp = yosys_get_sdc_interp(); - Tcl_Preserve(interp); - Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argc", 4), NULL, Tcl_NewIntObj(script_args.size()), 0); - Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argv", 4), NULL, Tcl_NewListObj(script_args.size(), script_args.data()), 0); - Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argv0", 5), NULL, Tcl_NewStringObj(args[1].c_str(), args[1].size()), 0); - if (Tcl_EvalFile(interp, args[1].c_str()) != TCL_OK) - log_cmd_error("SDC interpreter returned an error: %s\n", Tcl_GetStringResult(interp)); - Tcl_Release(interp); - } -} SdcPass; #endif #if defined(__linux__) || defined(__CYGWIN__) diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc index 4ecaea7dd..d6f7023f3 100644 --- a/passes/cmds/Makefile.inc +++ b/passes/cmds/Makefile.inc @@ -56,3 +56,6 @@ OBJS += passes/cmds/setenv.o OBJS += passes/cmds/abstract.o OBJS += passes/cmds/test_select.o OBJS += passes/cmds/timeest.o +OBJS += passes/cmds/sdc.o + +$(eval $(call add_share_file,share/sdc,passes/cmds/stubs.sdc)) diff --git a/passes/cmds/sdc.cc b/passes/cmds/sdc.cc new file mode 100644 index 000000000..539b349f7 --- /dev/null +++ b/passes/cmds/sdc.cc @@ -0,0 +1,112 @@ +#include "kernel/register.h" +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/log.h" +#include + + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +template +static bool parse_flag(char* arg, const char* flag_name, T& flag_var) { + std::string expected = std::string("-") + flag_name; + if (expected == arg) { + flag_var = true; + return true; + } + return false; +} + +static int sdc_get_pins_cmd(ClientData, Tcl_Interp *interp, int objc, Tcl_Obj* const objv[]) +{ + (void)interp; + bool hierarchical_flag = false; + bool regexp_flag = false; + bool nocase_flag = false; + std::string separator = "/"; + Tcl_Obj* of_objects; + std::vector patterns; + int i = 1; + for (; i < objc; i++) { + if (parse_flag(Tcl_GetString(objv[i]), "hierarchical", hierarchical_flag)) + if (parse_flag(Tcl_GetString(objv[i]), "regexp", regexp_flag)) continue; + if (parse_flag(Tcl_GetString(objv[i]), "nocase", nocase_flag)) continue; + if (!strcmp(Tcl_GetString(objv[i]), "-hsc")) { + separator = Tcl_GetString(objv[++i]); + continue; + } + if (!strcmp(Tcl_GetString(objv[i]), "-of_objects")) { + of_objects = objv[++i]; + continue; + } + // Onto the next loop + break; + } + for (; i < objc; i++) { + patterns.push_back(Tcl_GetString(objv[i])); + } + log("get_pins patterns:\n"); + for (auto pat : patterns) { + log("\t%s\n", pat.c_str()); + } + (void)hierarchical_flag; + (void)regexp_flag; + (void)nocase_flag; + (void)separator; + (void)of_objects; + return TCL_OK; +} + +class SDCInterpreter +{ +private: + Tcl_Interp* interp = nullptr; +public: + ~SDCInterpreter() { + if (interp) + Tcl_DeleteInterp(interp); + } + static SDCInterpreter& get() { + static SDCInterpreter instance; + return instance; + } + Tcl_Interp* fresh_interp() { + if (interp) + Tcl_DeleteInterp(interp); + interp = Tcl_CreateInterp(); + if (Tcl_Init(interp)!=TCL_OK) + log_warning("Tcl_Init() call failed - %s\n",Tcl_ErrnoMsg(Tcl_GetErrno())); + Tcl_CreateObjCommand(interp, "get_pins", sdc_get_pins_cmd, NULL, NULL); + return interp; + } +}; + +// Also see TclPass +struct SdcPass : public Pass { + SdcPass() : Pass("sdc", "sniff at some SDC") { } + void execute(std::vector args, RTLIL::Design *) override { + if (args.size() < 2) + log_cmd_error("Missing script file.\n"); + + std::vector script_args; + for (auto it = args.begin() + 2; it != args.end(); ++it) + script_args.push_back(Tcl_NewStringObj((*it).c_str(), (*it).size())); + + Tcl_Interp *interp = SDCInterpreter::get().fresh_interp(); + Tcl_Preserve(interp); + Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argc", 4), NULL, Tcl_NewIntObj(script_args.size()), 0); + Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argv", 4), NULL, Tcl_NewListObj(script_args.size(), script_args.data()), 0); + Tcl_ObjSetVar2(interp, Tcl_NewStringObj("argv0", 5), NULL, Tcl_NewStringObj(args[1].c_str(), args[1].size()), 0); + + std::string stub_path = "+/sdc/stubs.sdc"; + rewrite_filename(stub_path); + if (Tcl_EvalFile(interp, stub_path.c_str()) != TCL_OK) + log_cmd_error("SDC interpreter returned an error in stub file: %s\n", Tcl_GetStringResult(interp)); + if (Tcl_EvalFile(interp, args[1].c_str()) != TCL_OK) + log_cmd_error("SDC interpreter returned an error: %s\n", Tcl_GetStringResult(interp)); + Tcl_Release(interp); + } +} SdcPass; + +YOSYS_NAMESPACE_END diff --git a/passes/cmds/stubs.sdc b/passes/cmds/stubs.sdc new file mode 100644 index 000000000..bf41c4620 --- /dev/null +++ b/passes/cmds/stubs.sdc @@ -0,0 +1 @@ +proc set_false_path {args} {} \ No newline at end of file