1 // OpenSTA, Static Timing Analyzer
2 // Copyright (c) 2021, Parallax Software, Inc.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
16 
17 #include <string>
18 #include <iostream>
19 #include <fstream>
20 #include <regex>
21 #include "Machine.hh"
22 #include "Debug.hh"
23 #include "Error.hh"
24 #include "Report.hh"
25 #include "StringUtil.hh"
26 #include "FuncExpr.hh"
27 #include "Liberty.hh"
28 #include "TimingArc.hh"
29 #include "Network.hh"
30 #include "Graph.hh"
31 #include "Sdc.hh"
32 #include "DcalcAnalysisPt.hh"
33 #include "Parasitics.hh"
34 #include "PathAnalysisPt.hh"
35 #include "Path.hh"
36 #include "PathRef.hh"
37 #include "PathExpanded.hh"
38 #include "StaState.hh"
39 #include "WriteSpice.hh"
40 
41 namespace sta {
42 
43 using std::string;
44 using std::ofstream;
45 using std::ifstream;
46 
47 typedef Vector<string> StringVector;
48 typedef Map<string, StringVector*> CellSpicePortNames;
49 typedef int Stage;
50 typedef Map<ParasiticNode*, int> ParasiticNodeMap;
51 
52 void
53 split(const string &text,
54       const string &delims,
55       // Return values.
56       StringVector &tokens);
57 void
58 streamPrint(ofstream &stream,
59 	    const char *fmt,
60 	    ...) __attribute__((format (printf, 2, 3)));
61 
62 ////////////////////////////////////////////////////////////////
63 
64 class WriteSpice : public StaState
65 {
66 public:
67   WriteSpice(Path *path,
68 	     const char *spice_filename,
69 	     const char *subckts_filename,
70 	     const char *lib_subckts_filename,
71 	     const char *models_filename,
72 	     const StaState *sta);
73   ~WriteSpice();
74   void writeSpice();;
75 
76 private:
77   void writeHeader();
78   void writeStageInstances();
79   void writeInputSource();
80   void writeStageSubckts();
81   void writeInputStage(Stage stage);
82   void writeMeasureStmts();
83   void writeGateStage(Stage stage);
84   void writeStageVoltageSources(LibertyCell *cell,
85 				StringVector *spice_port_names,
86 				const char *inst_name,
87 				LibertyPort *from_port,
88 				LibertyPort *drvr_port);
89   void writeStageParasitics(Stage stage);
90   void writeSubckts();
91   void findPathCellnames(// Return values.
92 			 StringSet &path_cell_names);
93   void recordSpicePortNames(const char *cell_name,
94 			    StringVector &tokens);
95   float pgPortVoltage(const char *pg_port_name,
96 		      LibertyCell *cell);
97   float pgPortVoltage(LibertyPgPort *pg_port);
98   float maxTime();
99   const char *nodeName(ParasiticNode *node);
100   void initNodeMap(const char *net_name);
101 
102   // Stage "accessors".
103   // Internally a stage index from stageFirst() to stageLast()
104   // is turned into an index into path_expanded_.
105   Stage stageFirst();
106   Stage stageLast();
107   string stageName(Stage stage);
108   int stageGateInputPathIndex(Stage stage);
109   int stageDrvrPathIndex(Stage stage);
110   int stageLoadPathIndex(Stage stage);
111   PathRef *stageGateInputPath(Stage stage);
112   PathRef *stageDrvrPath(Stage stage);
113   PathRef *stageLoadPath(Stage stage);
114   TimingArc *stageGateArc(Stage stage);
115   TimingArc *stageWireArc(Stage stage);
116   Edge *stageGateEdge(Stage stage);
117   Edge *stageWireEdge(Stage stage);
118   Pin *stageInputPin(Stage stage);
119   Pin *stageDrvrPin(Stage stage);
120   Pin *stageLoadPin(Stage stage);
121   const char *stageInputPinName(Stage stage);
122   const char *stageDrvrPinName(Stage stage);
123   const char *stageLoadPinName(Stage stage);
124 
125   Path *path_;
126   const char *spice_filename_;
127   const char *subckts_filename_;
128   const char *lib_subckts_filename_;
129   const char *models_filename_;
130 
131   ofstream spice_stream_;
132   PathExpanded path_expanded_;
133   CellSpicePortNames cell_spice_port_names_;
134   ParasiticNodeMap node_map_;
135   int next_node_index_;
136   const char *net_name_;
137 
138   // Resistance to use to simulate a short circuit between spice nodes.
139   static const float short_ckt_resistance_;
140 };
141 
142 ////////////////////////////////////////////////////////////////
143 
144 class SubcktEndsMissing : public StaException
145 {
146 public:
147   SubcktEndsMissing(const char *cell_name,
148 		    const char *subckt_filename);;
149   const char *what() const throw();
150 
151 protected:
152   string what_;
153 };
154 
SubcktEndsMissing(const char * cell_name,const char * subckt_filename)155 SubcktEndsMissing::SubcktEndsMissing(const char *cell_name,
156 				     const char *subckt_filename)
157 {
158   what_ = "Error: spice subckt for cell ";
159   what_ += cell_name;
160   what_ += " missing .ends in ";
161   what_ += subckt_filename;
162 }
163 
164 const char *
what() const165 SubcktEndsMissing::what() const throw()
166 {
167   return what_.c_str();
168 }
169 
170 ////////////////////////////////////////////////////////////////
171 
172 void
writeSpice(Path * path,const char * spice_filename,const char * subckts_filename,const char * lib_subckts_filename,const char * models_filename,StaState * sta)173 writeSpice (Path *path,
174 	    const char *spice_filename,
175 	    const char *subckts_filename,
176 	    const char *lib_subckts_filename,
177 	    const char *models_filename,
178 	    StaState *sta)
179 {
180   WriteSpice writer(path, spice_filename, subckts_filename,
181 		    lib_subckts_filename, models_filename, sta);
182   writer.writeSpice();
183 }
184 
185 const float WriteSpice::short_ckt_resistance_ = .0001;
186 
WriteSpice(Path * path,const char * spice_filename,const char * subckts_filename,const char * lib_subckts_filename,const char * models_filename,const StaState * sta)187 WriteSpice::WriteSpice(Path *path,
188 		       const char *spice_filename,
189 		       const char *subckts_filename,
190 		       const char *lib_subckts_filename,
191 		       const char *models_filename,
192 		       const StaState *sta) :
193   StaState(sta),
194   path_(path),
195   spice_filename_(spice_filename),
196   subckts_filename_(subckts_filename),
197   lib_subckts_filename_(lib_subckts_filename),
198   models_filename_(models_filename),
199   path_expanded_(sta),
200   net_name_(NULL)
201 {
202 }
203 
~WriteSpice()204 WriteSpice::~WriteSpice()
205 {
206   cell_spice_port_names_.deleteContents();
207 }
208 
209 void
writeSpice()210 WriteSpice::writeSpice()
211 {
212   spice_stream_.open(spice_filename_);
213   if (spice_stream_.is_open()) {
214     path_expanded_.expand(path_, true);
215     // Find subckt port names as a side-effect of writeSubckts.
216     writeSubckts();
217     writeHeader();
218     writeStageInstances();
219     writeInputSource();
220     writeStageSubckts();
221     streamPrint(spice_stream_, ".end\n");
222     spice_stream_.close();
223   }
224   else
225     throw FileNotWritable(spice_filename_);
226 }
227 
228 void
writeHeader()229 WriteSpice::writeHeader()
230 {
231   const MinMax *min_max = path_->minMax(this);
232   const Pvt *pvt = sdc_->operatingConditions(min_max);
233   if (pvt == NULL)
234     pvt = network_->defaultLibertyLibrary()->defaultOperatingConditions();
235   float temp = pvt->temperature();
236   streamPrint(spice_stream_, ".temp %.1f\n", temp);
237   streamPrint(spice_stream_, ".include \"%s\"\n", models_filename_);
238   streamPrint(spice_stream_, ".include \"%s\"\n", subckts_filename_);
239 
240   float max_time = maxTime();
241   float time_step = max_time / 1e+3;
242   streamPrint(spice_stream_, ".tran %.3g %.3g\n\n",
243 	      time_step, max_time);
244 }
245 
246 float
maxTime()247 WriteSpice::maxTime()
248 {
249   float end_slew = path_->slew(this);
250   float max_time = (path_->arrival(this) + end_slew * 2) * 1.5;
251   return max_time;
252 }
253 
254 void
writeStageInstances()255 WriteSpice::writeStageInstances()
256 {
257   streamPrint(spice_stream_, "*****************\n");
258   streamPrint(spice_stream_, "* Stage instances\n");
259   streamPrint(spice_stream_, "*****************\n\n");
260 
261   for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
262     const char *stage_name = stageName(stage).c_str();
263     if (stage == stageFirst())
264       streamPrint(spice_stream_, "x%s %s %s %s\n",
265 		  stage_name,
266 		  stageDrvrPinName(stage),
267 		  stageLoadPinName(stage),
268 		  stage_name);
269     else
270       streamPrint(spice_stream_, "x%s %s %s %s %s\n",
271 		  stage_name,
272 		  stageInputPinName(stage),
273 		  stageDrvrPinName(stage),
274 		  stageLoadPinName(stage),
275 		  stage_name);
276   }
277   streamPrint(spice_stream_, "\n");
278 }
279 
280 float
pgPortVoltage(const char * pg_port_name,LibertyCell * cell)281 WriteSpice::pgPortVoltage(const char *pg_port_name,
282 			  LibertyCell *cell)
283 {
284   auto pg_port = cell->findPgPort(pg_port_name);
285   return pgPortVoltage(pg_port);
286 }
287 
288 float
pgPortVoltage(LibertyPgPort * pg_port)289 WriteSpice::pgPortVoltage(LibertyPgPort *pg_port)
290 {
291   auto cell = pg_port->cell();
292   auto voltage_name = pg_port->voltageName();
293   auto lib = cell->libertyLibrary();
294   float voltage = lib->supplyVoltage(voltage_name);
295   return voltage;
296 }
297 
298 void
writeInputSource()299 WriteSpice::writeInputSource()
300 {
301   streamPrint(spice_stream_, "**************\n");
302   streamPrint(spice_stream_, "* Input source\n");
303   streamPrint(spice_stream_, "**************\n\n");
304 
305   Stage input_stage = stageFirst();
306   streamPrint(spice_stream_, "v1 %s 0 pwl(\n",
307 	      stageDrvrPinName(input_stage));
308   auto wire_arc = stageWireArc(input_stage);
309   auto load_pin = stageLoadPin(input_stage);
310   auto cell = network_->libertyCell(network_->instance(load_pin));
311   auto load_port = network_->libertyPort(load_pin);
312   const char *pg_gnd_port_name = load_port->relatedGroundPin();
313   const char *pg_pwr_port_name = load_port->relatedPowerPin();
314   auto gnd_volt = pgPortVoltage(pg_gnd_port_name, cell);
315   auto pwr_volt = pgPortVoltage(pg_pwr_port_name, cell);
316   float volt0, volt1;
317   if (wire_arc->fromTrans()->asRiseFall() == TransRiseFall::rise()) {
318     volt0 = gnd_volt;
319     volt1 = pwr_volt;
320   }
321   else {
322     volt0 = pwr_volt;
323     volt1 = gnd_volt;
324   }
325   float time0 = .1e-9;
326   float time1 = .2e-9;
327   streamPrint(spice_stream_, "+%.3e %.3e\n", 0.0, volt0);
328   streamPrint(spice_stream_, "+%.3e %.3e\n", time0, volt0);
329   streamPrint(spice_stream_, "+%.3e %.3e\n", time1, volt1);
330   streamPrint(spice_stream_, "+%.3e %.3e\n", maxTime(), volt1);
331   streamPrint(spice_stream_, "+)\n\n");
332 }
333 
334 void
writeMeasureStmts()335 WriteSpice::writeMeasureStmts()
336 {
337   streamPrint(spice_stream_, "********************\n");
338   streamPrint(spice_stream_, "* Measure statements\n");
339   streamPrint(spice_stream_, "********************\n\n");
340 }
341 
342 void
writeStageSubckts()343 WriteSpice::writeStageSubckts()
344 {
345   streamPrint(spice_stream_, "***************\n");
346   streamPrint(spice_stream_, "* Stage subckts\n");
347   streamPrint(spice_stream_, "***************\n\n");
348 
349   for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
350     if (stage == stageFirst())
351       writeInputStage(stage);
352     else
353       writeGateStage(stage);
354   }
355 }
356 
357 // Input port to first gate input.
358 void
writeInputStage(Stage stage)359 WriteSpice::writeInputStage(Stage stage)
360 {
361   // Input arc.
362   // External driver not handled.
363   auto drvr_pin_name = stageDrvrPinName(stage);
364   auto load_pin_name = stageLoadPinName(stage);
365   streamPrint(spice_stream_, ".subckt %s %s %s\n",
366 	      stageName(stage).c_str(),
367 	      drvr_pin_name,
368 	      load_pin_name);
369   writeStageParasitics(stage);
370   streamPrint(spice_stream_, ".ends\n\n");
371 }
372 
373 // Gate and load parasitics.
374 void
writeGateStage(Stage stage)375 WriteSpice::writeGateStage(Stage stage)
376 {
377   auto input_pin = stageInputPin(stage);
378   auto input_pin_name = stageInputPinName(stage);
379   auto drvr_pin = stageDrvrPin(stage);
380   auto drvr_pin_name = stageDrvrPinName(stage);
381   auto load_pin_name = stageLoadPinName(stage);
382   streamPrint(spice_stream_, ".subckt stage%d %s %s %s\n",
383 	      stage,
384 	      input_pin_name,
385 	      drvr_pin_name,
386 	      load_pin_name);
387   Instance *inst = network_->instance(input_pin);
388   const char *inst_name = network_->pathName(inst);
389   LibertyCell *cell = network_->libertyCell(inst);
390   const char *cell_name = cell->name();
391   auto spice_port_names = cell_spice_port_names_[cell_name];
392 
393   // Instance subckt call.
394   streamPrint(spice_stream_, "x%s", inst_name);
395   StringVector::Iterator port_iter(spice_port_names);
396   while (port_iter.hasNext()) {
397     const char *subckt_port_name = port_iter.next().c_str();
398     auto pin = network_->findPin(inst, subckt_port_name);
399     auto pg_port = cell->findPgPort(subckt_port_name);
400     const char *pin_name;
401     if (pin) {
402       pin_name = network_->pathName(pin);
403       streamPrint(spice_stream_, " %s", pin_name);
404     }
405     else if (pg_port)
406       streamPrint(spice_stream_, " %s/%s", inst_name, subckt_port_name);
407   }
408   streamPrint(spice_stream_, " %s\n", cell_name);
409 
410   writeStageVoltageSources(cell, spice_port_names,
411 			   inst_name,
412 			   network_->libertyPort(input_pin),
413 			   network_->libertyPort(drvr_pin));
414   writeStageParasitics(stage);
415   streamPrint(spice_stream_, ".ends\n\n");
416 }
417 
418 typedef Map<LibertyPort*, LogicValue> LibertyPortLogicValues;
419 
420 // Find the logic values for expression inputs to enable paths from_port.
421 void
sensitizationValues(FuncExpr * expr,LibertyPort * from_port,LibertyPortLogicValues & port_values)422 sensitizationValues(FuncExpr *expr,
423 		    LibertyPort *from_port,
424 		    // Return values.
425 		    LibertyPortLogicValues &port_values)
426 {
427   switch (expr->op()) {
428   case FuncExpr::op_port: {
429     break;
430   }
431   case FuncExpr::op_not: {
432     sensitizationValues(expr->left(), from_port, port_values);
433     break;
434   }
435   case FuncExpr::op_or: {
436     FuncExpr *left = expr->left();
437     FuncExpr *right = expr->right();
438     if (left->port() == from_port
439 	&& right->op() == FuncExpr::op_port)
440       port_values[right->port()] = logic_zero;
441     else if (right->port() == from_port
442 	     && left->op() == FuncExpr::op_port)
443       port_values[left->port()] = logic_zero;
444     break;
445   }
446   case FuncExpr::op_and: {
447     FuncExpr *left = expr->left();
448     FuncExpr *right = expr->right();
449     if (left->port() == from_port
450 	&& right->op() == FuncExpr::op_port)
451       port_values[right->port()] = logic_one;
452     else if (right->port() == from_port
453 	     && left->op() == FuncExpr::op_port)
454       port_values[left->port()] = logic_one;
455     break;
456   }
457   case FuncExpr::op_xor: {
458     // Need to know timing arc sense to get this right.
459     FuncExpr *left = expr->left();
460     FuncExpr *right = expr->right();
461     if (left->port() == from_port
462 	&& right->op() == FuncExpr::op_port)
463       port_values[right->port()] = logic_zero;
464     else if (right->port() == from_port
465 	     && left->op() == FuncExpr::op_port)
466       port_values[left->port()] = logic_zero;
467     break;
468   }
469   case FuncExpr::op_one:
470   case FuncExpr::op_zero:
471     break;
472   }
473 }
474 
475 // Power/ground and input voltage sources.
476 void
writeStageVoltageSources(LibertyCell * cell,StringVector * spice_port_names,const char * inst_name,LibertyPort * from_port,LibertyPort * drvr_port)477 WriteSpice::writeStageVoltageSources(LibertyCell *cell,
478 				     StringVector *spice_port_names,
479 				     const char *inst_name,
480 				     LibertyPort *from_port,
481 				     LibertyPort *drvr_port)
482 {
483   auto from_port_name = from_port->name();
484   auto drvr_port_name = drvr_port->name();
485   LibertyLibrary *lib = cell->libertyLibrary();
486   LibertyPortLogicValues port_values;
487   sensitizationValues(drvr_port->function(), from_port, port_values);
488   int volt_source = 1;
489   debugPrint1(debug_, "write_spice", 2, "subckt %s\n", cell->name());
490   StringVector::Iterator port_iter(spice_port_names);
491   while (port_iter.hasNext()) {
492     auto subckt_port_name = port_iter.next().c_str();
493     auto pg_port = cell->findPgPort(subckt_port_name);
494     debugPrint2(debug_, "write_spice", 2, " port %s%s\n",
495 		subckt_port_name,
496 		pg_port ? " pwr/gnd" : "");
497     if (pg_port) {
498       auto voltage = pgPortVoltage(pg_port);
499       streamPrint(spice_stream_, "v%d %s/%s 0 %.3f\n",
500 		  volt_source,
501 		  inst_name, subckt_port_name,
502 		  voltage);
503       volt_source++;
504     } else if (!(stringEq(subckt_port_name, from_port_name)
505 		 || stringEq(subckt_port_name, drvr_port_name))) {
506       // Input voltage to sensitize path from gate input to output.
507       LibertyPort *port = cell->findLibertyPort(subckt_port_name);
508       if (port) {
509 	const char *pg_port_name = NULL;
510 	bool port_has_value;
511 	LogicValue port_value;
512 	port_values.findKey(port, port_value, port_has_value);
513 	if (port_has_value) {
514 	  switch (port_value) {
515 	  case logic_zero:
516 	    pg_port_name = port->relatedGroundPin();
517 	    break;
518 	  case logic_one:
519 	    pg_port_name = port->relatedPowerPin();
520 	    break;
521 	  default:
522 	    break;
523 	  }
524 	  if (pg_port_name) {
525 	    auto pg_port = cell->findPgPort(pg_port_name);
526 	    if (pg_port) {
527 	      auto voltage_name = pg_port->voltageName();
528 	      if (voltage_name) {
529 		float voltage = lib->supplyVoltage(voltage_name);
530 		streamPrint(spice_stream_, "v%d %s/%s 0 %.3f\n",
531 			    volt_source,
532 			    inst_name, subckt_port_name,
533 			    voltage);
534 		volt_source++;
535 	      }
536 	      else
537 	      report_->error("port %s %s voltage %s not found,\n",
538 			     subckt_port_name,
539 			     pg_port_name,
540 			     voltage_name);
541 	    }
542 	    else
543 	      report_->error("port %s %s not found,\n",
544 			     subckt_port_name,
545 			     pg_port_name);
546 	  }
547 	}
548       }
549     }
550   }
551 }
552 
553 typedef Set<ParasiticDevice*> ParasiticDeviceSet;
554 typedef Set<ParasiticNode*> ParasiticNodeSet;
555 
556 void
findParasiticDevicesNodes(ParasiticNode * node,Parasitics * parasitics,ParasiticNodeSet & nodes,ParasiticDeviceSet & devices)557 findParasiticDevicesNodes(ParasiticNode *node,
558 			  Parasitics *parasitics,
559 			  // Return values.
560 			  ParasiticNodeSet &nodes,
561 			  ParasiticDeviceSet &devices)
562 {
563   nodes.insert(node);
564   auto device_iter = parasitics->deviceIterator(node);
565   while (device_iter->hasNext()) {
566     auto device = device_iter->next();
567     if (!devices.hasKey(device)) {
568       devices.insert(device);
569       auto other_node = parasitics->otherNode(device, node);
570       findParasiticDevicesNodes(other_node, parasitics, nodes, devices);
571     }
572   }
573   delete device_iter;
574 }
575 
576 void
writeStageParasitics(Stage stage)577 WriteSpice::writeStageParasitics(Stage stage)
578 {
579   auto drvr_path = stageDrvrPath(stage);
580   auto drvr_pin = stageDrvrPin(stage);
581   auto load_pin = stageLoadPin(stage);
582   auto dcalc_ap = drvr_path->dcalcAnalysisPt(this);
583   auto parasitic_ap = dcalc_ap->parasiticAnalysisPt();
584   auto parasitic = parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
585   int resistor_index = 1;
586   int cap_index = 1;
587   if (parasitic) {
588     Net *net = network_->net(drvr_pin);
589     auto net_name =
590       net ? network_->pathName(net) : network_->pathName(drvr_pin);
591     initNodeMap(net_name);
592     streamPrint(spice_stream_, "* Net %s\n", net_name);
593     auto node = parasitics_->findNode(parasitic, drvr_pin);
594     ParasiticNodeSet nodes;
595     ParasiticDeviceSet devices;
596     findParasiticDevicesNodes(node, parasitics_, nodes, devices);
597     ParasiticDeviceSet::Iterator device_iter(devices);
598     while (device_iter.hasNext()) {
599       auto device = device_iter.next();
600       auto resistance = parasitics_->value(device, parasitic_ap);
601       if (parasitics_->isResistor(device)) {
602 	ParasiticNode *node1, *node2;
603 	parasitics_->resistorNodes(device, node1, node2);
604 	streamPrint(spice_stream_, "R%d %s %s %.3e\n",
605 		    resistor_index,
606 		    nodeName(node1),
607 		    nodeName(node2),
608 		    resistance);
609 	resistor_index++;
610       }
611       else if (parasitics_->isCouplingCap(device)) {
612       }
613     }
614     ParasiticNodeSet::Iterator node_iter(nodes);
615     while (node_iter.hasNext()) {
616       auto node = node_iter.next();
617       auto cap = parasitics_->nodeGndCap(node, parasitic_ap);
618       streamPrint(spice_stream_, "C%d %s 0 %.3e\n",
619 		  cap_index,
620 		  nodeName(node),
621 		  cap);
622       cap_index++;
623     }
624   }
625   else
626     streamPrint(spice_stream_, "R1 %s %s %.3e\n",
627 		network_->pathName(drvr_pin),
628 		network_->pathName(load_pin),
629 		short_ckt_resistance_);
630 }
631 
632 void
initNodeMap(const char * net_name)633 WriteSpice::initNodeMap(const char *net_name)
634 {
635   stringDelete(net_name_);
636   node_map_.clear();
637   next_node_index_ = 1;
638   net_name_ = stringCopy(net_name);
639 }
640 
641 const char *
nodeName(ParasiticNode * node)642 WriteSpice::nodeName(ParasiticNode *node)
643 {
644   auto pin = parasitics_->connectionPin(node);
645   if (pin)
646     return parasitics_->name(node);
647   else {
648     int node_index;
649     bool node_index_exists;
650     node_map_.findKey(node, node_index, node_index_exists);
651     if (!node_index_exists) {
652       node_index = next_node_index_++;
653       node_map_[node] = node_index;
654     }
655     return stringPrintTmp(strlen(net_name_) + 10, "%s/%d",
656 			  net_name_, node_index);
657   }
658 }
659 
660 ////////////////////////////////////////////////////////////////
661 
662 // Copy the subckt definition from lib_subckts_filename for
663 // each cell in path to path_subckts_filename.
664 void
writeSubckts()665 WriteSpice::writeSubckts()
666 {
667   StringSet path_cell_names;
668   findPathCellnames(path_cell_names);
669 
670   ifstream lib_subckts_stream(lib_subckts_filename_);
671   if (lib_subckts_stream.is_open()) {
672     ofstream subckts_stream(subckts_filename_);
673     if (subckts_stream.is_open()) {
674       string line;
675       while (getline(lib_subckts_stream, line)) {
676 	// .subckt <cell_name> [args..]
677 	StringVector tokens;
678 	split(line, " \t", tokens);
679 	if (tokens.size() >= 2
680 	    && stringEqual(tokens[0].c_str(), ".subckt")) {
681 	  const char *cell_name = tokens[1].c_str();
682 	  if (path_cell_names.hasKey(cell_name)) {
683 	    subckts_stream << line << "\n";
684 	    bool found_ends = false;
685 	    while (getline(lib_subckts_stream, line)) {
686 	      subckts_stream << line << "\n";
687 	      if (stringEqual(line.c_str(), ".ends")) {
688 		subckts_stream << "\n";
689 		found_ends = true;
690 		break;
691 	      }
692 	    }
693 	    if (!found_ends)
694 	      throw SubcktEndsMissing(cell_name, lib_subckts_filename_);
695 	    path_cell_names.eraseKey(cell_name);
696 	  }
697 	  recordSpicePortNames(cell_name, tokens);
698 	}
699       }
700       subckts_stream.close();
701       lib_subckts_stream.close();
702 
703       if (!path_cell_names.empty()) {
704 	StringSet::Iterator cell_iter(path_cell_names);
705 	report_->error("The following subkcts are missing from %s\n",
706 		       lib_subckts_filename_);
707 	while (cell_iter.hasNext()) {
708 	  const char *cell_name = cell_iter.next();
709 	  report_->printError(" %s\n", cell_name);
710 	}
711       }
712     }
713     else {
714       lib_subckts_stream.close();
715       throw FileNotWritable(subckts_filename_);
716     }
717   }
718   else
719     throw FileNotReadable(lib_subckts_filename_);
720 }
721 
722 void
findPathCellnames(StringSet & path_cell_names)723 WriteSpice::findPathCellnames(// Return values.
724 			      StringSet &path_cell_names)
725 {
726   for (Stage stage = stageFirst(); stage <= stageLast(); stage++) {
727     auto arc = stageGateArc(stage);
728     if (arc) {
729       LibertyCell *cell = arc->set()->libertyCell();
730       if (cell) {
731 	debugPrint1(debug_, "write_spice", 2, "cell %s\n", cell->name());
732 	path_cell_names.insert(cell->name());
733       }
734     }
735   }
736 }
737 
738 void
recordSpicePortNames(const char * cell_name,StringVector & tokens)739 WriteSpice::recordSpicePortNames(const char *cell_name,
740 				 StringVector &tokens)
741 {
742   auto cell = network_->findLibertyCell(cell_name);
743   auto spice_port_names = new StringVector;
744   for (int i = 2; i < tokens.size(); i++) {
745     const char *port_name = tokens[i].c_str();
746     auto port = cell->findLibertyPort(port_name);
747     auto pg_port = cell->findPgPort(port_name);
748     if (port == NULL && pg_port == NULL)
749       report_->error("subckt %s port %s has no corresponding liberty port or pg_port.\n",
750 		     cell_name, port_name);
751     spice_port_names->push_back(port_name);
752   }
753   cell_spice_port_names_[cell_name] = spice_port_names;
754 }
755 
756 ////////////////////////////////////////////////////////////////
757 
758 Stage
stageFirst()759 WriteSpice::stageFirst()
760 {
761   return 1;
762 }
763 
764 Stage
stageLast()765 WriteSpice::stageLast()
766 {
767   return (path_expanded_.size() + 1) / 2;
768 }
769 
770 string
stageName(Stage stage)771 WriteSpice::stageName(Stage stage)
772 {
773   string name;
774   stringPrint(name, "stage%d", stage);
775   return name;
776 }
777 
778 int
stageGateInputPathIndex(Stage stage)779 WriteSpice::stageGateInputPathIndex(Stage stage)
780 {
781   return stage * 2 - 3;
782 }
783 
784 int
stageDrvrPathIndex(Stage stage)785 WriteSpice::stageDrvrPathIndex(Stage stage)
786 {
787   return stage * 2 - 2;
788 }
789 
790 int
stageLoadPathIndex(Stage stage)791 WriteSpice::stageLoadPathIndex(Stage stage)
792 {
793   return stage * 2 - 1;
794 }
795 
796 PathRef *
stageGateInputPath(Stage stage)797 WriteSpice::stageGateInputPath(Stage stage)
798 {
799   int path_index = stageGateInputPathIndex(stage);
800   return path_expanded_.path(path_index);
801 }
802 
803 PathRef *
stageDrvrPath(Stage stage)804 WriteSpice::stageDrvrPath(Stage stage)
805 {
806   int path_index = stageDrvrPathIndex(stage);
807   return path_expanded_.path(path_index);
808 }
809 
810 PathRef *
stageLoadPath(Stage stage)811 WriteSpice::stageLoadPath(Stage stage)
812 {
813   int path_index = stageLoadPathIndex(stage);
814   return path_expanded_.path(path_index);
815 }
816 
817 TimingArc *
stageGateArc(Stage stage)818 WriteSpice::stageGateArc(Stage stage)
819 {
820   int path_index = stageDrvrPathIndex(stage);
821   if (path_index >= 0)
822     return path_expanded_.prevArc(path_index);
823   else
824     return NULL;
825 }
826 
827 TimingArc *
stageWireArc(Stage stage)828 WriteSpice::stageWireArc(Stage stage)
829 {
830   int path_index = stageLoadPathIndex(stage);
831   return path_expanded_.prevArc(path_index);
832 }
833 
834 Edge *
stageGateEdge(Stage stage)835 WriteSpice::stageGateEdge(Stage stage)
836 {
837   PathRef *path = stageGateInputPath(stage);
838   TimingArc *arc = stageGateArc(stage);
839   return path->prevEdge(arc, this);
840 }
841 
842 Edge *
stageWireEdge(Stage stage)843 WriteSpice::stageWireEdge(Stage stage)
844 {
845   PathRef *path = stageLoadPath(stage);
846   TimingArc *arc = stageWireArc(stage);
847   return path->prevEdge(arc, this);
848 }
849 
850 Pin *
stageInputPin(Stage stage)851 WriteSpice::stageInputPin(Stage stage)
852 {
853   PathRef *path = stageGateInputPath(stage);
854   return path->pin(this);
855 }
856 
857 Pin *
stageDrvrPin(Stage stage)858 WriteSpice::stageDrvrPin(Stage stage)
859 {
860   PathRef *path = stageDrvrPath(stage);
861   return path->pin(this);
862 }
863 
864 Pin *
stageLoadPin(Stage stage)865 WriteSpice::stageLoadPin(Stage stage)
866 {
867   PathRef *path = stageLoadPath(stage);
868   return path->pin(this);
869 }
870 
871 const char *
stageInputPinName(Stage stage)872 WriteSpice::stageInputPinName(Stage stage)
873 {
874   const Pin *pin = stageInputPin(stage);
875   return network_->pathName(pin);
876 }
877 
878 const char *
stageDrvrPinName(Stage stage)879 WriteSpice::stageDrvrPinName(Stage stage)
880 {
881   Pin *pin = stageDrvrPin(stage);
882   return network_->pathName(pin);
883 }
884 
885 const char *
stageLoadPinName(Stage stage)886 WriteSpice::stageLoadPinName(Stage stage)
887 {
888   const Pin *pin = stageLoadPin(stage);
889   return network_->pathName(pin);
890 }
891 
892 ////////////////////////////////////////////////////////////////
893 
894 void
split(const string & text,const string & delims,StringVector & tokens)895 split(const string &text,
896       const string &delims,
897       // Return values.
898       StringVector &tokens)
899 {
900   auto start = text.find_first_not_of(delims);
901   auto end = text.find_first_of(delims, start);
902   while (end != string::npos) {
903     tokens.push_back(text.substr(start, end - start));
904     start = text.find_first_not_of(delims, end);
905     end = text.find_first_of(delims, start);
906   }
907   if (start != string::npos)
908     tokens.push_back(text.substr(start));
909 }
910 
911 // fprintf for c++ streams.
912 // Yes, I hate formatted output to ostream THAT much.
913 void
streamPrint(ofstream & stream,const char * fmt,...)914 streamPrint(ofstream &stream,
915 	    const char *fmt,
916 	    ...)
917 {
918   va_list args;
919   va_start(args, fmt);
920   char *result;
921   vasprintf(&result, fmt, args);
922   stream << result;
923   free(result);
924   va_end(args);
925 }
926 
927 } // namespace
928