diff --git a/include/sta/WritePathSpice.hh b/include/sta/WritePathSpice.hh index 6ab489e5..a54c9c95 100644 --- a/include/sta/WritePathSpice.hh +++ b/include/sta/WritePathSpice.hh @@ -16,8 +16,16 @@ #pragma once +#include +#include + namespace sta { +using std::string; +using std::set; + +typedef set StdStringSet; + class Path; class StaState; @@ -33,7 +41,9 @@ writePathSpice(Path *path, const char *lib_subckt_filename, // Device model file included in spice file. const char *model_filename, - const char *power_name, + // Nets off of path to include in the spice run. + StdStringSet *off_path_pin_names, + const char *power_name, const char *gnd_name, StaState *sta); diff --git a/search/WritePathSpice.cc b/search/WritePathSpice.cc index 99ec69df..ee68a312 100644 --- a/search/WritePathSpice.cc +++ b/search/WritePathSpice.cc @@ -45,11 +45,9 @@ namespace sta { -using std::string; using std::ofstream; using std::ifstream; using std::max; -using std::set; typedef Map CellSpicePortNames; typedef int Stage; @@ -71,6 +69,7 @@ public: const char *subckt_filename, const char *lib_subckt_filename, const char *model_filename, + StdStringSet *off_path_pin_names, const char *power_name, const char *gnd_name, const StaState *sta); @@ -100,8 +99,8 @@ private: DcalcAPIndex dcalc_ap_index); void writeStageParasitics(Stage stage); void writeSubckts(); - set findPathCellnames(); - void findPathCellSubckts(set &path_cell_names); + StdStringSet findPathCellnames(); + void findPathCellSubckts(StdStringSet &path_cell_names); void recordSpicePortNames(const char *cell_name, StringVector &tokens); float maxTime(); @@ -209,12 +208,14 @@ private: const char *stageLoadPinName(Stage stage); LibertyCell *stageLibertyCell(Stage stage); Instance *stageInstance(Stage stage); + StdStringSet stageOffPathPinNames(Stage stage); Path *path_; const char *spice_filename_; const char *subckt_filename_; const char *lib_subckt_filename_; const char *model_filename_; + StdStringSet *off_path_pin_names_; const char *power_name_; const char *gnd_name_; @@ -270,13 +271,14 @@ writePathSpice(Path *path, const char *subckt_filename, const char *lib_subckt_filename, const char *model_filename, - const char *power_name, + StdStringSet *off_path_pin_names, + const char *power_name, const char *gnd_name, StaState *sta) { WritePathSpice writer(path, spice_filename, subckt_filename, lib_subckt_filename, model_filename, - power_name, gnd_name, sta); + off_path_pin_names, power_name, gnd_name, sta); writer.writeSpice(); } @@ -285,6 +287,7 @@ WritePathSpice::WritePathSpice(Path *path, const char *subckt_filename, const char *lib_subckt_filename, const char *model_filename, + StdStringSet *off_path_pin_names, const char *power_name, const char *gnd_name, const StaState *sta) : @@ -294,6 +297,7 @@ WritePathSpice::WritePathSpice(Path *path, subckt_filename_(subckt_filename), lib_subckt_filename_(lib_subckt_filename), model_filename_(model_filename), + off_path_pin_names_(off_path_pin_names), power_name_(power_name), gnd_name_(gnd_name), path_expanded_(sta), @@ -388,6 +392,9 @@ WritePathSpice::writePrintStmt() for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { streamPrint(spice_stream_, " v(%s)", stageDrvrPinName(stage)); streamPrint(spice_stream_, " v(%s)", stageLoadPinName(stage)); + StdStringSet off_path_names = stageOffPathPinNames(stage); + for (const string &off_path_name : off_path_names) + streamPrint(spice_stream_, " v(%s)", off_path_name.c_str()); } streamPrint(spice_stream_, "\n\n"); } @@ -441,13 +448,17 @@ WritePathSpice::writeStageInstances() stageDrvrPinName(stage), stageLoadPinName(stage), stage_cname); - else - streamPrint(spice_stream_, "x%s %s %s %s %s\n", + else { + streamPrint(spice_stream_, "x%s %s %s %s", stage_cname, stageGateInputPinName(stage), stageDrvrPinName(stage), - stageLoadPinName(stage), - stage_cname); + stageLoadPinName(stage)); + StdStringSet off_path_names = stageOffPathPinNames(stage); + for (const string &off_path_name : off_path_names) + streamPrint(spice_stream_, " %s", off_path_name.c_str()); + streamPrint(spice_stream_, " %s\n", stage_cname); + } } streamPrint(spice_stream_, "\n"); } @@ -855,11 +866,16 @@ WritePathSpice::writeGateStage(Stage stage) const char *drvr_pin_name = stageDrvrPinName(stage); const Pin *load_pin = stageLoadPin(stage); const char *load_pin_name = stageLoadPinName(stage); - streamPrint(spice_stream_, ".subckt stage%d %s %s %s\n", + streamPrint(spice_stream_, ".subckt stage%d %s %s %s", stage, input_pin_name, drvr_pin_name, load_pin_name); + StdStringSet off_path_names = stageOffPathPinNames(stage); + for (const string &off_path_name : off_path_names) + streamPrint(spice_stream_, " %s", off_path_name.c_str()); + streamPrint(spice_stream_, "\n"); + // Driver subckt call. Instance *inst = stageInstance(stage); LibertyPort *input_port = stageGateInputPort(stage); @@ -1433,7 +1449,7 @@ WritePathSpice::nodeName(ParasiticNode *node) void WritePathSpice::writeSubckts() { - set path_cell_names = findPathCellnames(); + StdStringSet path_cell_names = findPathCellnames(); findPathCellSubckts(path_cell_names); ifstream lib_subckts_stream(lib_subckt_filename_); @@ -1489,10 +1505,10 @@ WritePathSpice::writeSubckts() throw FileNotReadable(lib_subckt_filename_); } -set +StdStringSet WritePathSpice::findPathCellnames() { - set path_cell_names; + StdStringSet path_cell_names; for (Stage stage = stageFirst(); stage <= stageLast(); stage++) { TimingArc *arc = stageGateArc(stage); if (arc) { @@ -1520,7 +1536,7 @@ WritePathSpice::findPathCellnames() // Subckts can call subckts (asap7). void -WritePathSpice::findPathCellSubckts(set &path_cell_names) +WritePathSpice::findPathCellSubckts(StdStringSet &path_cell_names) { ifstream lib_subckts_stream(lib_subckt_filename_); if (lib_subckts_stream.is_open()) { @@ -1731,6 +1747,26 @@ WritePathSpice::stageLoadPinName(Stage stage) return network_->pathName(pin); } +StdStringSet +WritePathSpice::stageOffPathPinNames(Stage stage) +{ + StdStringSet pin_names; + if (off_path_pin_names_) { + const PathRef *path = stageDrvrPath(stage); + Vertex *drvr = path->vertex(this); + VertexOutEdgeIterator edge_iter(drvr, graph_); + while (edge_iter.hasNext()) { + Edge *edge = edge_iter.next(); + Vertex *load = edge->to(graph_); + const Pin *load_pin = load->pin(); + string load_pin_name = network_->pathName(load_pin); + if (off_path_pin_names_->find(load_pin_name) != off_path_pin_names_->end()) + pin_names.insert(load_pin_name); + } + } + return pin_names; +} + Instance * WritePathSpice::stageInstance(Stage stage) { diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index 86ec7975..08946e4b 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -254,6 +254,26 @@ tclListSeqConstChar(Tcl_Obj *const source, return nullptr; } +StdStringSet * +tclListSetStdString(Tcl_Obj *const source, + Tcl_Interp *interp) +{ + int 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. @@ -425,6 +445,10 @@ using namespace sta; $1 = tclListSeqConstChar($input, interp); } +%typemap(in) StdStringSet* { + $1 = tclListSetStdString($input, interp); +} + %typemap(out) StringSeq* { StringSeq *strs = $1; Tcl_Obj *list = Tcl_NewListObj(0, nullptr); @@ -4865,12 +4889,13 @@ write_path_spice_cmd(PathRef *path, const char *subckt_filename, const char *lib_subckt_filename, const char *model_filename, + StdStringSet *off_path_pins, const char *power_name, const char *gnd_name) { Sta *sta = Sta::sta(); writePathSpice(path, spice_filename, subckt_filename, - lib_subckt_filename, model_filename, + lib_subckt_filename, model_filename, off_path_pins, power_name, gnd_name, sta); } diff --git a/tcl/WritePathSpice.tcl b/tcl/WritePathSpice.tcl index a8cf9c5a..0ba7da65 100644 --- a/tcl/WritePathSpice.tcl +++ b/tcl/WritePathSpice.tcl @@ -89,7 +89,7 @@ proc write_path_spice { args } { set spice_file [file join $spice_dir "$path_name.sp"] set subckt_file [file join $spice_dir "$path_name.subckt"] write_path_spice_cmd $path $spice_file $subckt_file \ - $lib_subckt_file $model_file $power $ground + $lib_subckt_file $model_file {} $power $ground incr path_index } }