/* SLIBCOMP (SCM) -- Compare SCM Library Elements */ /* SLIBCOMP (SCM) -- SCM-Bibliothekselemente vergleichen */ /* // Copyright (c) 1994-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 (091021) 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 (020620) RELEASED FOR BAE V5.4. // rl (010625) RELEASED FOR BAE V5.0. // rl (010125) ENHANCEMENT: // Added class statement to loglib syntax. // rl (000509) RELEASED FOR BAE V4.6. // rl (990625) RELEASED FOR BAE V4.4. // rl (980910) RELEASED FOR BAE V4.2. // mb (980712) ENHANCEMENT: // Dynamic multi-language support introduced. // rl (970929) RELEASED FOR BAE V4.0. // mb (970422) CHANGE: // Adapted to new logical library features for defining // (pure) logical parts with the part command, and for // assigning attributes to physical pin lists using the // newattr command. // mb (960919) RELEASED FOR BAE V3.4. // mb (951103) IMPROVEMENT: // MNU mnu_poptext() function for compare report display used // instead of file output. // mb (951012) IMPROVEMENT: // Performing BAE_Demo_check(2) before starting output. // mb (95) RELEASED FOR BAE V3.2. // mb (950125) ENHANCEMENT/UPGRADE: // Introduced LOGLIB alternate plname definitions evaluation. // mb (950102) ORIGINAL CODING. // // DESCRIPTION // // slibcomp is an SCM library management utility program for // comparing selectable SCM library elements in order to // designate equivalent and/or different symbol definitions // (relating to pin naming, pin placement, pin macro usage, // logical library element assignment, etc.). The library // comparison result report is displayed in a popup menu with // file output option. */ // Includes #include "mnu.ulh" // User Language menu utilities // Disable undo state request #pragma ULCALLERNOUNDO // Messages string UPRABORT = M_UPRABORT(); string UPRPEXIT = M_UPRPEXIT(); string REPSCANLOG = M("Scannen Loglib-Datei '%s'...", "Scanning Loglib file '%s'..."); string REPCOMP = M("Vergleichen Symbol '%s'...", "Comparing symbol '%s'..."); string UPRLIB1 = M("DDB-Datei 1 ? ","DDB File 1 ? "); string UPRLIB2 = M("DDB-Datei 2 ? ","DDB File 2 ? "); string UPRPART1 = M("Bibliothek 1 Symbol(e) ? ", "Library 1 Symbol(s) ? "); string UPRPART2 = M("Bibliothek 2 ('%s') Symbol ? ", "Library 2 ('%s') Symbol ? "); string UPRCMACM = M("Makro-Check-Modus waehlen!", "Select Macro Check Mode!"); string UPRCMACN = M("&Kein Makro-Check","&No Macro Check"); string UPRCMACY = M("&Makro-Check","&Macro Check"); string UPRCLOGM = M("Loglib/DEF-Check/Report-Modus waehlen!", "Select Loglib/DEF Check/Report Mode!"); string UPRCLOGN = M("&Kein Loglib-Check","&No Loglib Check"); string UPRCLOGY = M("&Loglib-Check","&Loglib Check"); string UPRLIBDIR = M("Loglib/DEF-Bibliotheks-Verzeichnis : ", "Loglib/DEF Library Directory : "); string WRNMULELM = M("Mehrfach-Referenz '%s' ['%s' - '%s'] !", "Multiple reference '%s' ['%s' - '%s'] !"); string WRNPARSE = M("['%s' / %d] Parser-Fehler %d bei '%s' !", "['%s' / %d] Parser error %d at '%s' !"); string ERRNOSSYM = M("Kein SCM-Symbol gefunden in '%s'!", "No SCM symbol found in '%s'!"); string ERRLOAD = M("Fehler beim Laden des Symbols '%s'!", "Error loading symbol '%s'!"); string ERREQUSEL = M( "Identische Bibliothekselemente fuer Vergleich selektiert!", "Identical library elements selected for comparison!"); // Output control #define FMTCMPHD "SCM LIBRARY COMPARE REPORT" #define FMTCMPLIB1 " LIBRARY 1 ......: '%s'" #define FMTCMPLIB2 " LIBRARY 2 ......: '%s'" #define FMTCMPPART1 " PART 1 .........: '%s'" #define FMTCMPPART2 " PART 2 .........: '%s'" #define FMTMACCHECK " MACRO CHECK ....: %s" #define FMTLOGCHECK " LOGLIB CHECK ...: %s" #define FMTLOGLBDIR " LOGLIB DIR .....: '%s'" #define FMTPARTEXCL "SYMBOL %-*s EXCLUSIVE [%s] ;" #define FMTPARTEQU "SYMBOL %-*s EQUAL [%s EQ %s] ;" #define FMTPARTDIF "SYMBOL %-*s DIFFERENT [%s NE %s] :" #define FMTSPARTEQU "SYMBOL %s [%s] EQ %s [%s] ;" #define FMTSPARTDIF "SYMBOL %s [%s] NE %s [%s] :" #define FMTLOGELEM " LOGPART [%-*s : %c%-*s] (%s)" #define FMTPIN " PIN %*s" #define FMTPINMAC " [%-*s NE %-*s]" #define FMTPINCOORD " [%7.3f,%7.3f NE %7.3f,%7.3f]" #define FMTPINANG " (%7.3f NE %7.3f)" #define FMTPINMIR " <%d NE %d>" #define FMTLOGUREF "UNREFERENCED SCM SYMBOL [%-*s] (%s)" #define ITMYES "YES" #define ITMNO "NO" #define ITMEQ "EQ" #define ITMNE "NE" int MAXPARTLEN = 0 /* Max. part name length */; int MAXPINLEN /* Max. pin name length */; int MAXPINMACLEN /* Max. pin macro name length */; int MAXLPNLEN = 0 /* Max. logical part name length */; int MAXPLRLEN = 0 /* Max. physical lib. ref. length */; // Globals #define DEFEXT ".def" // Def file name extension #define DIRDEL "/" // Directory name delimiter string lib1 = "" /* Library 1 */; string lib2 = "" /* Library 2 */; string part1 = "" /* Part name 1 */; string part2 = "" /* Part name 2 */; string loglibdir /* Logical/DEF library directory */; STRINGS deffiles /* DEF file list */; int deffilen = 0 /* DEF file count */; int singlepart = 0 /* Single part check flag */; int macrocheck /* Macro check flag */; int loglibcheck /* Loglib/DEF check/report flag */; int curloglibidx /* Current loglib file index */; int curplrtyp /* Physical lib. reference type */; string curpname /* Current part name */; STRINGS curplnamel /* Cur. physical lib. name list */; int curplnamen /* Cur. physical lib. name count */; string curstr /* Current string */; STRINGS msgl /* Message list */; int msgn = 0 /* Message count */; // Library masks #define LIBMASK1 0x01 #define LIBMASK2 0x02 #define LIBMASKA LIBMASK1 | LIBMASK2 // Pysical library reference types #define PLRTYPNP 0 // Normal #define PLRTYPND 1 // Normal default #define PLRTYPMP 2 // Mainpart #define PLRTYPMD 3 // Mainpart default #define PLRTYPSP 4 // Subpart #define PLRTYPVP 5 // Virtual #define PLRTYPLP 6 // Logical STRINGS plrdef = { // Physical lib. ref. designators "NP ", // Normal "ND ", // Normal default "MP ", // Mainpart "MD ", // Mainpart default "SP ", // Subpart "VP ", // Virtual "LP " // Logical }; struct logpartdes { // Logical part descriptor string pn /* Part name */; STRINGS plnl /* Physical library name list */; int plnn /* Physical library name count */; int plrtyp /* Physical library ref. type */; int loglibidx /* Loglib file index */; }; struct logpartdes lps[] /* Logical part list */; int lpn = 0 /* Logical part count */; // Part list struct partdes { // Part descriptor string pn /* Part name */; int libmask /* Library mask */; } parts[] /* Part list */; int partn = 0 /* Part count */; struct { // Pin descriptor string n /* Pin name */; string mn1 /* Pin macro name 1 */; string mn2 /* Pin macro name 2 */; double x1,y1,a1 /* Pin 1 coordinates */; int m1 /* Pin 1 mirror mode */; double x2,y2,a2 /* Pin 2 coordinates */; int m2 /* Pin 2 mirror mode */; int diffpin /* Different pin flag */; int diffmac /* Different pin macros flag */; int diffcoord /* Different pin coordinates flag */; int diffangle /* Different pin angle flag */; int diffmir /* Different pin mirror flag */; int difflay /* Different pin layer flag */; } pins[] /* Pin list */; int pinn /* Pin count */; // Main program void main() { int jobclass /* Current element DDB class */; string jobfname /* Current element file name */; string jobename /* Current element name */; // Get current element info jobclass=bae_planddbclass(); jobfname=bae_planfname(); jobename=bae_planename(); // Save current element with verification on request verifysave(); // Select files/parts if ((lib1=askddbfile(UPRLIB1,DDBCLSSYM))=="" || (part1=askscmsym(UPRPART1,lib1))=="" || part1==UINPOPABORT || (lib2=askddbfile(UPRLIB2,DDBCLSSYM))=="" || ddbcheck(lib1,DDBCLSSYM,part1)==0 && bae_askddbename( part2,lib2,DDBCLSSYM,msgstring(UPRPART2,convstring(lib2,1)))) error_abort(); // Set second part name if (part2=="") part2=part1; else singlepart=1; // Check on identical part selection if (lib1==lib2 && part1==part2) error(ERREQUSEL); // Get macro check mode bae_promptdialog(UPRCMACM); if ((macrocheck=bae_askmenu(3,UPRCMACN,UPRCMACY,UPRABORT))<0 || macrocheck>1) error_abort(); // Get loglib/DEF check/report mode bae_promptdialog(UPRCLOGM); switch (loglibcheck=bae_askmenu(3,UPRCLOGN,UPRCLOGY,UPRABORT)) { case 0 : break; case 1 : // Ask for library directory name if ((loglibdir=askstr(UPRLIBDIR,MAXPATHLEN))!="") { // Check if abort request if (loglibdir==UINPOPABORT) error_abort(); // Build the library file lists buildfilelist(loglibdir); // Scan the logical library scanloglib(); } break; // Abort : default : error_abort(); } // Issue compare list header msgl[msgn++]=FMTCMPHD; msgl[msgn++]=""; sprintf(msgl[msgn],FMTCMPLIB1,lib1); msgn++; sprintf(msgl[msgn],FMTCMPLIB2,lib2); msgn++; sprintf(msgl[msgn],FMTCMPPART1,part1); msgn++; sprintf(msgl[msgn],FMTCMPPART2,part2); msgn++; sprintf(msgl[msgn],FMTMACCHECK,macrocheck ? ITMYES : ITMNO); msgn++; sprintf(msgl[msgn],FMTLOGCHECK,loglibcheck ? ITMYES : ITMNO); msgn++; if (loglibcheck) { sprintf(msgl[msgn],FMTLOGLBDIR,loglibdir); msgn++; } msgl[msgn++]=""; // Compare selected parts if (singlepart) // Single part comparison cmpparts(lib1,lib2,part1,part2); else // Multiple part comparison scanparts(); // Reload the original element if (jobclass!=DDBCLUNDEF && (jobclass!=bae_planddbclass() || jobfname!=bae_planfname() || jobename!=bae_planename())) { bae_setintpar(22,2); bae_loadelem(jobfname,jobename,jobclass); } // Display library comparison report with popup menu bae_setintpar(16,3055); mnu_poptext(msgl,1,1,-1,0,0); } string askscmsym(string prompt,string filename) /* // Perform a SCM symbol selection via popup menu // Return value : // name of selected element or empty string on abort // Parameters : // string prompt : Prompt string // string filename : File name */ { STRINGS headl /* Header string list */; int headn = 2 /* Header string count */; STRINGS entryl /* Entry string list */; int entryn = 0 /* Entry list */; string project = UINPOPABORT /* Project name */; string ename /* Current element name */; // Abort on DDB file access failure if (ddbcheck(filename,DDBCLSSYM,"")) errormsg(ERRNOSSYM,filename); // Define the header headl[0]=M_REPPOPDIRHD(DDBCLSSYM,filename); headl[headn-1]=""; // Set the project name if (bae_planfname()==filename && bae_planddbclass()==DDBCLSSYM) project=bae_planename(); // Scan the element name list message(M_REPSCANDDB(),filename); ename=""; while (scanddbenames(filename,DDBCLSSYM,ename)==1) // Append the element name to the menu entryl[entryn++]=ename; // Activate the popup and return the element name bae_setintpar(16,3085); return(popupmenu(1,prompt, headl,headn,entryl,entryn,project,0,0,1,0,0,0,UINPOPABORT)); } void buildfilelist(string dname) /* // Build the file name list // Parameters : // string dname : Directory name */ { // Get the def file list filelist(deffiles,deffilen,dname,DEFEXT,"",0,0,1,0,1,0); } void scanloglib() /* // Build the LOG library contents file // Return value : // zero if done or (-1) on error */ { int sts /* Status code */; // Init the logical part count lpn=0; // Loop thru the def file list synscaneoln(0); for (curloglibidx=0;curloglibidx>1; // Get and test the compare result if ((compres=numstrcmp(pn,lps[idx].pn))==0) { sprintf(msgl[msgn],WRNMULELM, pn,deffiles[curloglibidx], deffiles[lps[idx].loglibidx]); msgn++; return; } // Update the search area if (compres<0) sub=idx-1; else slb=idx+1; } // Insert the new entry to the logical part list lpn++; for (idx=lpn-2;idx>=slb;idx--) lps[idx+1]=lps[idx]; lps[slb].pn=pn; for (idx=plnn-1;idx>=0;idx--) lps[slb].plnl[idx]=plnl[idx]; lps[slb].plnn=plnn; lps[slb].plrtyp=plrtyp; lps[slb].loglibidx=curloglibidx; MAXLPNLEN=maxint(MAXLPNLEN,strlen(pn)); MAXPLRLEN=maxint(MAXPLRLEN,strlen(plrdef[plrtyp])); } void createpart(string pn,int libmask) /* // Create a part list entry // Parameters : // string pn : Part name // int libmask : Library mask */ { int idx /* Search index */; int insidx /* Insert index */; // Loop until search area empty if ((idx=findpart(pn,insidx))>=0) { // Part found; set library mask parts[idx].libmask |= libmask; // Done return; } // Insert the new entry to the part list partn++; for (idx=partn-2;idx>=insidx;idx--) parts[idx+1]=parts[idx]; parts[insidx].pn=pn; parts[insidx].libmask=libmask; MAXPARTLEN=maxint(MAXPARTLEN,strlen(pn)); } int findpart(string pn,int insidx=(-1)) /* // Find a part list entry // Return value : // part list index or (-1) if not found // Parameters : // string pn : Part name // int insidx = (-1) : Insert index */ { int slb = 0 /* Search lower boundary */; int sub = partn-1 /* Search upper boundary */; int idx /* Search index */; int compres /* Compare result */; // Loop until search area empty while (slb<=sub) { // Get the search index idx=(slb+sub)>>1; // Get and test the compare result if ((compres=numstrcmp(pn,parts[idx].pn))==0) return(idx); // Update the search area if (compres<0) sub=idx-1; else slb=idx+1; } // Part not found insidx=slb; return(-1); } void gcpin1(string pn,string pmn,double x,double y,double a,int m) /* // Get or create some pin entry // Parameters : // string pn : Pin name // string pmn : Pin macro name // double x : Pin X coordinate // double y : Pin Y coordinate // double a : Pin rotation angle // int m : Pin mirror mode */ { int slb = 0 /* Search lower boundary */; int sub = pinn-1 /* Search upper boundary */; int idx /* Search index */; int compres /* Compare result */; // Loop until search area empty while (slb<=sub) { // Get the search index idx=(slb+sub)>>1; // Get and test the compare result if ((compres=numstrcmp(pn,pins[idx].n))==0) return; // Update the search area if (compres<0) sub=idx-1; else slb=idx+1; } // Insert the new entry to the logical part list pinn++; for (idx=pinn-2;idx>=slb;idx--) pins[idx+1]=pins[idx]; pins[slb].n=pn; pins[slb].mn1=pmn; pins[slb].x1=x; pins[slb].y1=y; pins[slb].a1=a; pins[slb].m1=m; pins[slb].mn2=""; pins[slb].x2=0.0; pins[slb].y2=0.0; pins[slb].a2=0.0; pins[slb].m2=0; MAXPINLEN=maxint(MAXPINLEN,strlen(pn)); MAXPINMACLEN=maxint(MAXPINMACLEN,strlen(pmn)); } void gcpin2(string pn,string pmn,double x,double y,double a,int m) /* // Get or create some pin entry // Parameters : // string pn : Pin name // string pmn : Pin macro name // double x : Pin Xcoordinate // double y : Pin Y coordinate // double a : Pin rotation angle // int m : Pin mirror mode */ { int slb = 0 /* Search lower boundary */; int sub = pinn-1 /* Search upper boundary */; int idx /* Search index */; int compres /* Compare result */; // Loop until search area empty while (slb<=sub) { // Get the search index idx=(slb+sub)>>1; // Get and test the compare result if ((compres=numstrcmp(pn,pins[idx].n))==0) { pins[idx].n=pn; pins[idx].mn2=pmn; pins[idx].x2=x; pins[idx].y2=y; pins[idx].a2=a; pins[idx].m2=m; return; } // Update the search area if (compres<0) sub=idx-1; else slb=idx+1; } // Insert the new entry to the logical part list pinn++; for (idx=pinn-2;idx>=slb;idx--) pins[idx+1]=pins[idx]; pins[slb].n=pn; pins[slb].mn2=pmn; pins[slb].x2=x; pins[slb].y2=y; pins[slb].a2=a; pins[slb].m2=m; pins[slb].mn1=""; pins[slb].x1=0.0; pins[slb].y1=0.0; pins[slb].a1=0.0; pins[slb].m1=0; MAXPINLEN=maxint(MAXPINLEN,strlen(pn)); MAXPINMACLEN=maxint(MAXPINMACLEN,strlen(pmn)); } /*________________________________________________________________*/ // Logical library file syntax #bnf { // Loglib file loglib : "loglib" libdefs "end" "." ; libdefs : libdefs libdef | ; libdef : "delete" "part" ident ";" | "part" (p_init) ident (p_pname) ":" optclassspec partdef (p_partstore) ; // Part functions syntax optclassspec : "class" ident | ; partdef : mainflag defflag plnames partblk | "subpart" (p_subpart) ident (p_plname) partblk | "virtual" (p_virtual) virtblk | "logical" (p_logical) virtblk ; mainflag : "mainpart" (p_mainflag) | ; defflag : "default" (p_default) | ; plnames : plnames "," ident (p_plname) | ident (p_plname) ; partblk : "{" partcmds "}" | ";" ; partcmds : partcmds partcmd | partcmd ; partcmd : "bus" pinlist ";" | "net" netcmd ":" pinlist ";" | "pin" pinlist ";" | "swap" swapcmd swapblk ";" | "xlat" pinlist "to" xlats ";" | "xlat" "(" xlatpinass ")" ";" | "netattr" "priority" DQSTR ":" pinlist ";" | "netattr" "mindist" DQSTR ":" pinlist ";" | "netattr" "powwidth" DQSTR ":" pinlist ";" | "netattr" "routwidth" DQSTR ":" pinlist ";" | "netattr" idstr DQSTR ":" pinlist ";" | "newattr" DQSTR "=" DQSTR topinlist ";" | "comment" "=" DQSTR ";" ; virtblk : "{" virtcmds "}" | ";" ; virtcmds : virtcmds virtcmd | virtcmd ; virtcmd : "bus" pinlist ";" | "net" netcmd ":" pinlist ";" | "pin" pinlist ";" | "netattr" "priority" DQSTR ":" pinlist ";" | "netattr" "mindist" DQSTR ":" pinlist ";" | "netattr" "powwidth" DQSTR ":" pinlist ";" | "netattr" "routwidth" DQSTR ":" pinlist ";" | "netattr" idstr DQSTR ":" pinlist ";" | "newattr" DQSTR "=" DQSTR topinlist ";" | "call" ident ";" | "architecture" "{" synthprog "}" | "comment" "=" DQSTR ";" ; topinlist : "to" pinlist | ; netcmd : ident | "internal" ; swapcmd : "internal" | ; swapblk : "(" groups ")" | "(" gates ")" ; groups : groups "," "[" gates "]" | "[" gates "]" ; gates : gates "," gate | gate ; gate : "(" gateblk ")" | pin ; gateblk : gateblk "," gatepin | gatepin ; gatepin : pinlist | pin ; xlats : xlats "or" pinlist | pinlist ; xlatpinass : xlatpinass "," xlpindef | xlpindef ; xlpindef : "(" pin "," xlpins ")" ; xlpins : xlpins "," pin | pin ; synthprog : synthprog sprogcmd | sprogcmd ; sprogcmd : "part" ident "(" preqpinlist ")" ";" ; preqpinlist : preqpinlist "," preqpinass | preqpinass ; preqpinass : pin ":" preqdest ; preqdest : pin | "net" ident | "net" "&" ident | "&" ident ; pinlist : "(" pins ")" ; pins : pins "," pin | pin ; pin : identpt | identpt "-" identpt optstep ; optstep : ":" NUMBER | ; // Identifier expression ident : IDENT (p_ident) | NUMBER (p_ident) | SQSTR (p_ident) | DQSTR (p_ident) ; identpt : identpt idpiece | '/' idpiece | idpiece ; idpiece : IDENT | NUMBER | SQSTR | DQSTR | '.' ; idstr : IDENT | DQSTR ; } // BNF end /*________________________________________________________________*/ // Parser action routines int p_init() /* // Handle the init request // Return value : // zero if done, or nonzero on error */ { // Init the states curplrtyp=PLRTYPNP; curpname=""; curplnamen=0; // Return without errors return(0); } int p_partstore() /* // Handle the part store request // Return value : // zero if done, or nonzero on error */ { int i /* Loop control variable */; // Abort program on request if (kbhit()) { getchr(); if (verify(UPRPEXIT,0)) error_abort(); } // Store the part strlower(curpname); for (i=0;i