write_path_spice handle subckt calls in library subckts

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2023-03-21 21:03:08 -07:00
parent 054b5045d3
commit 458a7cf0d1
1 changed files with 75 additions and 16 deletions

View File

@ -48,6 +48,8 @@ namespace sta {
using std::string;
using std::ofstream;
using std::ifstream;
using std::max;
using std::set;
typedef Map<string, StringVector*> CellSpicePortNames;
typedef int Stage;
@ -98,8 +100,8 @@ private:
DcalcAPIndex dcalc_ap_index);
void writeStageParasitics(Stage stage);
void writeSubckts();
void findPathCellnames(// Return values.
StringSet &path_cell_names);
set<string> findPathCellnames();
void findPathCellSubckts(set<string> &path_cell_names);
void recordSpicePortNames(const char *cell_name,
StringVector &tokens);
float maxTime();
@ -332,6 +334,18 @@ WritePathSpice::writeSpice()
throw FileNotWritable(spice_filename_);
}
// Use c++17 fs::path(filename).stem()
static string
filenameStem(const char *filename)
{
string filename1 = filename;
const size_t last_slash_idx = filename1.find_last_of("\\/");
if (last_slash_idx != std::string::npos)
return filename1.substr(last_slash_idx + 1);
else
return filename1;
}
void
WritePathSpice::writeHeader()
{
@ -348,7 +362,8 @@ WritePathSpice::writeHeader()
float temp = pvt->temperature();
streamPrint(spice_stream_, ".temp %.1f\n", temp);
streamPrint(spice_stream_, ".include \"%s\"\n", model_filename_);
streamPrint(spice_stream_, ".include \"%s\"\n", subckt_filename_);
string subckt_filename_stem = filenameStem(subckt_filename_);
streamPrint(spice_stream_, ".include \"%s\"\n", subckt_filename_stem.c_str());
float max_time = maxTime();
float time_step = max_time / 1e+3;
@ -373,9 +388,8 @@ WritePathSpice::maxTime()
}
else {
float end_slew = findSlew(path_);
float max_time = delayAsFloat(input_slew
+ path_->arrival(this)
+ end_slew * 2) * 1.5;
float arrival = delayAsFloat(path_->arrival(this));
float max_time = input_slew / 2.0 + arrival + end_slew;
return max_time;
}
}
@ -1342,8 +1356,8 @@ WritePathSpice::nodeName(ParasiticNode *node)
void
WritePathSpice::writeSubckts()
{
StringSet path_cell_names;
findPathCellnames(path_cell_names);
set<string> path_cell_names = findPathCellnames();
findPathCellSubckts(path_cell_names);
ifstream lib_subckts_stream(lib_subckt_filename_);
if (lib_subckts_stream.is_open()) {
@ -1357,7 +1371,7 @@ WritePathSpice::writeSubckts()
if (tokens.size() >= 2
&& stringEqual(tokens[0].c_str(), ".subckt")) {
const char *cell_name = tokens[1].c_str();
if (path_cell_names.hasKey(cell_name)) {
if (path_cell_names.find(cell_name) != path_cell_names.end()) {
subckts_stream << line << "\n";
bool found_ends = false;
while (getline(lib_subckts_stream, line)) {
@ -1379,10 +1393,14 @@ WritePathSpice::writeSubckts()
lib_subckts_stream.close();
if (!path_cell_names.empty()) {
report_->error(28, "The following subkcts are missing from %s",
lib_subckt_filename_);
for (const char *cell_name : path_cell_names)
report_->reportLine(" %s", cell_name);
string missing_cells;
for (const string &cell_name : path_cell_names) {
missing_cells += "\n";
missing_cells += cell_name;
}
report_->error(28, "The subkct file %s is missing definitions for %s",
lib_subckt_filename_,
missing_cells.c_str());
}
}
else {
@ -1394,10 +1412,10 @@ WritePathSpice::writeSubckts()
throw FileNotReadable(lib_subckt_filename_);
}
void
WritePathSpice::findPathCellnames(// Return values.
StringSet &path_cell_names)
set<string>
WritePathSpice::findPathCellnames()
{
set<string> path_cell_names;
for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
TimingArc *arc = stageGateArc(stage);
if (arc) {
@ -1420,6 +1438,47 @@ WritePathSpice::findPathCellnames(// Return values.
delete pin_iter;
}
}
return path_cell_names;
}
// Subckts can call subckts (asap7).
void
WritePathSpice::findPathCellSubckts(set<string> &path_cell_names)
{
ifstream lib_subckts_stream(lib_subckt_filename_);
if (lib_subckts_stream.is_open()) {
string line;
while (getline(lib_subckts_stream, line)) {
// .subckt <cell_name> [args..]
StringVector tokens;
split(line, " \t", tokens);
if (tokens.size() >= 2
&& stringEqual(tokens[0].c_str(), ".subckt")) {
const char *cell_name = tokens[1].c_str();
if (path_cell_names.find(cell_name) != path_cell_names.end()) {
// Scan the subckt definition for subckt calls.
string stmt;
while (getline(lib_subckts_stream, line)) {
if (line[0] == '+')
stmt += line.substr(1);
else {
// Process previous statement.
if (tolower(stmt[0]) == 'x') {
split(stmt, " \t", tokens);
string &subckt_cell = tokens[tokens.size() - 1];
path_cell_names.insert(subckt_cell);
}
stmt = line;
}
if (stringBeginEqual(line.c_str(), ".ends"))
break;
}
}
}
}
}
else
throw FileNotReadable(lib_subckt_filename_);
}
void