Migrate static helper functions in `StaTclTypes.i` to non-static functions in `TclTypeHelpers.cc`/`.hh` (#182)

* Migrate static helper functions in StaTclTypes.i to non-static functions in StaTclTypeHelpers.cc/.hh

* Rename and reorder as requested
This commit is contained in:
Akash Levy 2025-01-17 11:15:00 -08:00 committed by GitHub
parent aaa9d2d377
commit cc3b911b6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 269 additions and 180 deletions

View File

@ -125,6 +125,11 @@ set(STA_SOURCE
parasitics/SpefNamespace.cc
parasitics/SpefReader.cc
parasitics/SpefReaderPvt.hh
power/Power.cc
power/VcdReader.cc
power/SaifReader.cc
power/VcdParse.cc
sdc/Clock.cc
sdc/ClockGatingCheck.cc
@ -198,10 +203,7 @@ set(STA_SOURCE
spice/WriteSpice.cc
spice/Xyce.cc
power/Power.cc
power/VcdReader.cc
power/SaifReader.cc
power/VcdParse.cc
tcl/TclTypeHelpers.cc
util/Debug.cc
util/DispatchQueue.cc

View File

@ -0,0 +1,61 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2024, Parallax Software, Inc.
//
// 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 "ArcDelayCalc.hh"
#include "StringSet.hh"
#include "StringSeq.hh"
#include <tcl.h>
namespace sta {
#if TCL_MAJOR_VERSION < 9
typedef int Tcl_Size;
#endif
StringSet *
tclListSetConstChar(Tcl_Obj *const source,
Tcl_Interp *interp);
StringSeq *
tclListSeqConstChar(Tcl_Obj *const source,
Tcl_Interp *interp);
StdStringSet *
tclListSetStdString(Tcl_Obj *const source,
Tcl_Interp *interp);
void
tclArgError(Tcl_Interp *interp,
const char *msg,
const char *arg);
void
objectListNext(const char *list,
const char *type,
// Return values.
bool &type_match,
const char *&next);
Tcl_Obj *
tclArcDcalcArg(ArcDcalcArg &gate,
Tcl_Interp *interp);
ArcDcalcArg
arcDcalcArgTcl(Tcl_Obj *obj,
Tcl_Interp *interp);
} // namespace

View File

@ -39,9 +39,9 @@
#include "PathEnd.hh"
#include "SearchClass.hh"
#include "CircuitSim.hh"
#include "ArcDelayCalc.hh"
#include "Property.hh"
#include "Sta.hh"
#include "TclTypeHelpers.hh"
namespace sta {
@ -190,66 +190,6 @@ tclListNetworkSet1(Tcl_Obj *const source,
return set;
}
static StringSet *
tclListSetConstChar(Tcl_Obj *const source,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
StringSet *set = new StringSet;
for (int i = 0; i < argc; i++) {
int length;
const char *str = Tcl_GetStringFromObj(argv[i], &length);
set->insert(str);
}
return set;
}
else
return nullptr;
}
static StringSeq *
tclListSeqConstChar(Tcl_Obj *const source,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
StringSeq *seq = new StringSeq;
for (int i = 0; i < argc; i++) {
int length;
const char *str = Tcl_GetStringFromObj(argv[i], &length);
seq->push_back(str);
}
return seq;
}
else
return nullptr;
}
static StdStringSet *
tclListSetStdString(Tcl_Obj *const source,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
StdStringSet *set = new StdStringSet;
for (int i = 0; i < argc; i++) {
int length;
const char *str = Tcl_GetStringFromObj(argv[i], &length);
set->insert(str);
}
return set;
}
else
return nullptr;
}
////////////////////////////////////////////////////////////////
// Sequence out to tcl list.
@ -315,121 +255,6 @@ setPtrTclList(SET_TYPE *set,
////////////////////////////////////////////////////////////////
static void
tclArgError(Tcl_Interp *interp,
const char *msg,
const char *arg)
{
// Swig does not add try/catch around arg parsing so this cannot use Report::error.
string error_msg = "Error: ";
error_msg += msg;
char *error = stringPrint(error_msg.c_str(), arg);
Tcl_SetResult(interp, error, TCL_VOLATILE);
stringDelete(error);
}
static void
objectListNext(const char *list,
const char *type,
// Return values.
bool &type_match,
const char *&next)
{
// Default return values (failure).
type_match = false;
next = nullptr;
// _hexaddress_p_type
const char *s = list;
char ch = *s++;
if (ch == '_') {
while (*s && isxdigit(*s))
s++;
if ((s - list - 1) == sizeof(void*) * 2
&& *s && *s++ == '_'
&& *s && *s++ == 'p'
&& *s && *s++ == '_') {
const char *t = type;
while (*s && *s != ' ') {
if (*s != *t)
return;
s++;
t++;
}
type_match = true;
if (*s)
next = s + 1;
else
next = nullptr;
}
}
}
static Tcl_Obj *
tclArcDcalcArg(ArcDcalcArg &gate,
Tcl_Interp *interp)
{
Sta *sta = Sta::sta();
const Network *network = sta->network();
const Instance *drvr = network->instance(gate.drvrPin());
const TimingArc *arc = gate.arc();
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
Tcl_Obj *obj;
const char *inst_name = network->pathName(drvr);
obj = Tcl_NewStringObj(inst_name, strlen(inst_name));
Tcl_ListObjAppendElement(interp, list, obj);
const char *from_name = arc->from()->name();
obj = Tcl_NewStringObj(from_name, strlen(from_name));
Tcl_ListObjAppendElement(interp, list, obj);
const char *from_edge = arc->fromEdge()->asString();
obj = Tcl_NewStringObj(from_edge, strlen(from_edge));
Tcl_ListObjAppendElement(interp, list, obj);
const char *to_name = arc->to()->name();
obj = Tcl_NewStringObj(to_name, strlen(to_name));
Tcl_ListObjAppendElement(interp, list, obj);
const char *to_edge = arc->toEdge()->asString();
obj = Tcl_NewStringObj(to_edge, strlen(to_edge));
Tcl_ListObjAppendElement(interp, list, obj);
const char *input_delay = delayAsString(gate.inputDelay(), sta, 3);
obj = Tcl_NewStringObj(input_delay, strlen(input_delay));
Tcl_ListObjAppendElement(interp, list, obj);
return list;
}
static ArcDcalcArg
arcDcalcArgTcl(Tcl_Obj *obj,
Tcl_Interp *interp)
{
Sta *sta = Sta::sta();
sta->ensureGraph();
int list_argc;
Tcl_Obj **list_argv;
if (Tcl_ListObjGetElements(interp, obj, &list_argc, &list_argv) == TCL_OK) {
const char *input_delay = "0.0";
int length;
if (list_argc == 6)
input_delay = Tcl_GetStringFromObj(list_argv[5], &length);
if (list_argc == 5 || list_argc == 6) {
return makeArcDcalcArg(Tcl_GetStringFromObj(list_argv[0], &length),
Tcl_GetStringFromObj(list_argv[1], &length),
Tcl_GetStringFromObj(list_argv[2], &length),
Tcl_GetStringFromObj(list_argv[3], &length),
Tcl_GetStringFromObj(list_argv[4], &length),
input_delay, sta);
}
else
sta->report()->warn(2140, "Delay calc arg requires 5 or 6 args.");
}
return ArcDcalcArg();
}
} // namespace
using namespace sta;

201
tcl/TclTypeHelpers.cc Normal file
View File

@ -0,0 +1,201 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2024, Parallax Software, Inc.
//
// 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 "TclTypeHelpers.hh"
#include "Liberty.hh"
#include "Network.hh"
#include "Sta.hh"
namespace sta {
StringSet *
tclListSetConstChar(Tcl_Obj *const source,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
StringSet *set = new StringSet;
for (int i = 0; i < argc; i++) {
int length;
const char *str = Tcl_GetStringFromObj(argv[i], &length);
set->insert(str);
}
return set;
}
else
return nullptr;
}
StringSeq *
tclListSeqConstChar(Tcl_Obj *const source,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
StringSeq *seq = new StringSeq;
for (int i = 0; i < argc; i++) {
int length;
const char *str = Tcl_GetStringFromObj(argv[i], &length);
seq->push_back(str);
}
return seq;
}
else
return nullptr;
}
StdStringSet *
tclListSetStdString(Tcl_Obj *const source,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK) {
StdStringSet *set = new StdStringSet;
for (int i = 0; i < argc; i++) {
int length;
const char *str = Tcl_GetStringFromObj(argv[i], &length);
set->insert(str);
}
return set;
}
else
return nullptr;
}
void
tclArgError(Tcl_Interp *interp,
const char *msg,
const char *arg)
{
// Swig does not add try/catch around arg parsing so this cannot use Report::error.
string error_msg = "Error: ";
error_msg += msg;
char *error = stringPrint(error_msg.c_str(), arg);
Tcl_SetResult(interp, error, TCL_VOLATILE);
stringDelete(error);
}
void
objectListNext(const char *list,
const char *type,
// Return values.
bool &type_match,
const char *&next)
{
// Default return values (failure).
type_match = false;
next = nullptr;
// _hexaddress_p_type
const char *s = list;
char ch = *s++;
if (ch == '_') {
while (*s && isxdigit(*s))
s++;
if ((s - list - 1) == sizeof(void*) * 2
&& *s && *s++ == '_'
&& *s && *s++ == 'p'
&& *s && *s++ == '_') {
const char *t = type;
while (*s && *s != ' ') {
if (*s != *t)
return;
s++;
t++;
}
type_match = true;
if (*s)
next = s + 1;
else
next = nullptr;
}
}
}
Tcl_Obj *
tclArcDcalcArg(ArcDcalcArg &gate,
Tcl_Interp *interp)
{
Sta *sta = Sta::sta();
const Network *network = sta->network();
const Instance *drvr = network->instance(gate.drvrPin());
const TimingArc *arc = gate.arc();
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
Tcl_Obj *obj;
const char *inst_name = network->pathName(drvr);
obj = Tcl_NewStringObj(inst_name, strlen(inst_name));
Tcl_ListObjAppendElement(interp, list, obj);
const char *from_name = arc->from()->name();
obj = Tcl_NewStringObj(from_name, strlen(from_name));
Tcl_ListObjAppendElement(interp, list, obj);
const char *from_edge = arc->fromEdge()->asString();
obj = Tcl_NewStringObj(from_edge, strlen(from_edge));
Tcl_ListObjAppendElement(interp, list, obj);
const char *to_name = arc->to()->name();
obj = Tcl_NewStringObj(to_name, strlen(to_name));
Tcl_ListObjAppendElement(interp, list, obj);
const char *to_edge = arc->toEdge()->asString();
obj = Tcl_NewStringObj(to_edge, strlen(to_edge));
Tcl_ListObjAppendElement(interp, list, obj);
const char *input_delay = delayAsString(gate.inputDelay(), sta, 3);
obj = Tcl_NewStringObj(input_delay, strlen(input_delay));
Tcl_ListObjAppendElement(interp, list, obj);
return list;
}
ArcDcalcArg
arcDcalcArgTcl(Tcl_Obj *obj,
Tcl_Interp *interp)
{
Sta *sta = Sta::sta();
sta->ensureGraph();
int list_argc;
Tcl_Obj **list_argv;
if (Tcl_ListObjGetElements(interp, obj, &list_argc, &list_argv) == TCL_OK) {
const char *input_delay = "0.0";
int length;
if (list_argc == 6)
input_delay = Tcl_GetStringFromObj(list_argv[5], &length);
if (list_argc == 5 || list_argc == 6) {
return makeArcDcalcArg(Tcl_GetStringFromObj(list_argv[0], &length),
Tcl_GetStringFromObj(list_argv[1], &length),
Tcl_GetStringFromObj(list_argv[2], &length),
Tcl_GetStringFromObj(list_argv[3], &length),
Tcl_GetStringFromObj(list_argv[4], &length),
input_delay, sta);
}
else
sta->report()->warn(2140, "Delay calc arg requires 5 or 6 args.");
}
return ArcDcalcArg();
}
} // namespace