/* LAYPCR (LAY) -- Layout Report */ /* LAYPCR (LAY) -- Layout-Report */ /* -- INTENDED FOR KEY-CALL USE -- */ /* // Copyright (c) 1992-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 (091027) 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 (060829) ENHANCEMENT: // Changed lay_getplanchkparam parameters to 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 (000823) RELEASED FOR BAE V4.6. // rl (000823) ENHANCEMENT: // Added pad mirroring display. // rl (991122) RELEASED FOR BAE V4.4. // rl (991122) ENHANCEMENT: // Added pin drill diameter display. // rl (980910) RELEASED FOR BAE V4.2. // rl (980901) ENHANCEMENT: // Changed lay_getplanchkparam parameters to V4.2. // mb (980713) ENHANCEMENT: // Dynamic multi-language support introduced. // rl (970929) RELEASED FOR BAE V4.0. // mb (960919) RELEASED FOR BAE V3.4. // mb (951004) IMPROVEMENT: // Providing SORTED part/pin lists. // mb (95) RELEASED FOR BAE V3.2. // mb (94) RELEASED FOR BAE V3.0. // mb (93) RELEASED FOR BAE V2.6. // mb (93) RELEASED FOR BAE V2.4. // mb (92) RELEASED FOR BAE V2.2. // mb (92) ORIGINAL CODING. // // DESCRIPTION // // The laypcr User Language program provides detailed information // on the currently loaded layout element such as DDB file name, // element name, element origin coordinates, element boundary coordinates, // element size, DRC checking parameter settings, power layer definitions, // top layer setting, reference listing (parts on layout, padstacks // on part, pads/drilling on padstack). The report output is directed // to a popup menu with file output option. */ // Includes #include "pop.ulh" // User Language popup utilities #include "lay.ulh" // User Language layout utilities // Enforce LAY caller type #pragma ULCALLERLAY // Disable undo state request #pragma ULCALLERNOUNDO // Messages string REPSCNPRT = M("Scannen Bauteile (Abbruch mit Tastendruck)...", "Scanning parts (hit any key to abort)..."); string REPHEADER = M("%s Report :","%s Report :"); string REPFILE = M("Dateiname ...............: '%s'", "File Name ...............: '%s'"); string REPELEM = M("Elementname .............: '%s'", "Element Name ............: '%s'"); string REPSAVE = M("Plan gesichert ..........: %s", "Element saved ...........: %s"); string REPORIG = M("Nullpunkt ...............: %8.3f,%8.3f %s", "Origin ..................: %8.3f,%8.3f %s"); string REPUBND = M("Obere Grenze ............: %8.3f,%8.3f %s", "Upper Boundary ..........: %8.3f,%8.3f %s"); string REPLBND = M("Untere Grenze ...........: %8.3f,%8.3f %s", "Lower Boundary ..........: %8.3f,%8.3f %s"); string REPSIZE = M("Plan Groesse ............: %8.3f,%8.3f %s", "Element Size ............: %8.3f,%8.3f %s"); string REPRSIZE = M("Routingmatrix Groesse ...: %s", "Routing Matrix Size .....: %s"); string REPNOBOUTLINE = M("Keine Umrandung definiert!", "No board outline definied!"); string REPCHKBLK = M("DRC-Block %d .............: %s", "DRC Block %d .............: %s"); string REPCHKHD1 = M("DRC-Abstaende ...........:", "DRC Distances ...........:"); string REPCHKHD2 = M(" T-T T-C C-C T-WIDTH", " T-T T-C C-C T-WIDTH"); string REPCHKHD = REPCHKHD1+REPCHKHD2; string REPCHKEN = M(" Block %d %-15s : %8.3f %-2s %8.3f %-2s %8.3f %-2s %8.3f %-2s", " Block %d %-15s : %8.3f %-2s %8.3f %-2s %8.3f %-2s %8.3f %-2s"); string REPPOWLAY = M("Versorgungslage %2d ......: '%s'", "Power Layer %2d ..........: '%s'"); string REPTOPLAY = M("Oberste Lage ............: %d", "Top Layer ...............: %d"); string REPBTWLAY = M("Anzahl Innenlagen .......: %d", "Inner Layer Count .......: %d"); string REPPRTCNT = M("Bauteilanzahl ...........: %d", "Part Count ..............: %d"); string REPPINCNT = M("Pin-/Viaanzahl ..........: %d", "Pin/Via Count ...........: %d"); string UPRPARTLA = M("Bauteilliste Alle","Part List All"); string UPRPARTLP = M("Bauteilliste Platziert","Part List Placed"); string UPRPARTLU = M("Bauteilliste Unplatziert","Part List Unplaced"); string UPRPARTLC = M("Bauteilliste Konstruktive", "Part List Constructive"); string ITMHDPRT = M("Bauteil","Part"); string ITMHDPAD = M("Pad","Pad"); string ITMHDRL = M("Bohrung","Drill"); string ITMHDPIN = M("Pin","Pin"); string ITMHDMAC = M("Makro","Macro"); string ITMHDPLC = M("Platzierung","Placement"); string ITMPLCCS = M("Bauteilseite","Component Side"); string ITMPLCSS = M("Loetseite","Solder Side"); string ITMUNPLC = M("-unplatziert-","-unplaced-"); string ITMINVPLC = M("-falsches Gehaeuse-","-wrong package-"); string ITMHDLAY = M("Lage/Klasse","Layer/Class"); string ITMHDMIR = M("Spiegelung","Mirror"); string ITMHDDRL = M("Bohrung","Drill"); string ITMYES = M("ja","yes"); string ITMNO = M("nein","no"); string ITMON = M("ein","on"); string ITMOFF = M("aus","off"); #define ITMVIA " - VIA -" // General item and format strings #define ITMULINE "========================================" #define ITMELLIPS "..." #define FMTHEADUL "%.*s" #define FMTPRTH1 "%-*s %-*s %-*s" #define FMTPRTH2 "%.*s %.*s %.*s" #define FMTPLCH1 "%-*s %-*s %8s %8s Rotation %s %s" #define FMTPINH1 "%-*s %-*s %8s %8s Rotation %s %8s" #define FMTPINH2 "%.*s %.*s ======== ======== ======== %-.*s ========" #define FMTPADH2 "%-*s %.*s ======== ======== ======== %-.*s %-.*s" #define FMTPLC "%-*s %-*s %8.3f %8.3f %8.3f %s" #define FMTPAD "%-*s %-*s %8.3f %8.3f %8.3f %-*s %s" #define FMTPIND "%-*s %-*s %8.3f %8.3f %8.3f %-*s %8.3f" // Destination unit designators string UNIT = bae_getcoorddisp() ? "[\"]" : "[mm]"; // Unit designator double ITOB = baecvtl(1.0) /* Scale factor int. to BAE disp. */; // Globals double nx = bae_planwsnx()/* Plan origin X coordinate */; double ny = bae_planwsny()/* Plan origin Y coordinate */; double ux = bae_planwsux()/* Plan upper X coordinate */; double uy = bae_planwsuy()/* Plan upper Y coordinate */; double lx = bae_planwslx()/* Plan lower X coordinate */; double ly = bae_planwsly()/* Plan lower Y coordinate */; double drlrad /* Drill radius */; STRINGS headl /* Header list */; int headn = 0 /* Header count */; STRINGS entryl /* Entry list */; int entryn = 0 /* Entry count */; // Main program void main() { index L_POWLAYER pl /* Power layer index */; int class = bae_planddbclass() /* Current element class */; int mc = 0 /* Requested popup column count */; int i /* Loop variable */; // Print the plan characteristics sprintf(headl[0],REPHEADER,ddbclassname(class)); sprintf(headl[1],FMTHEADUL,strlen(headl[0]),ITMULINE); sprintf(headl[2],REPFILE,bae_planfname()); sprintf(headl[3],REPELEM,bae_planename()); sprintf(headl[4],REPSAVE,bae_plannotsaved()?ITMNO:ITMYES); sprintf(headl[5],REPORIG,ITOB*nx,ITOB*ny,UNIT); sprintf(headl[6],REPUBND,ITOB*ux,ITOB*uy,UNIT); sprintf(headl[7],REPLBND,ITOB*lx,ITOB*ly,UNIT); sprintf(headl[8],REPSIZE,ITOB*(ux-lx),ITOB*(uy-ly),UNIT); headn=9; if (class==DDBCLLAY) { if (uliptype()==ULIPAR) { sprintf(headl[headn],REPRSIZE,getmatsize()); headn++; } sprintf(headl[headn],REPTOPLAY,lay_plantoplay()+1); headn++; sprintf(headl[headn],REPBTWLAY,lay_planmidlaycnt()); headn++; } // Evaluate the plan class switch (class) { // Layout case DDBCLLAY : // Print the power layer list forall (pl where pl.CNET.NAME!="") { // Print the power layer info sprintf(headl[headn],REPPOWLAY,pl+1,pl.CNET.NAME); headn++; } // Print the checking parameters chkparams(); // Print the layout part list partlist(); break; // Part case DDBCLLPRT : // Print the checking parameters chkparams(); // Print the part pin list pinlist(); break; // Padstack case DDBCLLSTK : // Print the pad and drill info paddrilllist(); break; } // Get the maximum line length for (i=headn-1;i>=0;i--) mc=maxint(mc,strlen(headl[i])+1); for (i=entryn-1;i>=0;i--) mc=maxint(mc,strlen(entryl[i])+1); // Activate the report popup menu bae_setintpar(16,4027); popupmenu(0,"",headl,headn,entryl,entryn, "",0,0,1,headn+entryn+2,mc,0,""); } // Data retrieval routines void chkparams() /* // Append the checking parameters at list */ { string blkname /* Block name */; double ttdist /* Distance trace to trace */; double tcdist /* Distance trace to copper */; double ccdist /* Distance copper to copper */; double twidth /* Trace default width */; int layer /* Layer number */; int blk /* DRC block number */; int lastblk = (-1) /* Last documented DRC block number */; // Store the checking parameters header sprintf(headl[headn],REPCHKHD); headn++; // Loop while valid blocks found blk=0; while (1) { // Get the all layer parameters ttdist=(-1.0); lay_getplanchkparam( ttdist,tcdist,ccdist,twidth,blkname,(-1),blk); if (ttdist==(-1.0)) break; if (blkname!="" && blk!=lastblk) { sprintf(headl[headn],REPCHKBLK,blk,blkname); headn++; lastblk=blk; } sprintf(headl[headn],REPCHKEN,blk,layername(-1),ITOB*ttdist, UNIT,ITOB*tcdist,UNIT,ITOB*ccdist,UNIT,ITOB*twidth,UNIT); headn++; // Get the top layer parameters ttdist=(-1.0); lay_getplanchkparam( ttdist,tcdist,ccdist,twidth,blkname,(-5),blk); if (ttdist!=(-1.0) && (ttdist!=0.0 || tcdist!=0.0 || ccdist!=0.0 || twidth!=0.0)) { sprintf(headl[headn],REPCHKEN,blk,layername(-5), ITOB*ttdist,UNIT,ITOB*tcdist,UNIT, ITOB*ccdist,UNIT,ITOB*twidth,UNIT); headn++; } // Get the middle layer parameters ttdist=(-1.0); lay_getplanchkparam( ttdist,tcdist,ccdist,twidth,blkname,(-6),blk); if (ttdist!=(-1.0) && (ttdist!=0.0 || tcdist!=0.0 || ccdist!=0.0 || twidth!=0.0)) { sprintf(headl[headn],REPCHKEN,blk,layername(-6), ITOB*ttdist,UNIT,ITOB*tcdist,UNIT, ITOB*ccdist,UNIT,ITOB*twidth,UNIT); headn++; } // Loop for all signal layers for (layer=0;layer=0;i--) mc=maxint(mc,strlen(headl[i])+1); for (i=entryn-1;i>=0;i--) mc=maxint(mc,strlen(entryl[i])+1); // Activate the popup menu; get part list request bae_setintpar(16,4028); if ((uinput=popupmenu(5,"",headl,headn,entryl,entryn, UINPOPABORT,0,0,1,headn+entryn+2,mc,0,""))=="" || uinput==UINPOPABORT) // Abort request break; // "Allocate" the part list plnam[pn]=""; plmac[pn]=""; plplc[pn]=""; // Re-init the part count pn=0; // Init the output field lengths lnam=strlen(ITMHDPRT); lmac=strlen(ITMHDMAC); forall (mac where mac.CLASS==DDBCLLPRT) lmac=maxint(lmac,strlen(mac.NAME)); lplc=strlen(ITMINVPLC); // Print part scan message bae_prtdialog(REPSCNPRT); // Test if unplaced connection parts list requested if (uinput==UPRPARTLA || uinput==UPRPARTLU) { // Get the unplaced connection list parts forall (cpart where (cpart.USED&CPART_PLC)==0) { // Abort on request if (kbhit()) { getchr(); abort=1; break; } // Store the part info plnam[pn]=cpart.NAME; plmac[pn]=cpart.PLNAME; plplc[pn]=ITMUNPLC; pn++; // Update the output field lengths lnam=maxint(lnam,strlen(cpart.NAME)); lmac=maxint(lmac,strlen(cpart.PLNAME)); } } // Get the parts list request flags listp=uinput==UPRPARTLA || uinput==UPRPARTLP; listc=uinput==UPRPARTLA || uinput==UPRPARTLC; // Test if constructive parts list requested if (!abort && (listc || listp)) { // Loop thru the placed part list forall (nref) { // Abort on request if (kbhit()) { getchr(); abort=1; break; } // Test if connection list part if (lay_findconpart(nref.NAME,cpart)) { // Constructive part if (!listc) continue; // Store the part info plnam[pn]=nref.NAME; plmac[pn]=nref.MACRO.NAME; plplc[pn]= nref.MIRROR ? ITMPLCSS : ITMPLCCS; pn++; // Update output field lengths lnam=maxint(lnam,strlen(nref.NAME)); } else { // Placed con. part if (!listp) continue; // Store the part info plnam[pn]=cpart.NAME; plmac[pn]=cpart.PLNAME; plplc[pn]=(nref.MACRO.NAME!=cpart.PLNAME) ? ITMINVPLC : (nref.MIRROR ? ITMPLCSS : ITMPLCCS); pn++; // Update the output field lengths lnam=maxint(lnam,strlen(cpart.NAME)); lmac=maxint(lmac,strlen(cpart.PLNAME)); } } } // Complete the header sprintf(headl[headn],FMTPRTH1, lnam,ITMHDPRT,lmac,ITMHDMAC,lplc,ITMHDPLC); sprintf(headl[headn+1],FMTPRTH2, lnam,ITMULINE,lmac,ITMULINE,lplc,ITMULINE); headn+=2; // Build the part entry list entryl[pn]=""; entryn=0; for (i=0;i>DRLCSHFT2)-1+'A')) : class; // Print the drill info sprintf(entryl[entryn],FMTPAD,ltyp,ITMHDRL, lmac,dia,ITOB*(d.X-nx),ITOB*(d.Y-ny),0.0,lmir,ITMOFF, class+" / "+mclass); entryn++; } } // Entry list routines void newentry(string entrystr) /* // Store a new entry string to the entry list // Parameters : // string entrystr : Entry string */ { int slb = 0 /* Search lower boundary */; int sub = entryn-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 entry found; update the search area if ((compres=numstrcmp(entrystr,entryl[sidx]))<0) sub=sidx-1; else slb=sidx+1; } // Insert new entry string to sorted entry list for (sidx=entryn;sidx>slb;sidx--) entryl[sidx]=entryl[sidx-1]; entryl[slb]=entrystr; entryn++; } int drillfunc(index L_DRILL drill,double x,double y, int drillinws,int tree,index L_LEVEL level) /* // Scan and store a new drill to unsorted drill list // Return value : // zero if done or (-1) on file error // Parameters : // index L_DRILL drill : Drill data block // double x : Drill X coordinate // double y : Drill Y coordinate // int drillinws : Drill in workspace flag // int tree : Drill tree number // index L_LEVEL level : Drill level */ { // Get the max. drill radius if (drill.RAD>drlrad) drlrad=drill.RAD; // Return without errors return(0); } string getmatsize() /* // Get the routing matrix size // Return value : // Size string */ { string sizemsg /* Size report string */; double bmsize /* Matrix base size */; double rsize /* Routing matrix size */; double lx,ly,ux,uy /* Board outline boundaries */; index L_POLY poly /* Polygon index */; index L_POINT point /* Point index */; index L_POWLAYER powlay /* Power layer index */; index L_FIGURE fig /* Figure list index */; int laycnt /* Total routing layer count */; int res /* Routing resolution */; double grid /* Routing grid */; int bfound = 0 /* Board outline found flag */; string nettype /* Net type */; int nettypeflag = 0 /* Net type routing area found flag */; int bitmaskflag = 0 /* Bitmask routing area found flag */; // Loop for polygons (board outline is always first polygon) forall (poly) { // Check if board outline if (poly.TYP==L_POLYBRDOUT) { // Loop for polygon points bae_clearpoints(); forall (point of poly) // Store point to internal list bae_storepoint(point.X,point.Y,point.TYP); // Get the polygon range bae_getpolyrange(lx,ly,ux,uy); bfound=1; } break; } if (!bfound) return(REPNOBOUTLINE); forall (fig where fig.TYP==L_FIGPOLY && fig.RULEOBJID>=0) { poly=fig.POLY; if (poly.TYP==L_POLYDOCAREA && poly.LAYER==LAYERALL && lay_rulequery(RS_OCFIG,fig, RS_PCBSUBJ,RS_NETTYPE,"?s",nettype)>0 && nettype!="") { nettypeflag=1; break; } } forall (fig where fig.TYP==L_FIGPOLY && fig.RULEOBJID>=0) { poly=fig.POLY; if (poly.TYP==L_POLYDOCAREA && lay_rulequery(RS_OCFIG,fig, RS_PCBSUBJ,RS_POLYROUTBITM,"?d",0)>0) { bitmaskflag=1; break; } } // Get signal layer count if (ar_getintpar(5,laycnt)!=0) laycnt= lay_plantoplay()==1 ? (lay_planmidlaycnt()+2) : (lay_plantoplay()+1); // Add power layer count forall (powlay where powlay.CNET.NAME!="") laycnt++; ar_getintpar(6,res); switch (res) { /* 1/20" */ case 0 : grid=0.0254/20.0; break; /* 1/40" */ case 1 : case 6 : grid=0.0254/40.0; break; /* 1/50" */ case 2 : grid=0.0254/50.0; break; /* 1/60" */ case 3 : case 7 : grid=0.0254/60.0; break; /* 1/80" */ case 4 : case 8 : grid=0.0254/80.0; break; /* 1/100" */ case 5 : case 9 : grid=0.0254/100.0; break; // User defined grid default : ar_rutgetdist(4,grid); } // Check if halfgrid routing if (ar_rutsetpar(31,-1)==2) grid*=0.5; // Get the base bitmap size bmsize=(ux-lx)*(uy-ly)/(grid*grid); // Store routing matrix size rsize=laycnt*bmsize; // Add net type area matrix size if (nettypeflag) rsize+=laycnt*bmsize; // Add bitmask area matrix size if (bitmaskflag) rsize+=laycnt*bmsize; // Add gridless routing control matrix size if (ar_rutsetpar(36,-1)>=2) rsize+=bmsize; // Determine size units if (rsize<1000000.0) sprintf(sizemsg,"%.1f KB",rsize/1000.0); else if (rsize<1000000000.0) sprintf(sizemsg,"%.1f MB",rsize/1000000.0); else sprintf(sizemsg,"%.1f GB",rsize/1000000000.0); // Return size string return(sizemsg); } // User Language program end