2018-09-28 17:54:21 +02:00
|
|
|
// OpenSTA, Static Timing Analyzer
|
2024-01-12 01:34:49 +01:00
|
|
|
// Copyright (c) 2024, 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
|
2022-01-04 18:17:08 +01:00
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2018-09-28 17:54:21 +02:00
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
2022-01-04 18:17:08 +01:00
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2018-09-28 17:54:21 +02:00
|
|
|
|
2020-04-05 23:53:44 +02:00
|
|
|
#include "StaMain.hh"
|
2022-10-24 18:18:01 +02:00
|
|
|
#include "StaConfig.hh" // STA_VERSION
|
2020-04-05 20:35:51 +02:00
|
|
|
|
2018-09-28 17:54:21 +02:00
|
|
|
#include <stdio.h>
|
2020-12-26 17:29:43 +01:00
|
|
|
#include <cstdlib> // exit
|
2019-11-17 02:11:25 +01:00
|
|
|
#include <tcl.h>
|
2022-10-24 18:18:01 +02:00
|
|
|
#if TCL_READLINE
|
|
|
|
|
#include <tclreadline.h>
|
|
|
|
|
#endif
|
2020-04-05 20:35:51 +02:00
|
|
|
|
2020-04-05 23:53:44 +02:00
|
|
|
#include "Sta.hh"
|
2018-09-28 17:54:21 +02:00
|
|
|
|
2019-11-17 02:11:25 +01:00
|
|
|
namespace sta {
|
|
|
|
|
extern const char *tcl_inits[];
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-30 16:05:50 +01:00
|
|
|
using std::string;
|
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::sourceTclFile;
|
|
|
|
|
using sta::parseThreadsArg;
|
|
|
|
|
using sta::tcl_inits;
|
2024-08-06 02:27:53 +02:00
|
|
|
using sta::is_regular_file;
|
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
|
2020-01-10 00:16:07 +01:00
|
|
|
initStaApp(int &argc,
|
2019-11-17 02:11:25 +01:00
|
|
|
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,
|
2019-06-15 01:53:03 +02:00
|
|
|
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
|
2022-10-24 18:18:01 +02:00
|
|
|
if (Tcl_Init(interp) == TCL_ERROR)
|
|
|
|
|
return TCL_ERROR;
|
|
|
|
|
|
|
|
|
|
#if TCL_READLINE
|
|
|
|
|
if (Tclreadline_Init(interp) == TCL_ERROR)
|
|
|
|
|
return TCL_ERROR;
|
|
|
|
|
Tcl_StaticPackage(interp, "tclreadline", Tclreadline_Init, Tclreadline_SafeInit);
|
|
|
|
|
if (Tcl_EvalFile(interp, TCLRL_LIBRARY "/tclreadlineInit.tcl") != TCL_OK)
|
|
|
|
|
printf("Failed to load tclreadline.tcl\n");
|
|
|
|
|
#endif
|
2019-11-17 02:11:25 +01:00
|
|
|
|
|
|
|
|
initStaApp(argc, argv, interp);
|
|
|
|
|
|
|
|
|
|
if (!findCmdLineFlag(argc, argv, "-no_splash"))
|
|
|
|
|
Tcl_Eval(interp, "sta::show_splash");
|
|
|
|
|
|
|
|
|
|
if (!findCmdLineFlag(argc, argv, "-no_init")) {
|
2022-01-15 20:51:05 +01:00
|
|
|
const char *home = getenv("HOME");
|
|
|
|
|
if (home) {
|
|
|
|
|
string init_path = home;
|
|
|
|
|
init_path += "/";
|
|
|
|
|
init_path += init_filename;
|
2024-08-06 02:27:53 +02:00
|
|
|
if (is_regular_file(init_path.c_str()))
|
2022-01-15 20:51:05 +01:00
|
|
|
sourceTclFile(init_path.c_str(), true, true, interp);
|
|
|
|
|
}
|
2019-11-17 02:11:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool exit_after_cmd_file = findCmdLineFlag(argc, argv, "-exit");
|
|
|
|
|
|
2024-06-27 22:57:58 +02:00
|
|
|
if (argc > 2
|
|
|
|
|
|| (argc > 1 && argv[1][0] == '-')) {
|
2019-11-17 02:11:25 +01:00
|
|
|
showUsage(argv[0], init_filename);
|
2020-12-25 00:54:26 +01:00
|
|
|
exit(1);
|
|
|
|
|
}
|
2019-11-17 02:11:25 +01:00
|
|
|
else {
|
|
|
|
|
if (argc == 2) {
|
|
|
|
|
char *cmd_file = argv[1];
|
|
|
|
|
if (cmd_file) {
|
2020-11-13 20:46:19 +01:00
|
|
|
int result = sourceTclFile(cmd_file, false, false, interp);
|
|
|
|
|
if (exit_after_cmd_file) {
|
|
|
|
|
int exit_code = (result == TCL_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
|
|
|
exit(exit_code);
|
|
|
|
|
}
|
2019-11-17 02:11:25 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-24 18:18:01 +02:00
|
|
|
#if TCL_READLINE
|
|
|
|
|
return Tcl_Eval(interp, "::tclreadline::Loop");
|
|
|
|
|
#else
|
2019-11-17 02:11:25 +01:00
|
|
|
return TCL_OK;
|
2022-10-24 18:18:01 +02:00
|
|
|
#endif
|
2019-11-17 02:11:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-01-10 00:16:07 +01:00
|
|
|
initStaApp(int &argc,
|
2019-11-17 02:11:25 +01:00
|
|
|
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);
|
2022-11-15 23:35:17 +01:00
|
|
|
Tcl_Eval(interp, "init_sta_cmds");
|
2019-11-17 02:11:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
}
|