phseg_list &CIns::flatseg (phseg_list &flatSeg, phseg_list &seg) { flatSeg.NAME = seg.NAME; flatSeg.LAYER = seg.LAYER; flatSeg.WIDTH = seg.WIDTH; xyflat ( &flatSeg.X1, &flatSeg.Y1 , seg.X1, seg.Y1 , phins->XINS, phins->YINS , model->XAB1, model->YAB1 , model->XAB2, model->YAB2 , phins->TRANSF ); xyflat ( &flatSeg.X2 , &flatSeg.Y2 , seg.X2 , seg.Y2 , phins->XINS, phins->YINS , model->XAB1, model->YAB1 , model->XAB2, model->YAB2 , phins->TRANSF ); // Ensure that (X1,Y1) < (X2,Y2) and type is correct. if (flatSeg.X1 > flatSeg.X2) { swap (flatSeg.X1, flatSeg.X2); } if (flatSeg.Y1 > flatSeg.Y2) { swap (flatSeg.Y1, flatSeg.Y2); } if (flatSeg.Y1 == flatSeg.Y2) { if (flatSeg.X1 < flatSeg.X2) flatSeg.TYPE = LEFT; else flatSeg.TYPE = RIGHT; } else { if (flatSeg.Y1 < flatSeg.Y2) flatSeg.TYPE = UP; else flatSeg.TYPE = DOWN; } // Return the flattened segment; return (flatSeg); }
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; } } }