/* ICAPNET (LAY) -- ICAP logical Netlist Conversion */ /* ICAPNET (LAY) -- ICAP logische Netzliste einlesen */ /* // Copyright (c) 2001-2012 Oliver Bartels F+E, Muenchen // Author: Roman Ludwig // 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 (060220) ENHANCEMENT: // Applied net name character check. // 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 (011120) ORIGINAL CODING. // // DESCRIPTION // // The icapnet User Language program is used for transferring // logical (i.e. unpacked) netlist data from ICAP/4 schematic // (version 8.2.10 / 1843 or higher) exported in TANGO format to internal // Bartels AutoEngineer format ready for processing with the BAE Packager. // icapnet reads the netlist data from the selected netlist file // ".net" and stores the netlist to DDB file // ".ddb" using the element name specified in the // netlist file (default "netlist"). The logical netlist generated // by icapnet may be translated to a physical netlist using the // Packager. In the subsequent layout process it will be possible // to perform pin/gate swaps according to the logical library swap // commands transferred by the Packager. // icapnet generates 1:1 pin assignment logical definitions for parts // with missing logical definitions in the default layout library. // Netlist transfer process messages, warnings, and error messages // are listed both to the screen and to a logfile named "bae.log". // After successfully tranferring the netlist, netconv automatically // starts the Packager. */ // Includes #include "pop.ulh" // User Language popup utilities // Disable undo state request #pragma ULCALLERNOUNDO // Messages string REPHD0 = M("ICAPNET -- Logical Netlist Conversion Utility", "ICAPNET -- Logical Netlist Conversion Utility"); string REPHD1 = M("ASCII-Netzliste ....: '%s'", "ASCII Netlist .....: '%s'"); string REPHD2 = M("DDB-Zieldatei ......: '%s'", "DDB Design File ...: '%s'"); string REPHD3 = M("Netzliste ..........: '%s'", "Netlist ............: '%s'"); string REPCONV = M("Uebernahme Logische ASCII-Netzliste '%s'...", "Converting Logical ASCII Netlist '%s'..."); string REPDEFLOG = M("Erzeugen logische Bibliotheksdefinition '%s'...", "Creating logical library definition. '%s'.."); string REPREADSTOP = M("Abbruch ohne Veraenderung der Projektdatenbank!", "Stopped, the project file was not modified!"); string REPWRPART = M("Speichern Netzlisten-Bauteil '%s'...", "Storing netlist part '%s'..."); string REPWRCON = M("Schreiben Netzliste '%s'...", "Writing netlist '%s'..."); string REPWRATTR = M("Speichern Attribute fuer Bauteil '%s'...", "Storing attributes for part '%s'..."); string UPRCONLIST = M("Netzlistendatei ? ","Netlist File ? "); string WRNDEFLOG = M("WARNUNG: Logischer Bibliothekseintrag '%s' konnte nicht definiert werden!\n", "WARNING: Could not define logical library entry '%s'!\n"); string ERRWRPART = M("Fehler beim Speichern des Bauteils '%s'!", "Error storing part '%s'!"); string ERRWRPIN = M("Fehler beim Speichern des Bauteilpins '%s'/'%s'!", "Error storing part '%s' pin '%s'!"); string ERRWRCON = M("Fehler beim Speichern der Netzliste!", "Error storing the netlist!"); string ERRWRATTR = M("Fehler beim Speichern von Bauteil/Attribut '%s'!", "Error storing part/attribute '%s'!"); string ERRNONET = M("Netzliste ist leer!","Netlist is empty!"); string ERRNETOVFL = M("Netzlisten Ueberlauf (mehr als %s Netze)!", "Netlist overflow (more than %s nets)!"); string ERRNETNAME = M("Netzname '%s' enthaelt ungueltige Zeichen!", "Net name '%s' contains invalid characters!"); string ERRMULPART = M("Bauteil '%s' mehrfach definiert", "Part '%s' multiple defined"); string ERRUDPART = M("Bauteil '%s' nicht deklariert", "Part '%s' not declared"); string ERRMULPIN = M("Bauteil '%s' Pin '%s' mehrfach angeschlossen", "Part '%s' pin '%s' multiple connected"); string ERRIDENTLEN = M("Identifier '%s' ist zu lang", "Identifier '%s' is too long"); string ERRFORMAT = M("Zeile %4d : FEHLER: %s!", "Line %4d : ERROR: %s!"); // Logical library definitions struct llpdes { // Logical library part descriptor string llname /* Logical library name */; string plname /* Physical library name */; } llpl[] /* Logical library part list */; int llpn = 0 /* Logical library part count */; // Connection part list definitions struct pindes { // Pin descriptor int pinconnum /* Pin con. number */; string pinname /* Pin name */; }; struct partdes { // Part descriptor string pname /* Part name */; string pllname /* Part log. library name */; string pplname /* Part phys. library name */; struct pindes ppinl[] /* Part pin list */; int ppinn /* Part pin count */; } cpartl[] /* Part list */; int cpartn = 0 /* Part count */; int inspartidx /* Insert part index */; // Connection tree list definitions struct condes { // Connection descriptor string ctreename /* Connection tree name */; int ctreenum /* Connection tree number */; int ctreepincnt /* Connection tree pin count */; }; struct condes ctreel[] /* Connection tree list */; int ctreen = 0 /* Connection tree count */; int cnamecount = 1 /* Connection name counter */; int nexttreenum /* Next valid tree number */; int instreeidx /* Insert tree index */; // Part selection data string curpartname /* Current part name */; string curllname /* Current logical library name */; string curplname /* Current physical library name */; // Connection read data string curconname /* Current connection name */; string curconpart /* Current connection part */; string curconpin /* Current connection pin */; int curconknown /* Current con. known flag */; int curconnum /* Current connection number */; int curconidx /* Current con. list index */; int curpinidx /* Current pin index */; int curpartidx /* Current part index */; // Current tree pin list struct pinrefdes { // Pin reference descriptor int partidx /* Part list index */; int pinidx /* Part pin list index */; } pinrefl[] /* Current tree pin ref. list */; int pinrefn /* Current tree pin ref. count */; // Scanned data buffers string curstr /* Current string */; // Globals #define CONEXT ".net" // Con. list file name extension #define DFLTNETL "netlist" // Default netlist name string confname /* Connection list file name */; string scmfname /* SCM project file name */; string planname = DFLTNETL /* SCM project element name */; string msgbuf /* Message buffer */; STRINGS hl /* Report list */; int hn = 0 /* Report count */; STRINGS msgl /* Message list */; int msgn = 0 /* Message count */; // Main program void main() { // Save current element with verification on request verifysave(); bae_clriactqueue(); if (bae_plannotsaved()) bae_storetextiact(1,"n"); bae_callmenu(9005); // Select the connection list file if (bae_askfilename(confname,CONEXT,UPRCONLIST) || confname=="") error_abort(); // Build the layout file name scmfname=convstring(confname,0)+DDBEXT; // Read the connection list message(REPCONV,confname); readcon(); // List report header hl[5]=hl[1]=""; hl[0]=REPHD0; sprintf(hl[2],REPHD1,confname); sprintf(hl[3],REPHD2,scmfname); sprintf(hl[4],REPHD3,planname); hn=6; // Define the logical library entries deflogparts(); // Test if any errors occurred if (msgn) { // Error occurred hl[hn++]=REPREADSTOP; hl[hn++]=""; // Display messages with popup menu bae_setintpar(16,5041); popupmenu(0,"",hl,hn,msgl,msgn, UINPOPABORT,0,-1,-1,hn+msgn+2,100,0,""); // Abort return; } // Write the connectivity entry writecon(); // Set project file name bae_setplanfname(scmfname); // Start packager bae_callmenu(9009); } void readcon() /* // Read the connections list // Return value : // zero if done or (-1) on error */ { // Init the scaling factors ([mm] and [Degree]) // Clear the connection state clrcon(); // Parse the connections file parsefile(confname); // Test if any non-fatal errors occured if (msgn) return; } void writecon() /* // Write the connectivity to the layout file */ { string partname /* Part name */; struct pindes pl[] /* Part pin list */; int pn /* Part pin count */; int i,j /* Loop control variables */; // Clear the internal connection list con_clear(); // Store the parts for (i=0;i=inspartidx;i--) cpartl[i+1]=cpartl[i]; // Store the part to the list cpartl[inspartidx]=part; // Return without errors return(0); } void updatepins(int contreeidx) /* // Store the current connection tree data, set the con. num. known flag // Update all previously stored pins // Parameters : // int contreeidx : Connection tree index */ { int i /* Loop control variable */; // Set the connection index and number curconidx=contreeidx; curconnum=ctreel[contreeidx].ctreenum; // Update all cur. tree pin list pins for (i=0;i=instreeidx;i--) ctreel[i+1]=ctreel[i]; ctreel[instreeidx]=con; // Return the con. index return(instreeidx); } int findcon(string conname) /* // Search a name specified connection // Return value : // tree list index or (-1) if not found // Parameters : // string conname : Name of connection searched */ { int slb = 0 /* Search lower boundary */; int sub = ctreen-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(conname,ctreel[sidx].ctreename))==0) // Part found return(sidx); // Update the search area if (compres<0) sub=sidx-1; else slb=sidx+1; } // Store the insert part index instreeidx=slb; // Part not found return(-1); } int findpin(string partname,string pinname,int partidx) /* // Search a name specified pin // Return value : // pin list index or (-1) if not found // Parameters : // string partname : Name of part searched // string pinname : Name of pin searched // int partidx : Part index */ { struct pindes pl[] /* Pin name list buffer */; int pn /* Pin name count buffer */; int sidx /* Search index */; // Search the part descriptor if ((partidx=findpart(partname))<0) // Part not found return(-1); // Get the pin name list buffer pl=cpartl[partidx].ppinl; pn=cpartl[partidx].ppinn; for (sidx=0;sidx>1; // Test if part found if ((compres=strcmp(partname,cpartl[sidx].pname))==0) { inspartidx=sidx; // Part found return(sidx); } // Update the search area if (compres<0) sub=sidx-1; else slb=sidx+1; } // Store the insert part index inspartidx=slb; // Part not found return(-1); } void deflogparts() /* // Define the logical library part entries // Return value : // zero if done or (-1) on error */ { string libname /* Default layout library name */; string llname /* Logical library name */; string rlname /* Requested logical library name */; string lastllname = "" /* Last logical library name */; string logdef /* Logical library definition */; int i /* Loop control variables */; // Get library file name libname=strgetvarfilename(lay_deflibname()); catext(libname,DDBEXT); // Store all logical library entries for (i=0;i=0) // Done return; // Insert new logical library entry to list llpn++; for (i=(llpn-1)-1;i>=insidx;i--) llpl[i+1]=llpl[i]; llpl[insidx].llname=llname; llpl[insidx].plname=plname; } int findllp(string llname,string plname,int insidx=(-1)) /* // Search a name specified logical library part // Return value : // logical part list index or (-1) if not found // Parameters : // string llname : Logical lib. part name // string plname : Physical lib. part name // int insidx=(-1) : List insert index */ { int slb = 0 /* Search lower boundary */; int sub = llpn-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 logical part found if ((compres=strcmp(plname,llpl[sidx].plname))==0) if ((compres=strcmp(llname,llpl[sidx].llname))==0) // Logical library entry found return(sidx); // Update the search area if (compres<0) sub=sidx-1; else slb=sidx+1; } // Set the list insert index insidx=slb; // Logical part not found return(-1); } // Error handling routines void prterr(string errmsg,string erritem) /* // Handle any program errors // Parameters : // string errmsg : Error message string // string erritem : Error item string */ { // Include the error item sprintf(msgbuf,errmsg,erritem); // Print the error message sprintf(msgl[msgn++],ERRFORMAT,synscanline(),msgbuf); } /*________________________________________________________________*/ #bnf { // Connection list BNF syntax definition // Whole file wholefile : tango EOF ; // TANGO compatible connection list syntax tango : tango_parts tango_cons ; tango_parts : tango_parts tango_part | ; tango_part : "[" partname plname llname "]" (p_storepart) ; tango_cons : tango_cons tango_con | ; tango_con : "(" conname tango_pins ")" (p_storecon) ; tango_pins : tango_pins tango_pin | tango_pin | ; tango_pin : partname "," pinname (p_storepin) | partname "-" pinname (p_storepin) | partname "@" "-" pinname (p_storepin) ; // General connection list syntax expressions llname : alnumstr (p_llname) ; plname : alnumstr (p_plname) ; partname : alnumstr (p_partname) ; conname : alnumstr (p_conname) ; pinname : alnumstr (p_pinname) ; // String expressions alnumstr : IDENT (p_name) | NUMBER (p_name) | SQSTR (p_name) | DQSTR (p_name) | UNKNOWN (p_name) | "-" (p_name) ; // BNF definition end } /*________________________________________________________________*/ // Scanner/parser functions void parsefile(string fn) /* // Parse an input file // Parameters : // string fn : File name */ { // Parser error messages STRINGS ERRS = { "", M("(synparsefile) Keine BNF-Definition verfuegbar!", "(synparsefile) No BNF definition available!"), M("(synparsefile) Parser ist bereits aktiv!", "(synparsefile) Parser already active!"), M("(synparsefile) Fehler beim Oeffnen der Datei '%s'!", "(synparsefile) Error opening file '%s'!"), M("(synparsefile) Zu viele offene Dateien!", "(synparsefile) Too many open files!"), M("[%s/%d] Fataler Lese-/Schreibfehler!", "[%s/%d] Fatal read/write error!"), M("[%s/%d] Scan Item '%s' zu lang!", "[%s/%d] Scan item '%s' too long!"), M("[%s/%d] Syntaxfehler bei '%s' (unerwartetes Symbol)!", "[%s/%d] Syntax error at '%s' (unexpected symbol)!"), M("[%s/%d] Dateiende erreicht!", "[%s/%d] Unexpected end of file!"), M("[%s/%d] Stackueberlauf (BNF zu komplex)!", "[%s/%d] Stack overflow (BNF too complex)!"), M("[%s/%d] Stackunterlauf (BNF fehlerhaft)!", "[%s/%d] Stack underflow (BNF erroneous)!"), M("[%s/%d] Fehler von Parser Aktion/Funktion!", "[%s/%d] Error from parse action function!"), M("(synparsefile) Unbekannter Fehlercode %d!", "(synparsefile) Unknown error code %d!") }; int status /* Parser status */; string msg /* Error message */; // Parse the input file and evaluate the parser status synscaneoln(0); if ((status=synparsefile(fn))==0) // No error return; if (status>=arylength(ERRS)) sprintf(msg,ERRS[arylength(ERRS)-1],status); else sprintf(msg,ERRS[status], fn,synscanline(),synscanstring()); // Print the error message error(msg); } // Parser action routines int p_storepart() /* // Store the current part // Return value : // zero if done or (-1) on error */ { // Store the current part if (storenewpart(curpartname,curllname,curplname)) return(-1); // Return without errors return(0); } int p_storepin() /* // Receive the pin component of a connection // Return value : // zero if done or (-1) on error */ { // Search the pin descriptor if (preppincon()) // Pin error, ignore this pin return(0); // Test the connection state if (curconknown) { // Store the known connection number ctreel[curconidx].ctreepincnt++; cpartl[curpartidx].ppinl[curpinidx].pinconnum=curconnum; } else { // Store the pin within the cur. tree pin list // Mark this pin as used cpartl[curpartidx].ppinl[curpinidx].pinconnum=(-2); // Allocate a new list element pinrefn++; // Store the pin pinrefl[pinrefn-1].pinidx=curpinidx; pinrefl[pinrefn-1].partidx=curpartidx; } // Return without errors return(0); } int p_storecon() /* // Handle the connection end // Return value : // zero if done or (-1) on error */ { int ci /* Cur. con. index */; // Test if a con. name was assigned if (!curconknown && pinrefn>0) { // Assign a system name if ((ci=getcon(""))==(-1)) { // Out of memory return(-1); } // Store the current con. tree data // Update the previously stored pins updatepins(ci); } // Clear the connection state clrcon(); // Return without errors return(0); } int p_llname() /* // Receive the logical library part name // Return value : // zero if done or (-1) on error */ { // Store the logical library part name curllname=curstr; curstr=""; // Return without errors return(0); } int p_plname() /* // Receive the physical library part name // Return value : // zero if done or (-1) on error */ { // Store the physical library part name curplname=curstr; curstr=""; // Return without errors return(0); } int p_partname() /* // Receive the part name // Return value : // zero if done or (-1) on error */ { // Store the part name curpartname=curstr; // Store the part name as current connection part name curconpart=curstr; curstr=""; // Return without errors return(0); } int p_pinname() /* // Receive the pin component of a connection // Return value : // zero if done or (-1) on error */ { // Store the pin name curconpin=curstr; // Return without errors return(0); } int p_conname() /* // Receive the connection name // Return value : // zero if done or (-1) on error */ { int ci /* Cur. con. index */; // Test if the con. num. was already assigned if (curconknown) return(-1); // Store the connection name curconname=curstr; // Get the connection index if ((ci=getcon(curconname))==(-1)) { // Out of memory return(-1); } // Store the current con. tree data // Update the previously stored pins updatepins(ci); // Return without errors return(0); } int p_name() /* // Handle name data // Return value : // zero if done or (-1) on error */ { // Check the identifier length if (strlen(synscanstring())>MAXKEYLEN) // Identifier too long prterr(ERRIDENTLEN,synscanstring()); // Store the current string curstr=synscanstring(); // Convert it to lowercase strlower(curstr); // Return without errors return(0); } // User Language program end