CPhfig::CPhfig (string &name) { phins_list *pPhins; cmess1 << " o Loading layout \"" << name << "\"...\n"; fig = getphfig ((char *)name.c_str (), 'A'); // Build the instances dictionnary (map). for (pPhins = fig->PHINS; pPhins != NULL; pPhins = pPhins->NEXT) { instances[pPhins->INSNAME] = pPhins; } }
phfig_list *CIns::getmodel (void) { if (!model) model = getphfig (phins->FIGNAME, 'A'); return (model); }
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; } } }
void lecture_vues(char *nom_circuit_lo, COEUR *lecoeur, lofig_list **circuit_lo, chain_list **liste_plotsph, int *nbplots, chain_list **lst_conestouest) { chain_list * lstph; phfig_list * ptfig; loins_list * circuit_inst; /* instances dans le circuit logique */ loins_list * coeur_inst = NULL; /* instance du coeur */ int nbcoeur = 0; /* nombres d'instances susceptibles d'etre le coeur */ int retour; *circuit_lo = getlofig(nom_circuit_lo, 'A'); if (!(*circuit_lo)) ringerreur(ERR_CIRCUITLO, nom_circuit_lo, NULL); /* viewlo(); */ circuit_inst = (*circuit_lo)->LOINS; if (!circuit_inst) ringerreur(ERR_CIRCUITINST, nom_circuit_lo, NULL); /* ---------------------------------------------------------------------------------------------------------- */ /* test la coherences des modeles logiques et physiques de toutes les modeles utilisee dans la figure logique */ /* ---------------------------------------------------------------------------------------------------------- */ testcon_modelfig(*circuit_lo); /* ------------------------------------------------------------------------------------------------------------- */ /* Parcours des instances pour distinguer celles qui sont des plots et les autres (normalement 1 seule: le coeur */ /* ------------------------------------------------------------------------------------------------------------- */ *nbplots = 0; (*liste_plotsph) = NULL; /* Initialisation de la liste de plots physiques */ while (circuit_inst != NULL) { retour = incatalog(circuit_inst->FIGNAME); if (mode_debug) printf("FIGNAME %s incatalog %d\n", circuit_inst->FIGNAME, retour); if (retour) { (*nbplots)++; /* -------------------------------------- */ /* Renommage des connecteurs vdd* et vss* */ /* -------------------------------------- */ ajout_listeplotsph(circuit_inst->FIGNAME, liste_plotsph); } else /* le coeur est reconnu */ { nbcoeur++; coeur_inst = circuit_inst; } circuit_inst = circuit_inst->NEXT; } if (mode_debug) printf("Lirevues: nb inst plots %d\n", *nbplots); /* -------------------------------------------- */ /* Verification sur le nombres de coeur trouves */ /* -------------------------------------------- */ switch (nbcoeur) { case 0: ringerreur(ERR_NONCOEUR, NULL, NULL); /* aucun => ringerreur */ break; case 1: /* ------------------------------------------------------ */ /* un seul coeur, on charge les vues logique et physique */ /* ------------------------------------------------------ */ (*lecoeur).coeur_lo = coeur_inst; if ((*lecoeur).coeur_lo == NULL) ringerreur(ERR_COEURINSTLO, coeur_inst->FIGNAME, NULL); ptfig = (*lecoeur).coeur_ph = getphfig(coeur_inst->FIGNAME, 'A'); (*lecoeur).coord.xabs = 0; (*lecoeur).coord.yabs = 0; /* Coordonnees du coeur fixees a 0,0 par defaut */ (*lecoeur).width = ptfig->XAB2 - ptfig->XAB1; (*lecoeur).height = ptfig->YAB2 - ptfig->YAB1; (*lecoeur).coord.piste = 0; (*lecoeur).rotation = NOSYM; /* pas de rotation par defaut */ /* viewphfig((*lecoeur).coeur_ph); */ if ((*lecoeur).coeur_ph == NULL) ringerreur(ERR_COEURINSTPH, coeur_inst->FIGNAME, NULL); break; default: /* ------------------------------------------ */ /* plusieurs candidats au coeur => ringerreur */ /* ------------------------------------------ */ ringerreur(ERR_PLUSCOEUR, (*circuit_lo)->LOINS, NULL); } /* ----------------------------------------------------- */ /* verification des modeles pour connexion alim internes */ /* ----------------------------------------------------- */ lstph = *liste_plotsph; while (NULL != lstph) { verif_con_estouest(lstph, lst_conestouest); lstph = lstph->NEXT; } if (mode_debug) affic_listeplotsph(*liste_plotsph); }
int main (int argc, char *argv[]) { phfig_list *pFig; phseg_list *pSeg; phvia_list *pVIA; long length[_MAX_ALU_]; long number[_MAX_ALU_]; long total_length; long total_number; long total_VIA; int i; mbkenv (); alliancebanner ( "PdV" , "0.1" , "Pot de Vin - Routing Evaluator" , "2002" , "5.0" ); if (argc < 2) { fprintf (stderr, "Usage : pdv <layout>\n"); exit (1); } pFig = getphfig (argv[1], 'A'); for (i = 0; i < _MAX_ALU_; i++) { length[i] = 0; number[i] = 0; } for (pSeg = pFig->PHSEG; pSeg != NULL; pSeg = pSeg->NEXT) { switch (pSeg->LAYER) { case ALU2: case CALU2: i = _ALU2_; break; case ALU3: case CALU3: i = _ALU3_; break; case ALU4: case CALU4: i = _ALU4_; break; case ALU5: case CALU5: i = _ALU5_; break; case ALU6: case CALU6: i = _ALU6_; break; case ALU7: case CALU7: i = _ALU7_; break; case ALU8: case CALU8: i = _ALU8_; break; default: continue; } number[i]++; if (pSeg->X1 == pSeg->X2) { /* Horizontal segments. */ length[i] += (pSeg->Y2 - pSeg->Y1) / SCALE_X; } else { /* Vertical segments. */ length[i] += (pSeg->X2 - pSeg->X1) / SCALE_X; } } for (i = 0; i < _MAX_ALU_; i++) { if (number[i] == 0) number[i]++; } total_VIA = 0; for (pVIA = pFig->PHVIA; pVIA != NULL; pVIA = pVIA->NEXT) { total_VIA++; } printf ("\n\n"); printf (" Routing statistics :\n\n"); total_length = 0; total_number = 0; for (i = 0; i < _MAX_ALU_; i++) { printf (" - ALU%d length := %10d", i+2, length[i]); printf (" (average length := %d)\n", length[i] / number[i]); total_length += length[i]; total_number += number[i]; } printf ("\n"); printf (" - Total length := %10d" , total_length); printf (" (average length := %d)\n", total_length / total_number); printf ("\n"); printf (" - Total VIA := %10d\n" , total_VIA); printf ("\n\n"); exit (0); }