From 73fba5164ffce53c766cc82dc0825f23baf996d3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Mar 2013 12:26:17 +0100 Subject: Implemented TCL support (only via -c option at the moment) --- Makefile | 3 +++ README | 4 ++-- kernel/driver.cc | 48 +++++++++++++++++++++++++++++++++++++++++------- kernel/register.cc | 30 ++++++++++++++++++++++++++++++ kernel/register.h | 7 +++++++ 5 files changed, 83 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index f406e7ac..c2477fe7 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,9 @@ CXX = gcc CXXFLAGS += -std=gnu++0x -march=native -O3 -DNDEBUG endif +CXXFLAGS += -I/usr/include/tcl8.5 -DYOSYS_ENABLE_TCL +LDLIBS += -ltcl8.5 + include frontends/*/Makefile.inc include passes/*/Makefile.inc include backends/*/Makefile.inc diff --git a/README b/README index d87d6a2f..6fe57081 100644 --- a/README +++ b/README @@ -246,8 +246,8 @@ TODOs / Open Bugs - Actually use range information on parameters - Add brief source code documentation to most passes and kernel code - Implement mux-to-tribuf pass and rebalance mixed mux/tribuf trees - - Add commands 'delete' (remove objects) and 'attr' (get, set and remove attributes) - - TCL and Python interfaces to frontends, passes, backends and RTLIL + - Add 'edit' command for changing the design (delete, add, modify objects) + - Improve TCL support and add 'list' command for inspecting the design from TCL - Additional internal cell types: $pla and $lut - Support for registering designs (as collection of modules) to CellTypes - Smarter resource sharing pass (add MUXes and get rid of duplicated cells) diff --git a/kernel/driver.cc b/kernel/driver.cc index 1dddefdc..cdb9e9ec 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -20,13 +20,13 @@ #include #include #include +#include +#include +#include #include "kernel/rtlil.h" #include "kernel/register.h" #include "kernel/log.h" -#include -#include -#include static void run_frontend(std::string filename, std::string command, RTLIL::Design *design, std::string *backend_command) { @@ -233,10 +233,15 @@ int main(int argc, char **argv) std::vector loaded_modules; std::string output_filename = ""; std::string scriptfile = ""; + bool scriptfile_tcl = false; bool got_output_filename = false; +#ifdef YOSYS_ENABLE_TCL + yosys_tcl = Tcl_CreateInterp(); +#endif + int opt; - while ((opt = getopt(argc, argv, "Sm:f:b:o:p:l:qts:")) != -1) + while ((opt = getopt(argc, argv, "Sm:f:b:o:p:l:qts:c:")) != -1) { switch (opt) { @@ -284,10 +289,15 @@ int main(int argc, char **argv) break; case 's': scriptfile = optarg; + scriptfile_tcl = false; + break; + case 'c': + scriptfile = optarg; + scriptfile_tcl = true; break; default: fprintf(stderr, "\n"); - fprintf(stderr, "Usage: %s [-S] [-q] [-t] [-l logfile] [-o ] [-f ] [-s ]\n", argv[0]); + fprintf(stderr, "Usage: %s [-S] [-q] [-t] [-l logfile] [-o ] [-f ] [{-s|-c} ]\n", argv[0]); fprintf(stderr, " %*s[-p [-p ..]] [-b ] [-m ] [ [..]]\n", int(strlen(argv[0])+1), ""); fprintf(stderr, "\n"); fprintf(stderr, " -q\n"); @@ -311,6 +321,9 @@ int main(int argc, char **argv) fprintf(stderr, " -s scriptfile\n"); fprintf(stderr, " execute the commands in the script file\n"); fprintf(stderr, "\n"); + fprintf(stderr, " -c tcl_scriptfile\n"); + fprintf(stderr, " execute the commands in the tcl script file\n"); + fprintf(stderr, "\n"); fprintf(stderr, " -p command\n"); fprintf(stderr, " execute the commands\n"); fprintf(stderr, "\n"); @@ -366,6 +379,10 @@ int main(int argc, char **argv) design->selection_stack.push_back(RTLIL::Selection()); log_push(); +#ifdef YOSYS_ENABLE_TCL + yosys_tcl_design = design; +#endif + if (optind == argc && passes_commands.size() == 0 && scriptfile.empty()) { if (!got_output_filename) backend_command = ""; @@ -375,8 +392,17 @@ int main(int argc, char **argv) while (optind < argc) run_frontend(argv[optind++], frontend_command, design, output_filename == "-" ? &backend_command : NULL); - if (!scriptfile.empty()) - run_frontend(scriptfile, "script", design, output_filename == "-" ? &backend_command : NULL); + if (!scriptfile.empty()) { + if (scriptfile_tcl) { +#ifdef YOSYS_ENABLE_TCL + if (Tcl_EvalFile(yosys_tcl, scriptfile.c_str()) != TCL_OK) + log_error("TCL interpreter returned an error: %s\n", Tcl_GetStringResult(yosys_tcl)); +#else + log_error("Can't exectue TCL script: this version of yosys is not built with TCL support enabled.\n"); +#endif + } else + run_frontend(scriptfile, "script", design, output_filename == "-" ? &backend_command : NULL); + } for (auto it = passes_commands.begin(); it != passes_commands.end(); it++) run_pass(*it, design); @@ -386,6 +412,10 @@ int main(int argc, char **argv) delete design; +#ifdef YOSYS_ENABLE_TCL + yosys_tcl_design = NULL; +#endif + log("\nREADY.\n"); log_pop(); @@ -400,6 +430,10 @@ int main(int argc, char **argv) for (auto mod : loaded_modules) dlclose(mod); +#ifdef YOSYS_ENABLE_TCL + Tcl_DeleteInterp(yosys_tcl); +#endif + return 0; } diff --git a/kernel/register.cc b/kernel/register.cc index 1dd60875..56222f73 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -27,6 +27,11 @@ using namespace REGISTER_INTERN; #define MAX_REG_COUNT 1000 +#ifdef YOSYS_ENABLE_TCL +Tcl_Interp *yosys_tcl = NULL; +RTLIL::Design *yosys_tcl_design = NULL; +#endif + namespace REGISTER_INTERN { int raw_register_count = 0; @@ -51,6 +56,8 @@ void Pass::run_register() { assert(pass_register.count(pass_name) == 0); pass_register[pass_name] = this; + + register_tcl(); } void Pass::init_register() @@ -70,6 +77,25 @@ void Pass::done_register() raw_register_done = false; } +#ifdef YOSYS_ENABLE_TCL +static int tcl_pass(ClientData that_vp, Tcl_Interp*, int argc, const char *argv[]) +{ + Pass *that = (Pass*)that_vp; + std::vector args; + for (int i = 0; i < argc; i++) + args.push_back(argv[i]); + that->call(yosys_tcl_design, args); + return TCL_OK; +} +#endif + +void Pass::register_tcl() +{ +#ifdef YOSYS_ENABLE_TCL + Tcl_CreateCommand(yosys_tcl, pass_name.c_str(), tcl_pass, (ClientData)this, NULL); +#endif +} + Pass::~Pass() { } @@ -189,6 +215,8 @@ void Frontend::run_register() assert(frontend_register.count(frontend_name) == 0); frontend_register[frontend_name] = this; + + register_tcl(); } Frontend::~Frontend() @@ -281,6 +309,8 @@ void Backend::run_register() assert(backend_register.count(backend_name) == 0); backend_register[backend_name] = this; + + register_tcl(); } Backend::~Backend() diff --git a/kernel/register.h b/kernel/register.h index a817d8c6..4e3cc5c1 100644 --- a/kernel/register.h +++ b/kernel/register.h @@ -26,6 +26,12 @@ #include #include +#ifdef YOSYS_ENABLE_TCL +#include +extern Tcl_Interp *yosys_tcl; +extern RTLIL::Design *yosys_tcl_design; +#endif + struct Pass { std::string pass_name, short_help; @@ -44,6 +50,7 @@ struct Pass static void init_register(); static void done_register(); + void register_tcl(); }; struct Frontend : Pass -- cgit v1.2.3