/* CHECKLNL (LAY) -- Check Layout against Netlist */ /* CHECKLNL (LAY) -- Layout gegen Netzliste pruefen */ /* // Copyright (c) 1993-2012 Oliver Bartels F+E, Muenchen // Author: Manfred Baumeister // Changes History: // rl (120427) RELEASED FOR BAE V7.8. // rl (101019) RELEASED FOR BAE V7.6. // rl (091020) RELEASED FOR BAE V7.4. // rl (081014) RELEASED FOR BAE V7.2. // rl (071029) RELEASED FOR BAE V7.0. // rl (060829) RELEASED FOR BAE V6.8. // rl (050906) RELEASED FOR BAE V6.6. // rl (040811) RELEASED FOR BAE V6.4. // rl (030904) RELEASED FOR BAE V6.2. // rl (021209) RELEASED FOR BAE V6.0. // rl (020618) RELEASED FOR BAE V5.4. // rl (010625) RELEASED FOR BAE V5.0. // rl (000508) RELEASED FOR BAE V4.6. // rl (990625) RELEASED FOR BAE V4.4. // rl (980910) RELEASED FOR BAE V4.2. // mb (980711) ENHANCEMENT: // Dynamic multi-language support introduced. // rl (970929) RELEASED FOR BAE V4.0. // mb (960919) RELEASED FOR BAE V3.4. // mb (95) RELEASED FOR BAE V3.2. // mb (941215) IMPROVEMENT: // Netlist check report via popup menu instead of // text screen output. // Pin lists generation via figure list scan for // avoiding part loads. // mb (94) RELEASED FOR BAE V3.0. // mb (94) BUGFIX: // lay_loadelem() status evaluation corrected. // mb (93) RELEASED FOR BAE V2.6. // mb (93) ORIGINAL CODING. // // DESCRIPTION // // The checklnl User Language program checks the currently // loaded layout against the corresponding netlist data and // reports unplaced parts, wrong package types and missing // pin definitions in a popup menu with file output option. */ // Includes #include "pop.ulh" // User Language popup utilities #include "lay.ulh" // User Language layout utilities // Disable undo state request #pragma ULCALLERNOUNDO // Messages string UPRFEXIT = M_UPRFEXIT(); string REPNOERR = M("Keine Fehler bei Pruefung Layout gegen Netzliste.", "No errors occurred on Layout check against Netlist."); string REPCKPIN = M("Pinlisten pruefen...","Checking pin lists..."); string WRNHD = M("Datei '%s' / Layout '%s' :", "File '%s' / Layout '%s' :"); string WRNPLCHD = M(" Noch nicht platzierte Bauteile :", " Unplaced Parts : "); string WRNPCKHD = M(" Bauteile platziert mit falschem Gehaeuse :", " Parts Placed with wrong Package :"); string WRNNMCHD = M(" Fehlende/undefinierte Makros/Symbole :", " Missing/undefined Macros/Symbols :"); string WRNNPNHD = M(" Fehlende Makro-Pindefinitionen :", " Missing Part Macro Pin Definitions :"); string WRNPLACE = M(" > '%s'"," > '%s'"); string WRNPCK = M(" > Bauteil '%s' Gehaeuse '%s' benutzt anstelle '%s'", " > Part '%s' Package '%s' used instead of '%s'"); string WRNNMC = M(" > %s Makro '%s'"," > %s Macro '%s'"); string WRNNPN = M(" > Bauteil '%s' Pin '%s' (Makro '%s')", " > Part '%s' Pin '%s' (Macro '%s')"); string HLPPLC1 = M("===> Bitte fehlende Bauteile platzieren!", "===> Please place missing parts!"); string HLPPLC2 = M(" (z.B. mit 'Naechstes Bauteil')", " (e.g. use 'Place Next Part')"); string HLPPACK1 = M("===> Bitte korrekte Gehaeusebauformen platzieren!", "===> Please place correct package types!"); string HLPPACK2 = M(" (z.B. mit 'Update Loeschen' und 'Naechstes Bauteil')", " (e.g. use 'Delete Update' and 'Place Next Part')"); string HLPNMC1 = M("===> Bitte fehlende Layout-Makros definieren/laden!", "===> Please define/load missing layout macros!"); string HLPNMC2 = M(" (z.B. mit 'Update Bibliothek')", " (e.g. use 'Update Library')"); string HLPNPN1 = M("===> Bitte Pindefinition(en) auf Bauteil-Makros korrigieren!", "===> Please correct pin definition(s) on part macros!"); string HLPNPN2 = M(" (z.B. Bauteilsymbole editieren und Layout neu laden)", " (e.g. edit part symbols and re-load layout)"); string ITMPRT = M("Bauteil ","Part "); string ITMSTK = M("Padstack","Padstack"); string ITMPAD = M("Pad ","Pad "); // Globals struct pmacrodes { // Part macro descriptor string n /* Part macro name */; int pn /* Part macro pin count */; STRINGS pl /* Part macro pin name list */; } pmacrol[] /* Part macro list */; int pmacron = 0 /* Part macro count */; int curmacidx = (-1) /* Current part macro index */; STRINGS curpl /* Current pin list */; int curpn /* Current macro pin count */; STRINGS msgl /* Message list */; int msgn = 0 /* Message count */; // Main program void main() { STRINGS headl /* Header list */; int headn = 2 /* Header count */; int popcols = 100 /* Popup columns count */; int i /* Loop control variable */; // Abort if invalid plan class if (bae_planddbclass()!=DDBCLLAY) error_class(); // Define the report header sprintf(headl[0],WRNHD,bae_planfname(),bae_planename()); // Check for unplaced parts checkplacement(); // Check for wrong packages checkpackages(); // Check the macro list checkmacros(); // Check the pin lists checkpinlists(); // Done if no error messages written if (!msgn) { bae_prtdialog(REPNOERR); bae_clriactqueue(); exit(0); } // Get the popup columns count for (i=0;i=0) { // Get current pin list curpl=pmacrol[curmacidx].pl; curpn=pmacrol[curmacidx].pn; // Loop for all undefined pins of the current part forall (cpin of cpart where findmacropin(cpin.NAME,idx)<0) { // Generate the error list header if first error if (!errflag) msgl[msgn++]=WRNNPNHD; // Pin name error sprintf(msgl[msgn],WRNNPN, cpart.NAME,cpin.NAME,cpart.PLNAME); msgn++; errflag++; } } // Test if any errors found if (errflag) { // Store help info msgl[msgn++]=HLPNPN1; msgl[msgn++]=HLPNPN2; msgn++; } } // Macro list functions int macfunc(index L_MACRO macro,index L_POOL pool, int macinws,string refname,index L_LEVEL level) /* // Macro scan function // Return value : // zero if scan abort or 1 if scan continue // Parameters : // index L_MACRO macro : Macro index // index L_POOL pool : Macro pool element index // int macinws : Macro in workspace flag // string refname : Macro reference name // index L_LEVEL level : Macro level */ { int insidx /* Insert index */; int i /* Loop control variable */; // Test the macro class switch (macro.CLASS) { case DDBCLLPRT : // Abort scan if macro not completed or already defined if ((macro.COMP & 0x02) || findmacro(macro.NAME,insidx)>=0) return(0); // Update the part macro list pmacron++; for (i=pmacron-2;i>=insidx;i--) pmacrol[i+1]=pmacrol[i]; pmacrol[insidx].n=macro.NAME; pmacrol[insidx].pn=0; curmacidx=insidx; // Continue scan return(1); // Padstack case DDBCLLSTK : // Store pin to current part macro pin list if (curmacidx>=0) gcmacropin(refname); // Continue scan return(1); } // Abort scan return(0); } int findmacro(string macroname,int insidx=(-1)) /* // Find a name specified macro within name-sorted macro list // Return value : // macro list index or (-1) if not found // Parameters : // string macroname : Macro name // int insidx : Macro list insert index */ { int slb = 0 /* Search lower boundary */; int sub = pmacron-1 /* Search upper boundary */; int sidx /* Search index */; int compres /* Compare result */; // Loop until search area empty while (slb<=sub) { // Get the search index sidx=(slb+sub)>>1; // Test if part found if ((compres=strcmp(macroname,pmacrol[sidx].n))==0) // Part found return(sidx); // Update the search area if (compres<0) sub=sidx-1; else slb=sidx+1; } // Store the insert part index insidx=slb; // Part not found return(-1); } void gcmacropin(string pinname) /* // Get or create a name specified pin within current macro pin list // Parameters : // string pinname : Pin name */ { int insidx /* Pin list insert index */; int i /* Loop control variable */; // Get current pin list curpl=pmacrol[curmacidx].pl; curpn=pmacrol[curmacidx].pn; if (findmacropin(pinname,insidx)>=0) return; // Update the current pin list curpn++; for (i=curpn-2;i>=insidx;i--) curpl[i+1]=curpl[i]; curpl[insidx]=pinname; // Restore the pin list to the current macro entry pmacrol[curmacidx].pl=curpl; pmacrol[curmacidx].pn=curpn; } int findmacropin(string pinname,int insidx=(-1)) /* // Find a name specified pin within current macro pin list // Return value : // pin list index, or (-1) if not found // Parameters : // string pinname : Pin name // int insidx=(-1) : Insert index */ { int slb = 0 /* Search lower boundary */; int sub = curpn-1 /* Search upper boundary */; int sidx /* Search index */; int compres /* Compare result */; // Loop until search area empty while (slb<=sub) { // Get the search index sidx=(slb+sub)>>1; // Test if part found if ((compres=strcmp(pinname,curpl[sidx]))==0) // Ignore multiple pin names return(sidx); // Update the search area if (compres<0) sub=sidx-1; else slb=sidx+1; } // Pin not found insidx=slb; return(-1); } // User Language program end