// 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 .
// Swig TCL input/output type parsers.
%{
#include "Machine.hh"
#include "StringUtil.hh"
#include "StringSet.hh"
#include "StringSeq.hh"
#include "PatternMatch.hh"
#include "Vector.hh"
#include "Network.hh"
#include "Liberty.hh"
#include "FuncExpr.hh"
#include "TimingArc.hh"
#include "TableModel.hh"
#include "TimingRole.hh"
#include "Graph.hh"
#include "NetworkClass.hh"
#include "Clock.hh"
#include "Corner.hh"
#include "Search.hh"
#include "PathRef.hh"
#include "search/Tag.hh"
#include "PathEnd.hh"
#include "SearchClass.hh"
#include "CircuitSim.hh"
#include "ArcDelayCalc.hh"
#include "Property.hh"
#include "Sta.hh"
namespace sta {
typedef MinPulseWidthCheckSeq::Iterator MinPulseWidthCheckSeqIterator;
typedef MinMaxAll MinMaxAllNull;
#if TCL_MAJOR_VERSION < 9
typedef int Tcl_Size;
#endif
template
Vector *
tclListSeqPtr(Tcl_Obj *const source,
swig_type_info *swig_type,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK
&& argc > 0) {
Vector *seq = new Vector;
for (int i = 0; i < argc; i++) {
void *obj;
// Ignore returned TCL_ERROR because can't get swig_type_info.
SWIG_ConvertPtr(argv[i], &obj, swig_type, false);
seq->push_back(reinterpret_cast(obj));
}
return seq;
}
else
return nullptr;
}
template
std::vector
tclListSeq(Tcl_Obj *const source,
swig_type_info *swig_type,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
std::vector seq;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK
&& argc > 0) {
for (int i = 0; i < argc; i++) {
void *obj;
// Ignore returned TCL_ERROR because can't get swig_type_info.
SWIG_ConvertPtr(argv[i], &obj, swig_type, false);
seq.push_back(reinterpret_cast(obj));
}
}
return seq;
}
template
SET_TYPE *
tclListSetPtr(Tcl_Obj *const source,
swig_type_info *swig_type,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK
&& argc > 0) {
SET_TYPE *set = new SET_TYPE;
for (int i = 0; i < argc; i++) {
void *obj;
// Ignore returned TCL_ERROR because can't get swig_type_info.
SWIG_ConvertPtr(argv[i], &obj, swig_type, false);
set->insert(reinterpret_cast(obj));
}
return set;
}
else
return nullptr;
}
template
SET_TYPE
tclListSet(Tcl_Obj *const source,
swig_type_info *swig_type,
Tcl_Interp *interp)
{
Tcl_Size argc;
Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK
&& argc > 0) {
SET_TYPE set;
for (int i = 0; i < argc; i++) {
void *obj;
// Ignore returned TCL_ERROR because can't get swig_type_info.
SWIG_ConvertPtr(argv[i], &obj, swig_type, false);
set.insert(reinterpret_cast(obj));
}
return set;
}
else
return SET_TYPE();
}
template
SET_TYPE *
tclListNetworkSet(Tcl_Obj *const source,
swig_type_info *swig_type,
Tcl_Interp *interp,
const Network *network)
{
Tcl_Size argc;
Tcl_Obj **argv;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK
&& argc > 0) {
SET_TYPE *set = new SET_TYPE(network);
for (int i = 0; i < argc; i++) {
void *obj;
// Ignore returned TCL_ERROR because can't get swig_type_info.
SWIG_ConvertPtr(argv[i], &obj, swig_type, false);
set->insert(reinterpret_cast(obj));
}
return set;
}
else
return nullptr;
}
template
SET_TYPE
tclListNetworkSet1(Tcl_Obj *const source,
swig_type_info *swig_type,
Tcl_Interp *interp,
const Network *network)
{
Tcl_Size argc;
Tcl_Obj **argv;
SET_TYPE set(network);
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK
&& argc > 0) {
for (int i = 0; i < argc; i++) {
void *obj;
// Ignore returned TCL_ERROR because can't get swig_type_info.
SWIG_ConvertPtr(argv[i], &obj, swig_type, false);
set.insert(reinterpret_cast(obj));
}
}
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.
template
void
seqPtrTclList(SEQ_TYPE *seq,
swig_type_info *swig_type,
Tcl_Interp *interp)
{
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (const OBJECT_TYPE *obj : *seq) {
Tcl_Obj *tcl_obj = SWIG_NewInstanceObj(const_cast(obj),
swig_type, false);
Tcl_ListObjAppendElement(interp, list, tcl_obj);
}
Tcl_SetObjResult(interp, list);
}
template
void
seqTclList(SEQ_TYPE &seq,
swig_type_info *swig_type,
Tcl_Interp *interp)
{
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (const OBJECT_TYPE *obj : seq) {
Tcl_Obj *tcl_obj = SWIG_NewInstanceObj(const_cast(obj),
swig_type, false);
Tcl_ListObjAppendElement(interp, list, tcl_obj);
}
Tcl_SetObjResult(interp, list);
}
template
void
setTclList(SET_TYPE set,
swig_type_info *swig_type,
Tcl_Interp *interp)
{
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (const OBJECT_TYPE *obj : set) {
Tcl_Obj *tcl_obj = SWIG_NewInstanceObj(const_cast(obj),
swig_type, false);
Tcl_ListObjAppendElement(interp, list, tcl_obj);
}
Tcl_SetObjResult(interp, list);
}
template
void
setPtrTclList(SET_TYPE *set,
swig_type_info *swig_type,
Tcl_Interp *interp)
{
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (const OBJECT_TYPE *obj : *set) {
Tcl_Obj *tcl_obj = SWIG_NewInstanceObj(const_cast(obj),
swig_type, false);
Tcl_ListObjAppendElement(interp, list, tcl_obj);
}
Tcl_SetObjResult(interp, list);
}
////////////////////////////////////////////////////////////////
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;
%}
////////////////////////////////////////////////////////////////
//
// SWIG type definitions.
//
////////////////////////////////////////////////////////////////
// String that is deleted after crossing over to tcland.
%typemap(out) string {
string &str = $1;
// String is volatile because it is deleted.
Tcl_SetResult(interp, const_cast(str.c_str()), TCL_VOLATILE);
}
// String that is deleted after crossing over to tcland.
%typemap(out) TmpString* {
string *str = $1;
if (str) {
// String is volatile because it is deleted.
Tcl_SetResult(interp, const_cast(str->c_str()), TCL_VOLATILE);
delete str;
}
else
Tcl_SetResult(interp, nullptr, TCL_STATIC);
}
%typemap(in) StringSeq* {
$1 = tclListSeqConstChar($input, interp);
}
%typemap(in) StdStringSet* {
$1 = tclListSetStdString($input, interp);
}
%typemap(out) StringSeq* {
StringSeq *strs = $1;
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (const char *str : *strs) {
Tcl_Obj *obj = Tcl_NewStringObj(str, strlen(str));
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
}
%typemap(out) StringSeq {
StringSeq &strs = $1;
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (const char *str : strs) {
Tcl_Obj *obj = Tcl_NewStringObj(str, strlen(str));
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
}
%typemap(out) Library* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) LibraryIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) LibertyLibraryIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) Cell* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(in) CellSeq* {
$1 = tclListSeqPtr($input, SWIGTYPE_p_Cell, interp);
}
%typemap(out) CellSeq {
seqTclList($1, SWIGTYPE_p_Cell, interp);
}
%typemap(in) LibertyCellSeq* {
$1 = tclListSeqPtr($input, SWIGTYPE_p_LibertyCell, interp);
}
%typemap(out) LibertyCellSeq * {
seqPtrTclList($1, SWIGTYPE_p_LibertyCell, interp);
}
%typemap(out) LibertyCellSeq {
seqTclList($1, SWIGTYPE_p_LibertyCell, interp);
}
%typemap(in) LibertyPortSeq* {
$1 = tclListSeqPtr($input, SWIGTYPE_p_LibertyPort, interp);
}
%typemap(out) LibertyPortSeq {
seqTclList($1, SWIGTYPE_p_LibertyPort, interp);
}
%typemap(out) CellPortIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) LibertyCellPortIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) Port* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(in) PortSeq* {
$1 = tclListSeqPtr($input, SWIGTYPE_p_Port, interp);
}
%typemap(out) PortSeq {
seqTclList($1, SWIGTYPE_p_Port, interp);
}
%typemap(out) PortMemberIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) LibertyCell* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) LibertyPort* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) LibertyPortMemberIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, SWIGTYPE_p_LibertyPortMemberIterator, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) TimingArc* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) TimingArcSetSeq& {
seqPtrTclList($1, SWIGTYPE_p_TimingArcSet, interp);
}
%typemap(out) TimingArcSeq& {
seqPtrTclList($1, SWIGTYPE_p_TimingArc, interp);
}
%typemap(out) Wireload* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) WireloadSelection* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(in) Transition* {
int length;
const char *arg = Tcl_GetStringFromObj($input, &length);
Transition *tr = Transition::find(arg);
if (tr == nullptr) {
Tcl_SetResult(interp,const_cast("Error: transition not found."),
TCL_STATIC);
return TCL_ERROR;
}
else
$1 = tr;
}
%typemap(out) Transition* {
Transition *tr = $1;
const char *str = "";
if (tr)
str = tr->asString();
Tcl_SetResult(interp, const_cast(str), TCL_STATIC);
}
%typemap(in) RiseFall* {
int length;
const char *arg = Tcl_GetStringFromObj($input, &length);
RiseFall *rf = RiseFall::find(arg);
if (rf == nullptr) {
Tcl_SetResult(interp,const_cast("Error: unknown rise/fall edge."),
TCL_STATIC);
return TCL_ERROR;
}
$1 = rf;
}
%typemap(out) RiseFall* {
const RiseFall *tr = $1;
const char *str = "";
if (tr)
str = tr->asString();
Tcl_SetResult(interp, const_cast(str), TCL_STATIC);
}
%typemap(in) RiseFallBoth* {
int length;
const char *arg = Tcl_GetStringFromObj($input, &length);
RiseFallBoth *tr = RiseFallBoth::find(arg);
if (tr == nullptr) {
Tcl_SetResult(interp,const_cast("Error: unknown transition name."),
TCL_STATIC);
return TCL_ERROR;
}
$1 = tr;
}
%typemap(out) RiseFallBoth* {
RiseFallBoth *tr = $1;
const char *str = "";
if (tr)
str = tr->asString();
Tcl_SetResult(interp, const_cast(str), TCL_STATIC);
}
%typemap(in) PortDirection* {
int length;
const char *arg = Tcl_GetStringFromObj($input, &length);
PortDirection *dir = PortDirection::find(arg);
if (dir == nullptr) {
Tcl_SetResult(interp,const_cast("Error: port direction not found."),
TCL_STATIC);
return TCL_ERROR;
}
else
$1 = dir;
}
%typemap(in) TimingRole* {
int length;
const char *arg = Tcl_GetStringFromObj($input, &length);
TimingRole *role = TimingRole::find(arg);
if (role)
$1 = TimingRole::find(arg);
else {
Tcl_SetResult(interp,const_cast("Error: unknown timing role."),
TCL_STATIC);
return TCL_ERROR;
}
}
%typemap(out) TimingRole* {
Tcl_SetResult(interp, const_cast($1->asString()), TCL_STATIC);
}
%typemap(in) LogicValue {
int length;
const char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEq(arg, "0") || stringEq(arg, "zero"))
$1 = LogicValue::zero;
else if (stringEq(arg, "1") || stringEq(arg, "one"))
$1 = LogicValue::one;
else if (stringEq(arg, "X"))
$1 = LogicValue::unknown;
else if (stringEq(arg, "rise") || stringEq(arg, "rising"))
$1 = LogicValue::rise;
else if (stringEq(arg, "fall") || stringEq(arg, "falling"))
$1 = LogicValue::fall;
else {
Tcl_SetResult(interp,const_cast("Error: unknown logic value."),
TCL_STATIC);
return TCL_ERROR;
}
}
%typemap(in) AnalysisType {
int length;
const char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEqual(arg, "single"))
$1 = AnalysisType::single;
else if (stringEqual(arg, "bc_wc"))
$1 = AnalysisType::bc_wc;
else if (stringEq(arg, "on_chip_variation"))
$1 = AnalysisType::ocv;
else {
Tcl_SetResult(interp,const_cast("Error: unknown analysis type."),
TCL_STATIC);
return TCL_ERROR;
}
}
%typemap(out) Instance* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(in) InstanceSeq* {
$1 = tclListSeqPtr($input, SWIGTYPE_p_Instance, interp);
}
%typemap(out) InstanceSeq {
seqTclList($1, SWIGTYPE_p_Instance, interp);
}
%typemap(out) InstanceChildIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) LeafInstanceIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) InstancePinIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) InstanceNetIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(in) LibertyLibrarySeq* {
$1 = tclListSeqPtr($input, SWIGTYPE_p_LibertyLibrary, interp);
}
%typemap(out) LibertyLibrarySeq {
seqTclList($1, SWIGTYPE_p_LibertyLibrary, interp);
}
%typemap(out) Pin* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) PinSeq* {
seqPtrTclList($1, SWIGTYPE_p_Pin, interp);
}
%typemap(out) PinSeq {
seqTclList($1, SWIGTYPE_p_Pin, interp);
}
%typemap(out) Net* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(in) NetSeq* {
$1 = tclListSeqPtr($input, SWIGTYPE_p_Net, interp);
}
%typemap(out) NetSeq* {
seqPtrTclList($1, SWIGTYPE_p_Net, interp);
}
%typemap(in) ConstNetSeq {
$1 = tclListSeq($input, SWIGTYPE_p_Net, interp);
}
%typemap(out) NetSeq {
seqTclList($1, SWIGTYPE_p_Net, interp);
}
%typemap(out) NetPinIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) NetTermIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) NetConnectedPinIterator* {
Tcl_Obj *obj=SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) PinConnectedPinIterator* {
Tcl_Obj *obj=SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) Clock* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(in) ConstClockSeq {
$1 = tclListSeq($input, SWIGTYPE_p_Clock, interp);
}
%typemap(in) ClockSeq* {
$1 = tclListSeqPtr($input, SWIGTYPE_p_Clock, interp);
}
%typemap(out) ClockSeq* {
seqPtrTclList($1, SWIGTYPE_p_Clock, interp);
}
%typemap(out) ClockSeq {
seqTclList($1, SWIGTYPE_p_Clock, interp);
}
%typemap(out) ClockEdge* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1,$1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(in) PinSeq* {
$1 = tclListSeqPtr($input, SWIGTYPE_p_Pin, interp);
}
%typemap(in) PinSet {
Network *network = Sta::sta()->ensureLinked();
$1 = tclListNetworkSet1($input, SWIGTYPE_p_Pin, interp, network);
}
%typemap(in) PinSet* {
Network *network = Sta::sta()->ensureLinked();
$1 = tclListNetworkSet($input, SWIGTYPE_p_Pin, interp, network);
}
%typemap(out) PinSet* {
setPtrTclList($1, SWIGTYPE_p_Pin, interp);
}
%typemap(out) PinSet {
setTclList($1, SWIGTYPE_p_Pin, interp);
}
%typemap(out) const PinSet& {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
// A swig bug sets the result to PinSet* rather than const PinSet&.
PinSet *pins = $1;
for (const Pin *pin : *pins) {
Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast(pin), SWIGTYPE_p_Pin, false);
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
}
%typemap(in) ConstClockSet {
$1 = tclListSet($input, SWIGTYPE_p_Clock, interp);
}
%typemap(in) ClockSet* {
$1 = tclListSetPtr($input, SWIGTYPE_p_Clock, interp);
}
%typemap(out) ClockSet* {
setPtrTclList($1, SWIGTYPE_p_Clock, interp);
}
%typemap(in) InstanceSet* {
Network *network = Sta::sta()->ensureLinked();
$1 = tclListNetworkSet($input, SWIGTYPE_p_Instance,
interp, network);
}
%typemap(out) InstanceSet {
setTclList($1, SWIGTYPE_p_Instance, interp);
}
%typemap(in) NetSet* {
Network *network = Sta::sta()->ensureLinked();
$1 = tclListNetworkSet($input, SWIGTYPE_p_Net, interp, network);
}
%typemap(in) FloatSeq* {
Tcl_Size argc;
Tcl_Obj **argv;
FloatSeq *floats = nullptr;
if (Tcl_ListObjGetElements(interp, $input, &argc, &argv) == TCL_OK) {
if (argc)
floats = new FloatSeq;
for (int i = 0; i < argc; i++) {
char *arg = Tcl_GetString(argv[i]);
double value;
if (Tcl_GetDouble(interp, arg, &value) == TCL_OK)
floats->push_back(static_cast(value));
else {
delete floats;
tclArgError(interp, "%s is not a floating point number.", arg);
return TCL_ERROR;
}
}
}
$1 = floats;
}
%typemap(out) FloatSeq* {
FloatSeq *floats = $1;
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
if (floats) {
for (float f : *floats) {
Tcl_Obj *obj = Tcl_NewDoubleObj(f);
Tcl_ListObjAppendElement(interp, list, obj);
}
}
Tcl_SetObjResult(interp, list);
}
%typemap(out) FloatSeq {
FloatSeq &floats = $1;
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (float f : floats) {
Tcl_Obj *obj = Tcl_NewDoubleObj(f);
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
}
%typemap(in) IntSeq* {
Tcl_Size argc;
Tcl_Obj **argv;
IntSeq *ints = nullptr;
if (Tcl_ListObjGetElements(interp, $input, &argc, &argv) == TCL_OK) {
if (argc)
ints = new IntSeq;
for (int i = 0; i < argc; i++) {
char *arg = Tcl_GetString(argv[i]);
int value;
if (Tcl_GetInt(interp, arg, &value) == TCL_OK)
ints->push_back(value);
else {
delete ints;
tclArgError(interp, "%s is not an integer.", arg);
return TCL_ERROR;
}
}
}
$1 = ints;
}
%typemap(out) Table1 {
Table1 &table = $1;
if (table.axis1()) {
Tcl_Obj *list3 = Tcl_NewListObj(0, nullptr);
Tcl_Obj *list1 = Tcl_NewListObj(0, nullptr);
for (float f : *table.axis1()->values()) {
Tcl_Obj *obj = Tcl_NewDoubleObj(f);
Tcl_ListObjAppendElement(interp, list1, obj);
}
Tcl_Obj *list2 = Tcl_NewListObj(0, nullptr);
for (float f : *table.values()) {
Tcl_Obj *obj = Tcl_NewDoubleObj(f);
Tcl_ListObjAppendElement(interp, list2, obj);
}
Tcl_ListObjAppendElement(interp, list3, list1);
Tcl_ListObjAppendElement(interp, list3, list2);
Tcl_SetObjResult(interp, list3);
}
}
%typemap(out) const Table1* {
const Table1 *table = $1;
Tcl_Obj *list3 = Tcl_NewListObj(0, nullptr);
if (table) {
Tcl_Obj *list1 = Tcl_NewListObj(0, nullptr);
for (float f : *table->axis1()->values()) {
Tcl_Obj *obj = Tcl_NewDoubleObj(f);
Tcl_ListObjAppendElement(interp, list1, obj);
}
Tcl_Obj *list2 = Tcl_NewListObj(0, nullptr);
for (float f : *table->values()) {
Tcl_Obj *obj = Tcl_NewDoubleObj(f);
Tcl_ListObjAppendElement(interp, list2, obj);
}
Tcl_ListObjAppendElement(interp, list3, list1);
Tcl_ListObjAppendElement(interp, list3, list2);
}
Tcl_SetObjResult(interp, list3);
}
%typemap(in) MinMax* {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
MinMax *min_max = MinMax::find(arg);
if (min_max)
$1 = min_max;
else {
tclArgError(interp, "%s not min or max.", arg);
return TCL_ERROR;
}
}
%typemap(out) MinMax* {
Tcl_SetResult(interp, const_cast($1->asString()), TCL_STATIC);
}
%typemap(out) MinMax* {
Tcl_SetResult(interp, const_cast($1->asString()), TCL_STATIC);
}
%typemap(in) MinMaxAll* {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
MinMaxAll *min_max = MinMaxAll::find(arg);
if (min_max)
$1 = min_max;
else {
tclArgError(interp, "%s not min, max or min_max.", arg);
return TCL_ERROR;
}
}
%typemap(in) MinMaxAllNull* {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEqual(arg, "NULL"))
$1 = nullptr;
else {
MinMaxAll *min_max = MinMaxAll::find(arg);
if (min_max)
$1 = min_max;
else {
tclArgError(interp, "%s not min, max or min_max.", arg);
return TCL_ERROR;
}
}
}
%typemap(out) MinMaxAll* {
Tcl_SetResult(interp, const_cast($1->asString()), TCL_STATIC);
}
// SetupHold is typedef'd to MinMax.
%typemap(in) SetupHold* {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEqual(arg, "hold")
|| stringEqual(arg, "min"))
$1 = MinMax::min();
else if (stringEqual(arg, "setup")
|| stringEqual(arg, "max"))
$1 = MinMax::max();
else {
tclArgError(interp, "%s not setup, hold, min or max.", arg);
return TCL_ERROR;
}
}
// SetupHoldAll is typedef'd to MinMaxAll.
%typemap(in) SetupHoldAll* {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEqual(arg, "hold")
|| stringEqual(arg, "min"))
$1 = SetupHoldAll::min();
else if (stringEqual(arg, "setup")
|| stringEqual(arg, "max"))
$1 = SetupHoldAll::max();
else if (stringEqual(arg, "setup_hold")
|| stringEqual(arg, "min_max"))
$1 = SetupHoldAll::all();
else {
tclArgError(interp, "%s not setup, hold, setup_hold, min, max or min_max.", arg);
return TCL_ERROR;
}
}
// EarlyLate is typedef'd to MinMax.
%typemap(in) EarlyLate* {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
EarlyLate *early_late = EarlyLate::find(arg);
if (early_late)
$1 = early_late;
else {
tclArgError(interp, "%s not early/min, late/max or early_late/min_max.", arg);
return TCL_ERROR;
}
}
// EarlyLateAll is typedef'd to MinMaxAll.
%typemap(in) EarlyLateAll* {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
EarlyLateAll *early_late = EarlyLateAll::find(arg);
if (early_late)
$1 = early_late;
else {
tclArgError(interp, "%s not early/min, late/max or early_late/min_max.", arg);
return TCL_ERROR;
}
}
%typemap(in) TimingDerateType {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEq(arg, "net_delay"))
$1 = TimingDerateType::net_delay;
else if (stringEq(arg, "cell_delay"))
$1 = TimingDerateType::cell_delay;
else if (stringEq(arg, "cell_check"))
$1 = TimingDerateType::cell_check;
else {
tclArgError(interp, "%s not net_delay, cell_delay or cell_check.", arg);
return TCL_ERROR;
}
}
%typemap(in) TimingDerateCellType {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEq(arg, "cell_delay"))
$1 = TimingDerateCellType::cell_delay;
else if (stringEq(arg, "cell_check"))
$1 = TimingDerateCellType::cell_check;
else {
tclArgError(interp, "%s not cell_delay or cell_check.", arg);
return TCL_ERROR;
}
}
%typemap(in) PathClkOrData {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEq(arg, "clk"))
$1 = PathClkOrData::clk;
else if (stringEq(arg, "data"))
$1 = PathClkOrData::data;
else {
tclArgError(interp, "%s not clk or data.", arg);
return TCL_ERROR;
}
}
%typemap(in) ReportSortBy {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEq(arg, "group"))
$1 = sort_by_group;
else if (stringEq(arg, "slack"))
$1 = sort_by_slack;
else {
tclArgError(interp, "%s not group or slack.", arg);
return TCL_ERROR;
}
}
%typemap(in) ReportPathFormat {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEq(arg, "full"))
$1 = ReportPathFormat::full;
else if (stringEq(arg, "full_clock"))
$1 = ReportPathFormat::full_clock;
else if (stringEq(arg, "full_clock_expanded"))
$1 = ReportPathFormat::full_clock_expanded;
else if (stringEq(arg, "short"))
$1 = ReportPathFormat::shorter;
else if (stringEq(arg, "end"))
$1 = ReportPathFormat::endpoint;
else if (stringEq(arg, "summary"))
$1 = ReportPathFormat::summary;
else if (stringEq(arg, "slack_only"))
$1 = ReportPathFormat::slack_only;
else if (stringEq(arg, "json"))
$1 = ReportPathFormat::json;
else {
tclArgError(interp, "unknown path type %s.", arg);
return TCL_ERROR;
}
}
%typemap(in) ExceptionThruSeq* {
$1 = tclListSeqPtr($input, SWIGTYPE_p_ExceptionThru, interp);
}
%typemap(out) Vertex* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) Vertex** {
int i = 0;
Tcl_ResetResult(interp);
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
while ($1[i]) {
Tcl_Obj *obj = SWIG_NewInstanceObj($1[i], SWIGTYPE_p_Vertex,false);
Tcl_ListObjAppendElement(interp, list, obj);
i++;
}
Tcl_SetObjResult(interp, list);
}
%typemap(out) Edge* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(in) EdgeSeq* {
$1 = tclListSeqPtr($input, SWIGTYPE_p_Edge, interp);
}
%typemap(out) EdgeSeq {
seqTclList($1, SWIGTYPE_p_Edge, interp);
}
%typemap(out) VertexIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) VertexInEdgeIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) VertexOutEdgeIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) CheckErrorSeq & {
Tcl_Obj *error_list = Tcl_NewListObj(0, nullptr);
CheckErrorSeq *check_errors = $1;
CheckErrorSeq::Iterator check_iter(check_errors);
while (check_iter.hasNext()) {
CheckError *error = check_iter.next();
Tcl_Obj *string_list = Tcl_NewListObj(0, nullptr);
CheckError::Iterator string_iter(error);
while (string_iter.hasNext()) {
const char *str = string_iter.next();
size_t str_len = strlen(str);
Tcl_Obj *obj = Tcl_NewStringObj(const_cast(str),
static_cast(str_len));
Tcl_ListObjAppendElement(interp, string_list, obj);
}
Tcl_ListObjAppendElement(interp, error_list, string_list);
}
Tcl_SetObjResult(interp, error_list);
}
%typemap(out) PathEnd* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) PathEndSeq* {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
const PathEndSeq *path_ends = $1;
PathEndSeq::ConstIterator end_iter(path_ends);
while (end_iter.hasNext()) {
PathEnd *path_end = end_iter.next();
Tcl_Obj *obj = SWIG_NewInstanceObj(path_end, SWIGTYPE_p_PathEnd, false);
Tcl_ListObjAppendElement(interp, list, obj);
}
// Delete the PathEndSeq, not the ends.
delete path_ends;
Tcl_SetObjResult(interp, list);
}
%typemap(out) PathEndSeq {
seqTclList($1, SWIGTYPE_p_PathEnd, interp);
}
%typemap(out) MinPulseWidthCheckSeqIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) PathRefSeq* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
PathRefSeq *paths = $1;
PathRefSeq::Iterator path_iter(paths);
while (path_iter.hasNext()) {
PathRef *path = &path_iter.next();
PathRef *copy = new PathRef(path);
Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_PathRef, false);
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
}
%typemap(out) MinPulseWidthCheck* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) MinPulseWidthCheckSeq & {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) MinPulseWidthCheckSeqIterator & {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) VertexPathIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) SlowDrvrIterator* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) ExceptionFrom* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) ExceptionTo* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) ExceptionThru* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) OperatingConditions* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) Delay {
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
}
%typemap(out) Arrival {
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
}
%typemap(out) Required {
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
}
%typemap(out) Slack {
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
}
%typemap(out) ArcDelay {
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
}
%typemap(out) Slew {
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
}
%typemap(out) Crpr {
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
}
%typemap(in) PathGroupNameSet* {
$1 = tclListSetConstChar($input, interp);
}
%typemap(in) StringSet* {
$1 = tclListSetConstChar($input, interp);
}
%typemap(out) Corner* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
}
%typemap(out) Corners* {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
Corners *corners = $1;
for (Corner *corner : *corners) {
Tcl_Obj *obj = SWIG_NewInstanceObj(corner, SWIGTYPE_p_Corner, false);
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
}
%typemap(out) PropertyValue {
PropertyValue value = $1;
switch (value.type()) {
case PropertyValue::Type::type_none:
Tcl_SetResult(interp, const_cast(""), TCL_STATIC);
break;
case PropertyValue::Type::type_string:
Tcl_SetResult(interp, const_cast(value.stringValue()), TCL_VOLATILE);
break;
case PropertyValue::Type::type_float: {
const Unit *unit = value.unit();
const char *float_string = unit->asString(value.floatValue(), 6);
Tcl_SetResult(interp, const_cast(float_string), TCL_VOLATILE);
}
break;
case PropertyValue::Type::type_bool: {
const char *bool_string = value.boolValue() ? "1" : "0";
Tcl_SetResult(interp, const_cast(bool_string), TCL_STATIC);
}
break;
case PropertyValue::Type::type_library: {
Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast(value.library()),
SWIGTYPE_p_Library, false);
Tcl_SetObjResult(interp, obj);
}
break;
case PropertyValue::Type::type_cell: {
Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast| (value.cell()),
SWIGTYPE_p_Cell, false);
Tcl_SetObjResult(interp, obj);
}
break;
case PropertyValue::Type::type_port: {
Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast(value.port()),
SWIGTYPE_p_Port, false);
Tcl_SetObjResult(interp, obj);
}
break;
case PropertyValue::Type::type_liberty_library: {
Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast(value.libertyLibrary()),
SWIGTYPE_p_LibertyLibrary, false);
Tcl_SetObjResult(interp, obj);
}
break;
case PropertyValue::Type::type_liberty_cell: {
Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast(value.libertyCell()),
SWIGTYPE_p_LibertyCell, false);
Tcl_SetObjResult(interp, obj);
}
break;
case PropertyValue::Type::type_liberty_port: {
Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast(value.libertyPort()),
SWIGTYPE_p_LibertyPort, false);
Tcl_SetObjResult(interp, obj);
}
break;
case PropertyValue::Type::type_instance: {
Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast(value.instance()),
SWIGTYPE_p_Instance, false);
Tcl_SetObjResult(interp, obj);
}
break;
case PropertyValue::Type::type_pin: {
Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast(value.pin()),
SWIGTYPE_p_Pin, false);
Tcl_SetObjResult(interp, obj);
}
break;
case PropertyValue::Type::type_pins: {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
PinSeq *pins = value.pins();
PinSeq::Iterator pin_iter(pins);
while (pin_iter.hasNext()) {
const Pin *pin = pin_iter.next();
Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast(pin), SWIGTYPE_p_Pin, false);
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
}
break;
case PropertyValue::Type::type_net: {
Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast(value.net()),
SWIGTYPE_p_Net, false);
Tcl_SetObjResult(interp, obj);
}
break;
case PropertyValue::Type::type_clk: {
Tcl_Obj *obj = SWIG_NewInstanceObj(const_cast(value.clock()),
SWIGTYPE_p_Clock, false);
Tcl_SetObjResult(interp, obj);
}
break;
case PropertyValue::Type::type_clks: {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
ClockSeq *clks = value.clocks();
ClockSeq::Iterator clk_iter(clks);
while (clk_iter.hasNext()) {
Clock *clk = clk_iter.next();
Tcl_Obj *obj = SWIG_NewInstanceObj(clk, SWIGTYPE_p_Clock, false);
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
}
break;
case PropertyValue::Type::type_path_refs: {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (PathRef &path : *value.pathRefs()) {
PathRef *copy = new PathRef(path);
Tcl_Obj *obj = SWIG_NewInstanceObj(copy, SWIGTYPE_p_PathRef, false);
Tcl_ListObjAppendElement(interp, list, obj);
}
Tcl_SetObjResult(interp, list);
}
break;
case PropertyValue::Type::type_pwr_activity: {
PwrActivity activity = value.pwrActivity();
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
Tcl_Obj *obj;
const char *str;
str = stringPrintTmp("%.5e", activity.activity());
obj = Tcl_NewStringObj(str, strlen(str));
Tcl_ListObjAppendElement(interp, list, obj);
str = stringPrintTmp("%.3f", activity.duty());
obj = Tcl_NewStringObj(str, strlen(str));
Tcl_ListObjAppendElement(interp, list, obj);
str = activity.originName();
obj = Tcl_NewStringObj(str, strlen(str));
Tcl_ListObjAppendElement(interp, list, obj);
Tcl_SetObjResult(interp, list);
}
break;
}
}
%typemap(in) CircuitSim {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEq(arg, "hspice"))
$1 = CircuitSim::hspice;
else if (stringEq(arg, "ngspice"))
$1 = CircuitSim::ngspice;
else if (stringEq(arg, "xyce"))
$1 = CircuitSim::xyce;
else {
tclArgError(interp, "unknown circuit simulator %s.", arg);
return TCL_ERROR;
}
}
%typemap(in) ArcDcalcArg {
Tcl_Obj *const source = $input;
$1 = arcDcalcArgTcl(source, interp);
}
%typemap(out) ArcDcalcArg {
Tcl_Obj *tcl_obj = tclArcDcalcArg($1, interp);
Tcl_SetObjResult(interp, tcl_obj);
}
%typemap(in) ArcDcalcArgSeq {
Tcl_Obj *const source = $input;
Tcl_Size argc;
Tcl_Obj **argv;
Sta *sta = Sta::sta();
ArcDcalcArgSeq seq;
if (Tcl_ListObjGetElements(interp, source, &argc, &argv) == TCL_OK
&& argc > 0) {
for (int i = 0; i < argc; i++) {
ArcDcalcArg gate = arcDcalcArgTcl(argv[i], interp);
if (gate.drvrPin())
seq.push_back(gate);
}
}
$1 = seq;
}
%typemap(out) ArcDcalcArgSeq {
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
for (ArcDcalcArg &gate : $1) {
Tcl_Obj *tcl_obj = tclArcDcalcArg(gate, interp);
Tcl_ListObjAppendElement(interp, list, tcl_obj);
}
Tcl_SetObjResult(interp, list);
}
| |