Improved/simplified TCL bindings

This commit is contained in:
Clifford Wolf 2013-05-01 14:21:03 +02:00
parent 83c743f717
commit 97f783e668
3 changed files with 57 additions and 40 deletions

View File

@ -149,10 +149,13 @@ static char **readline_completion(const char *text, int start, int)
return NULL;
}
static const char *create_prompt(RTLIL::Design *design)
static const char *create_prompt(RTLIL::Design *design, int recursion_counter)
{
static char buffer[100];
std::string str = "\nyosys";
std::string str = "\n";
if (recursion_counter > 1)
str += stringf("(%d) ", recursion_counter);
str += "yosys";
if (!design->selected_active_module.empty())
str += stringf(" [%s]", design->selected_active_module.c_str());
if (!design->selection_stack.back().full_selection) {
@ -168,26 +171,29 @@ static const char *create_prompt(RTLIL::Design *design)
static void shell(RTLIL::Design *design)
{
static bool recursion_detect = false;
static int recursion_counter = 0;
if (recursion_detect) {
log("Already in interactive shell.\n");
return;
}
recursion_detect = true;
recursion_counter++;
log_cmd_error_throw = true;
rl_readline_name = "yosys";
rl_attempted_completion_function = readline_completion;
char *command = NULL;
while ((command = readline(create_prompt(design))) != NULL)
while ((command = readline(create_prompt(design, recursion_counter))) != NULL)
{
if (command[strspn(command, " \t\r\n")] == 0)
continue;
add_history(command);
char *p = command + strspn(command, " \t\r\n");
if (!strncmp(p, "exit", 4)) {
p += 4;
p += strspn(p, " \t\r\n");
if (*p == 0)
break;
}
try {
assert(design->selection_stack.size() == 1);
Pass::call(design, command);
@ -197,8 +203,10 @@ static void shell(RTLIL::Design *design)
log_reset_stack();
}
}
if (command == NULL)
printf("exit\n");
recursion_detect = false;
recursion_counter--;
log_cmd_error_throw = false;
}
@ -233,7 +241,7 @@ struct ShellPass : public Pass {
log("This command is the default action if nothing else has been specified\n");
log("on the command line.\n");
log("\n");
log("Press Ctrl-D to leave the interactive shell.\n");
log("Press Ctrl-D or type 'exit' to leave the interactive shell.\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
@ -243,7 +251,7 @@ struct ShellPass : public Pass {
} ShellPass;
struct ScriptPass : public Pass {
ScriptPass() : Pass("script", "execute files from script file") { }
ScriptPass() : Pass("script", "execute commands from script file") { }
virtual void help() {
log("\n");
log(" script <filename>\n");
@ -252,12 +260,45 @@ struct ScriptPass : public Pass {
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
if (args.size() != 2)
if (args.size() < 2)
log_cmd_error("Missing script file.\n");
if (args.size() > 2)
extra_args(args, 1, design, false);
run_frontend(args[1], "script", design, NULL);
}
} ScriptPass;
#ifdef YOSYS_ENABLE_TCL
struct TclPass : public Pass {
TclPass() : Pass("tcl", "execute a TCL script file") { }
virtual void help() {
log("\n");
log(" tcl <filename>\n");
log("\n");
log("This command executes the tcl commands in the specified file.\n");
log("Use 'yosys cmd' to run the yosys command 'cmd' from tcl.\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
if (args.size() < 2)
log_cmd_error("Missing script file.\n");
if (args.size() > 2)
extra_args(args, 1, design, false);
if (Tcl_EvalFile(yosys_tcl, args[1].c_str()) != TCL_OK)
log_cmd_error("TCL interpreter returned an error: %s\n", Tcl_GetStringResult(yosys_tcl));
}
} TclPass;
static int tcl_yosys_cmd(ClientData, Tcl_Interp*, int argc, const char *argv[])
{
std::vector<std::string> args;
for (int i = 1; i < argc; i++)
args.push_back(argv[i]);
Pass::call(yosys_tcl_design, args);
return TCL_OK;
}
#endif
int main(int argc, char **argv)
{
std::string frontend_command = "auto";
@ -271,6 +312,7 @@ int main(int argc, char **argv)
#ifdef YOSYS_ENABLE_TCL
yosys_tcl = Tcl_CreateInterp();
Tcl_CreateCommand(yosys_tcl, "yosys", tcl_yosys_cmd, NULL, NULL);
#endif
int opt;
@ -356,6 +398,7 @@ int main(int argc, char **argv)
fprintf(stderr, "\n");
fprintf(stderr, " -c tcl_scriptfile\n");
fprintf(stderr, " execute the commands in the tcl script file\n");
fprintf(stderr, " (use 'yosys cmd' to run the yosys command 'cmd' from tcl)\n");
fprintf(stderr, "\n");
fprintf(stderr, " -p command\n");
fprintf(stderr, " execute the commands\n");

View File

@ -56,8 +56,6 @@ void Pass::run_register()
{
assert(pass_register.count(pass_name) == 0);
pass_register[pass_name] = this;
register_tcl();
}
void Pass::init_register()
@ -77,25 +75,6 @@ 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<std::string> 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()
{
}
@ -212,8 +191,6 @@ void Frontend::run_register()
assert(frontend_register.count(frontend_name) == 0);
frontend_register[frontend_name] = this;
register_tcl();
}
Frontend::~Frontend()
@ -306,8 +283,6 @@ void Backend::run_register()
assert(backend_register.count(backend_name) == 0);
backend_register[backend_name] = this;
register_tcl();
}
Backend::~Backend()

View File

@ -50,7 +50,6 @@ struct Pass
static void init_register();
static void done_register();
void register_tcl();
};
struct Frontend : Pass