OpenSTA/app/Main.cc

176 lines
4.5 KiB
C++
Raw Normal View History

2018-09-28 17:54:21 +02:00
// OpenSTA, Static Timing Analyzer
2019-01-01 21:26:11 +01:00
// Copyright (c) 2019, Parallax Software, Inc.
2018-09-28 17:54:21 +02:00
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <stdio.h>
2019-11-17 02:11:25 +01:00
#include <tcl.h>
2018-09-28 17:54:21 +02:00
#include "Machine.hh"
2019-02-16 21:07:59 +01:00
#include "StaConfig.hh" // STA_VERSION
2018-09-28 17:54:21 +02:00
#include "StringUtil.hh"
#include "Sta.hh"
#include "StaMain.hh"
2019-11-17 02:11:25 +01:00
namespace sta {
extern const char *tcl_inits[];
}
2018-09-28 17:54:21 +02:00
using sta::stringEq;
2019-11-17 02:11:25 +01:00
using sta::findCmdLineFlag;
2018-09-28 17:54:21 +02:00
using sta::Sta;
2019-11-17 02:11:25 +01:00
using sta::initSta;
using sta::evalTclInit;
using sta::stringPrintTmp;
using sta::sourceTclFile;
using sta::parseThreadsArg;
using sta::tcl_inits;
2018-09-28 17:54:21 +02:00
// Swig uses C linkage for init functions.
extern "C" {
extern int Sta_Init(Tcl_Interp *interp);
}
2019-11-17 02:11:25 +01:00
static int cmd_argc;
static char **cmd_argv;
static const char *init_filename = ".sta";
static void
showUsage(const char *prog,
const char *init_filename);
static int
tclAppInit(Tcl_Interp *interp);
static int
staTclAppInit(int argc,
char *argv[],
const char *init_filename,
Tcl_Interp *interp);
static void
initStaApp(int argc,
char *argv[],
Tcl_Interp *interp);
2019-05-20 01:06:06 +02:00
2018-09-28 17:54:21 +02:00
int
2019-06-01 17:07:38 +02:00
main(int argc,
char *argv[])
2018-09-28 17:54:21 +02:00
{
if (argc == 2 && stringEq(argv[1], "-help")) {
2019-11-17 02:11:25 +01:00
showUsage(argv[0], init_filename);
2018-09-28 17:54:21 +02:00
return 0;
}
else if (argc == 2 && stringEq(argv[1], "-version")) {
2019-02-16 21:07:59 +01:00
printf("%s\n", STA_VERSION);
2018-09-28 17:54:21 +02:00
return 0;
}
else {
2019-11-17 02:11:25 +01:00
// Set argc to 1 so Tcl_Main doesn't source any files.
// Tcl_Main never returns.
#if 0
// It should be possible to pass argc/argv to staTclAppInit with
// a closure but I couldn't get the signature to match Tcl_AppInitProc.
Tcl_Main(1, argv, [=](Tcl_Interp *interp)
{ sta::staTclAppInit(argc, argv, interp);
return 1;
});
#else
// Workaround.
cmd_argc = argc;
cmd_argv = argv;
Tcl_Main(1, argv, tclAppInit);
#endif
2018-09-28 17:54:21 +02:00
return 0;
}
}
2019-11-17 02:11:25 +01:00
static int
tclAppInit(Tcl_Interp *interp)
{
return staTclAppInit(cmd_argc, cmd_argv, init_filename, interp);
}
// Tcl init executed inside Tcl_Main.
static int
staTclAppInit(int argc,
char *argv[],
const char *init_filename,
Tcl_Interp *interp)
{
// source init.tcl
Tcl_Init(interp);
initStaApp(argc, argv, interp);
if (!findCmdLineFlag(argc, argv, "-no_splash"))
Tcl_Eval(interp, "sta::show_splash");
if (!findCmdLineFlag(argc, argv, "-no_init")) {
char *init_path = stringPrintTmp("[file join $env(HOME) %s]",
init_filename);
sourceTclFile(init_path, true, true, interp);
}
bool exit_after_cmd_file = findCmdLineFlag(argc, argv, "-exit");
if (argc > 2 ||
(argc > 1 && argv[1][0] == '-'))
showUsage(argv[0], init_filename);
else {
if (argc == 2) {
char *cmd_file = argv[1];
if (cmd_file) {
sourceTclFile(cmd_file, false, false, interp);
if (exit_after_cmd_file)
exit(EXIT_SUCCESS);
}
}
}
return TCL_OK;
}
static void
initStaApp(int argc,
char *argv[],
Tcl_Interp *interp)
{
initSta();
Sta *sta = new Sta;
Sta::setSta(sta);
sta->makeComponents();
sta->setTclInterp(interp);
int thread_count = parseThreadsArg(argc, argv);
sta->setThreadCount(thread_count);
// Define swig TCL commands.
Sta_Init(interp);
// Eval encoded sta TCL sources.
evalTclInit(interp, tcl_inits);
// Import exported commands from sta namespace to global namespace.
Tcl_Eval(interp, "sta::define_sta_cmds");
Tcl_Eval(interp, "namespace import sta::*");
}
static void
showUsage(const char *prog,
const char *init_filename)
{
printf("Usage: %s [-help] [-version] [-no_init] [-exit] cmd_file\n", prog);
printf(" -help show help and exit\n");
printf(" -version show version and exit\n");
printf(" -no_init do not read %s init file\n", init_filename);
printf(" -threads count|max use count threads\n");
printf(" -no_splash do not show the license splash at startup\n");
printf(" -exit exit after reading cmd_file\n");
printf(" cmd_file source cmd_file\n");
}