ostream &operator<< (ostream &o, CPowers &self) { LPower::iterator itLine, beginLine, endLine; o << "+ CPowers:\n"; o << "+ "; if (self.type == C_HORIZONTAL) o << "horizontal"; else o << "vertical "; o << " " << layer2a (self.layer) << " " << UNSCALE (self.width); o << " [" << UNSCALE (self.AB1) << "," << UNSCALE (self.AB2) << "]\n"; beginLine = self.powerLines.begin (); endLine = self.powerLines.end (); for (itLine = beginLine; itLine != endLine; itLine++) { o << "+ " << itLine->first << " " << itLine->second << "\n"; } return (o); }
static void define_coordinate_axes ( struct pset * pts, /* IN - terminals to plot */ struct scale_info * sip /* IN - problem scaling info */ ) { int i; int n; struct point * p1; double x, y; double minxcoord, maxxcoord; double minycoord, maxycoord; double xspan, yspan, span; double axmin, axmax; double aymin, aymax; n = pts -> n; if (n < 1) { printf ("\n0 1 0 1 SetAxes\n"); return; } p1 = &(pts -> a [0]); minxcoord = maxxcoord = p1 -> x; minycoord = maxycoord = p1 -> y; ++p1; for (i = 1; i < n; i++, p1++) { x = p1 -> x; y = p1 -> y; if (x < minxcoord) { minxcoord = x; } else if (x > maxxcoord) { maxxcoord = x; } if (y < minycoord) { minycoord = y; } else if (y > maxycoord) { maxycoord = y; } } minxcoord = UNSCALE (minxcoord, sip); maxxcoord = UNSCALE (maxxcoord, sip); minycoord = UNSCALE (minycoord, sip); maxycoord = UNSCALE (maxycoord, sip); /* We only generate square plots having equal scales on both */ /* axes. Determine the "span" of the plot, i.e., the length of */ /* each axis in the plot. */ xspan = maxxcoord - minxcoord; yspan = maxycoord - minycoord; if (xspan EQ 0.0) { if (yspan EQ 0.0) { /* Single point. */ if (maxxcoord NE 0.0) { if (fabs (maxxcoord) >= fabs (maxycoord)) { span = 2.0 * fabs (maxxcoord); } else { span = 2.0 * fabs (maxycoord); } } else if (maxycoord NE 0.0) { span = 2.0 * fabs (maxycoord); } else { /* Single point at the origin. */ span = 2.0; } } else { span = get_limit (yspan); } } else if (yspan EQ 0.0) { span = get_limit (xspan); } else if (xspan >= yspan) { span = get_limit (xspan); } else { span = get_limit (yspan); } /* Determine the minimum x axis value. */ if (xspan EQ 0.0) { goto center_x; } else if ((0.0 <= minxcoord) AND (maxxcoord <= span)) { axmin = 0.0; } else if ((-span <= minxcoord) AND (maxxcoord <= 0.0)) { axmin = -span; } else if ((-0.5 * span <= minxcoord) AND (maxxcoord <= 0.5 * span)) { axmin = -0.5 * span; } else { center_x: /* Center the x coordinates. */ axmin = 0.5 * (minxcoord + maxxcoord - span); } axmax = axmin + span; /* Determine the minimum y axis value. */ if (yspan EQ 0.0) { goto center_y; } else if ((0.0 <= minycoord) AND (maxycoord <= span)) { aymin = 0.0; } else if ((-span <= minycoord) AND (maxycoord <= 0.0)) { aymin = -span; } else if ((-0.5 * span <= minycoord) AND (maxycoord <= 0.5 * span)) { aymin = -0.5 * span; } else { center_y: /* Center the y coordinates */ aymin = 0.5 * (minycoord + maxycoord - span); } aymax = aymin + span; /* Good enough for now... */ printf ("\n%g %g %g %g SetAxes\n", axmin, axmax, aymin, aymax); }
CPowers::CPowers ( CFig *fig , long xoff , long yoff , char atype , int alayer , long awidth ) throw (except_done) : xoffset(xoff) , yoffset(yoff) { LPower::iterator itLine, beginLine, endLine; phins_list *ins; phfig_list *model; phseg_list *seg, flatSeg; string mess1, mess2; char ORIENT1, ORIENT2; char segType; long lbound, rbound, key; type = atype; width = awidth; layer = layer2CALU (alayer); switch (type) { default: case C_HORIZONTAL: mess1 = "horizontal"; mess2 = "EAST/WEST"; ORIENT1 = EAST; ORIENT2 = WEST; AB1 = fig->XAB1 (); AB2 = fig->XAB2 (); break; case C_VERTICAL: mess1 = "vertical"; mess2 = "NORTH/SOUTH"; ORIENT1 = NORTH; ORIENT2 = SOUTH; AB1 = fig->YAB1 (); AB2 = fig->YAB2 (); break; } // Loop over all the instances. for (ins = fig->phfig.fig->PHINS; ins != NULL; ins = ins->NEXT) { model = getphfig (ins->FIGNAME, 'A'); // Find the power segments (CALUx). for (seg = model->PHSEG; seg != NULL; seg = seg->NEXT) { // Skip no power segments. if (!(cmpALU (alayer, seg->LAYER) & F_CALU)) continue; segType = C_POWER_NONE; if (ISVDD (seg->NAME)) segType = C_POWER_VDD; if (ISVSS (seg->NAME)) segType = C_POWER_VSS; if (segType == C_POWER_NONE) continue; xyflat ( &(flatSeg.X1), &(flatSeg.Y1) , seg->X1, seg->Y1 , ins->XINS, ins->YINS , model->XAB1, model->YAB1 , model->XAB2, model->YAB2 , ins->TRANSF ); xyflat ( &(flatSeg.X2), &(flatSeg.Y2) , seg->X2, seg->Y2 , ins->XINS, ins->YINS , model->XAB1, model->YAB1 , model->XAB2, model->YAB2 , ins->TRANSF ); // Check the segment width. if (seg->WIDTH != width) { cerr << hwarn (""); cerr << " " << layer2a (layer) << " \"" << seg->NAME <<"\" segment at (" << UNSCALE (seg->X1) << "," << UNSCALE (seg->Y1) << ") doesn't have the rigth witdth :" << UNSCALE (seg->WIDTH) << " instead of " << UNSCALE (width) << ".\n"; cerr << " (instance \"" << ins->INSNAME << "\" of model \"" << model->NAME << "\")\n"; continue; } // Check the segment direction & position. switch (type) { default: case C_HORIZONTAL: lbound = flatSeg.X1; rbound = flatSeg.X2; key = flatSeg.Y1; if (flatSeg.Y1 != flatSeg.Y2) { cerr << hwarn (""); cerr << " " << layer2a (layer) << " \"" << seg->NAME <<"\" segment at (" << UNSCALE (seg->X1) << "," << UNSCALE (seg->Y1) << ") is not " << mess1; cerr << " (instance \"" << ins->INSNAME << "\" of model \"" << model->NAME << "\")\n"; continue; } if ( (cmpALU (alayer, CALU1) & F_CALU) && !fig->phfig.onslice (flatSeg.Y1,yoffset)) { cerr << hwarn (""); cerr << " " << layer2a (layer) << " \"" << seg->NAME <<"\" segment at (" << UNSCALE (seg->X1) << "," << UNSCALE (seg->Y1) << ") is not on a slice boundary.\n"; cerr << " (instance \"" << ins->INSNAME << "\" of model \"" << model->NAME << "\")\n"; cerr << " (valide slices boundaries are" << " ((n * " << D::Y_SLICE << ") - " << D::WIDTH_VSS / 2 << ") or" << " ((n * " << D::Y_SLICE << ") + " << D::WIDTH_VSS / 2 << ") )\n"; continue; } break; case C_VERTICAL: lbound = flatSeg.Y1; rbound = flatSeg.Y2; key = flatSeg.X1; if (flatSeg.X1 != flatSeg.X2) { cerr << hwarn (""); cerr << " " << layer2a (layer) << " \"" << seg->NAME <<"\" segment at (" << UNSCALE (seg->X1) << "," << UNSCALE (seg->Y1) << ") is not " << mess1; cerr << " (instance \"" << ins->INSNAME << "\" of model \"" << model->NAME << "\")\n"; continue; } break; } beginLine = powerLines.begin (); endLine = powerLines.end (); // Check if the power line is of the same type. // (no short circuits between VDD & VSS. itLine = powerLines.find (key); if (itLine != endLine) { if (itLine->second.type != segType) { cerr << herr (""); cerr << " " << layer2a (layer) << " \"" << seg->NAME <<"\" segment at (" << UNSCALE (seg->X1) << "," << UNSCALE (seg->Y1) << ") conflict with power line at" << UNSCALE (key) << ".\n"; throw except_done (); } } // Merge the segment with the power line (at long last...). powerLines[key].add (lbound, rbound); powerLines[key].type = segType; } } }