/* EDF20CON (LAY) -- EDIF 2.0 Netlist Data Import */ /* EDF20CON (LAY) -- EDIF 2.0 Netzliste importieren */ /* // Copyright (c) 1999-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 (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 (060220) ENHANCEMENT: // Applied net name character check. // rl (050906) RELEASED FOR BAE V6.6. // rl (040811) RELEASED FOR BAE V6.4. // rl (040513) ENHANCEMENT: // Added pin/part attribute list configuration through bae.ini. // 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 (010409) ENHANCEMENT: // Added optional parameter settings from bae.ini file. // rl (000829) RELEASED FOR BAE V4.6. // rl (991222) ADAPTED TO BAE V4.4 // rl (990728) ENHANCEMENT: // Added extended attribute processing. // rl (990222) ORIGINAL CODING. // // DESCRIPTION // // The edf20con User Language program converts a EDIF data file // to BAE format. Logical library definitions are generated automatically. // The edf20con User Language program is used for transferring // physical (i.e. packed) netlist data from different EDIF 2.0 // format to internal Bartels AutoEngineer format ready for // processing with the BAE Packager. // edf20con is tested with ORCAD-EDIF output only. Output from other // schematic entries may require changes to edf20con. // edf20con reads the netlist data from the selected netlist file // ".edn" and stores the netlist to DDB file // ".ddb" using the element name specified in // the netlist file (on default the LAYDEFELEMENT name defined // with the bsetup utility program is used!). Subsequently the // Packager must be used to translate the (pseudo-physical) // logical netlist generated by edf20con to a true physical // netlist ready for layout. For consistency checks edf20con // requires access to the pin lists of the part symbols referenced // from the netlist. Layout part symbol info is loaded either from // the destination project file (".ddb") or from the // currently selected layout library. Required part symbols not yet // defined in the project file will be automatically copied from // the library file. // edf20con performs automatic generation of synthetic logical library // entries subsequently required by the Packager (part/package assignments // with 1:1 pin mapping). 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, edf20con recommends to run the Packager. // If the net list contains net specific attributes loglib must be run // with the route definition file on the layout library used for the // packager. // // Special property names for attributes: // pcb_footprint : Part library macro name // rwidth : Net/Pin routing width // rdist : Net routing distance // prioritaet/priorit„t : Net routing priority */ // Includes #include "pop.ulh" // User Language popup utilities #include "baeparam.ulh" // User Language BAE param. access #include "lay.ulh" // User Language layout utilities // Disable undo state request #pragma ULCALLERNOUNDO // Messages string REPHD0 = M("EDF20CON -- Physical Netlist Conversion Utility", "EDF20CON -- Physical 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/Layout ...: '%s'", " Netlist/Layout ....: '%s'"); string REPHD4 = M(" Layoutbibliothek ...: '%s'", " Layout Library ....: '%s'"); string REPCONV = M("Uebernahme ASCII-Netzliste '%s'...", "Converting ASCII Netlist '%s'..."); string REPFILCONV = M("Konvertieren Netzlistendatei...", "Converting net list file..."); string REPCONDONE = M("Netzliste erfolgreich umgesetzt.", "Netlist successfully transferred."); string REPRUNPACK = M("Bitte PACKAGER-Lauf durchfuehren!", "Please run PACKAGER!"); string REPREADSTOP = M("Abbruch ohne Veraenderung der Projektdatenbank!", "Stopped, the project file was not modified!"); string REPRDPART = M("%d.Lesen Bauteil '%s'...","%d.Reading part '%s'..."); string REPRDNET = M("%d.Lesen Netz '%s'...","%d.Reading net '%s'..."); 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 REPDEFLOG = M("Erzeugen Logische Bibliotheksdefinitionen...", "Creating logical library definitions..."); string UPRCONLIST = M("Netzlistendatei ? ","Netlist File ? "); string UPRUSESTDLIB = M("Standard-Bibliothek '%s' benutzen ? ", "Use standard Library '%s' ? "); string UPRUSECURLIB = M("Aktuelle Bibliothek '%s' benutzen ? ", "Use current Library '%s' ? "); string UPRLIBRARY = M("Layout Bibliothek ? ","Layout Library ? "); string WRNLIBCOPY = M("WARNUNG: Gehaeuse '%s' konnte nicht kopiert werden!\n", "WARNING: Could not copy library part '%s'!\n"); string WRNDEFLOG = M("WARNUNG: Logischer Bibliothekseintrag '%s' konnte nicht definiert werden!\n", "WARNING: Could not define logical library entry '%s'!\n"); string ERRTMPWRITE = M("Fehler beim Schreiben der Temporaerdatei!", "Error writing temporary file!"); string ERRNETOPEN = M("Netzliste-Eingabedatei kann nicht geoeffnet werden!", "Couldn't open net list file!"); string ERRLIBACC = M("Fehler beim Zugriff auf Bibliotheksdatei '%s'!", "Error accessing library file '%s'!"); string ERRLOADPART = M("Fehler beim Laden des Bauteils '%s'!", "Error loading library part '%s'!"); 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 ERRPMISLIB = M("Bauteil '%s': Gehaeuse nicht definiert!", "Part '%s' : Package not defined!"); string ERRMISLIB = M("Gehaeuse '%s' nicht in Bibliothek '%s'", "Library part '%s' not found in library '%s'"); string ERRMISPIN = M("Bauteil '%s' Gehaeuse '%s' Pin '%s' undefiniert", "Part '%s' package '%s' pin '%s' undefined"); string ERRMISPKG = M("Bauteil '%s' kein Gehaeuse definiert", "Part '%s' no package specified"); string ERRMISPART = M("Bauteil '%s' nicht gefunden", "Part '%s' not found"); string ERRMULPIN = M("Bauteil '%s' Pin '%s' mehrfach angeschlossen. Netze '%s'/'%s'", "Part '%s' pin '%s' multiple connected. Nets '%s'/'%s'"); string ERRMULATT = M("Bauteil '%s' Attribut '%s' mehrfach definiert ('%s'<>'%s'", "Part '%s' attribute '%s' multiple defined ('%s'<>'%s'"); string ERRMULPATT = M("Bauteil '%s' Pin '%s' Attribut '%s' mehrfach definiert", "Part '%s' pin '%s' attribute '%s' multiple defined"); string ERRMULREF = M("Mehrfachreferenzen auf Bloecke nicht unterstuetzt(%s'", "Multiple block references not supported ('%s')"); string ERRFORMAT = M("Zeile %4d : FEHLER: %s!", "Line %4d : ERROR: %s!"); // INI file parameter name definitions #define PAR_EDFCSINGP "EDFCSINGP_LAY" // Connect single pins flag #define PAR_EDFCCHKLIB "EDFCCHKLIB_LAY" // Check log. libr. overwrite #define PAR_EDFCFEXT "EDFCFEXT_LAY" // Netlist file name extension #define PAR_EDFCTMPF "EDFCTMPF_LAY" // Temporary file name #define PAR_EDFCTMPC "EDFCTMPC_LAY" // Temporary file name conv. #define PAR_EDFCLOCN "EDFCLOCN_LAY" // Block local nets all. flag #define PAR_EDFCGNCN "EDFCGNCN_LAY" // Global net aux. cell name #define PAR_EDFCATTRWM "EDFCATTRWM_LAY" // routwidth macro name #define PAR_EDFCATTPWM "EDFCATTPWM_LAY" // powwidth macro name #define PAR_EDFCATTMDM "EDFCATTMDM_LAY" // mindist macro name #define PAR_EDFCATTPRM "EDFCATTPRM_LAY" // priority macro name #define PAR_EDFCATTRWN "EDFCATTRWN_LAY" // routwidth part name pattern #define PAR_EDFCATTPWN "EDFCATTPWN_LAY" // powwidth part name pattern #define PAR_EDFCATTMDN "EDFCATTMDN_LAY" // mindist part name pattern #define PAR_EDFCATTPRN "EDFCATTPRN_LAY" // priority part name pattern #define PAR_EDFCATTRWA "EDFCATTRWA_LAY" // routwidth attribute name #define PAR_EDFCATTPWA "EDFCATTPWA_LAY" // powwidth attribute name #define PAR_EDFCATTMDA "EDFCATTMDA_LAY" // mindist attribute name #define PAR_EDFCATTPRA "EDFCATTPRA_LAY" // priority attribute name #define PAR_EDFCATTTYA "EDFCATTTYA_LAY" // type attribute name #define PAR_EDFCATTPRW "EDFCATTPRW_LAY" // Pin routwidth attr. name #define PAR_EDFCATTRWP "EDFCATTRWP_LAY" // routwidth pin name #define PAR_EDFCATTPWP "EDFCATTPWP_LAY" // powwidth pin name #define PAR_EDFCATTMDP "EDFCATTMDP_LAY" // mindist pin name #define PAR_EDFCATTPRP "EDFCATTPRP_LAY" // priority pin name #define PAR_EDFCPROPPL1 "EDFCPROPPL1_LAY" // 1st phys.lib. property name #define PAR_EDFCPROPPL2 "EDFCPROPPL2_LAY" // 2nd phys.lib. property name #define PAR_EDFCPROPRW "EDFCPROPRW_LAY" // routwidth property name #define PAR_EDFCPROPPW "EDFCPROPPW_LAY" // powwidth property name #define PAR_EDFCPROPMD "EDFCPROPMD_LAY" // mindist property name #define PAR_EDFCPROPPR "EDFCPROPPR_LAY" // priority property name #define PAR_EDFCPROPPRW "EDFCPROPPRW_LAY" // Pin routwidth property name #define PAR_EDFPARTPL "EDFPARTPL_STD" // Part property trans. list #define PAR_EDFPINPL "EDFPINPL_STD" // Pin property trans. list // Global definitions int CONSINGLEPIN = bae_iniintval(PAR_EDFCSINGP,1) /* Connect single pins */; int CHECKOVERWRITELLIB = bae_iniintval(PAR_EDFCCHKLIB,0) /* Check logical libr. overwrite */; string CONEXT = bae_inistrval(PAR_EDFCFEXT,".edn") /* Netlist file name extension */; string TMPFILE = bae_inistrval(PAR_EDFCTMPF,"edifcon.pxx") /* Temporary file name */; int TMPFLAG = bae_iniintval(PAR_EDFCTMPC,1) /* Temporary file conversion flag */; int LOCALNET = bae_iniintval(PAR_EDFCLOCN,0) /* Block local nets allowed flag */; string GLOBNET = bae_inistrval(PAR_EDFCGNCN,"netglobal") /* Global net aux. cell name */; #define MULNETPAT "%s___%d" // Multiple net name ref. pattern // Attribute definitions struct attrdes { // Attribute descriptor string name /* Attribute name */; string value /* Attribute value */; }; struct attrdes defpinattrl[] = { // Default pin attribute property list { "nettype", "$nettype" } }; struct attrdes pinattrl[] /* Pin attribute property list */; int pinattrn /* Pin attribute property count */; struct attrdes defpartattrl[] = { // Default part attribute property list { "value", "$val" }, { "comment", "$val" }, { "tol", "$tol" }, { "volts", "$volts"}, { "desc", "$desc" }, { "attribute", "$attribute"} }; struct attrdes partattrl[] /* Part attribute property list */; int partattrn /* Part attribute property count */; struct attrdes pendattrl[] /* Pending attribute property list */; int pendattrn = 0 /* Pending attributes count */; // Scanner variables string curid /* Current identifier */; string curstrval /* Current string value */; string curcellname /* Current cell name */; string curcellref="" /* Current cell reference */; string curinstrefname /* Current instance ref. name */; string curinstname /* Current instance name */; string curplname /* Cur. physical lib. part name */; string curpropname /* Current property name */; string curportinstname="" /* Current port instance name */; string curconname /* Current connection name */; string curconpart /* Current connection part */; string curconpin /* Current connection pin */; int curconnum /* Current connection number */; int curconidx /* Current con. list index */; int curpinidx /* Current pin index */; int curpartidx /* Current part index */; int curportrefflag /* Current port reference flag */; int curview=0 /* Current view state */; string topcell /* Top level cell name */; string namestk[] /* Current name stack */; int namestkn=0 /* Current name stack count */; // Physical library definitions struct plpdes { // Physical lib. part descriptor string plname /* Physical library name */; STRINGS plpinl /* Pin name list */; int plpinn /* Pin count */; } plpl[] /* Physical library part list */; int plpn = 0 /* Physical library part count */; int insplpidx /* Ins. physical lib. part index */; // Logical library definitions struct llpdes { // Logical library part descriptor string llname /* Logical library name */; STRINGS plnames /* Physical library name list */; int plnamen /* Physical library name count */; } llpl[] /* Logical library part list */; int llpn = 0 /* Logical library part count */; // Connection part list definitions struct pindes { // Pin descriptor double pinrwidth /* Pin routing width */; int pinconnum /* Pin con. number */; int plpinidx /* Physical library pin index */; struct attrdes attl[] /* Pin attribute list */; int attn /* Pin attribute count */; }; struct partdes { // Part descriptor string pname /* Part name */; int plpidx /* Physical library part index */; struct pindes ppinl[] /* Part pin list */; int ppinn /* Part pin count */; struct attrdes attl[] /* Part attribute list */; int attn /* Part attribute count */; } cpartl[] /* Part list */; int cpartn = 0 /* Part count */; int inspartidx = (-1) /* Part list insert index */; string clnames[] /* Cell library names */; string cpnames[] /* Cell placement names */; int cnamen = 0 /* Cell count */; string plmisl[] /* Part library missing names */; int plmisn = 0 /* Part library missing count */; // Pin collision buffer definitions struct pincdes { // Pin collision descriptor int pinconnum1 /* Pin first con. number */; int pinconnum2 /* Pin second con. number */; string pinname /* Pin part name */; string partname /* Pin part name */; } pincl[] /* Pin collision list */; int pincn = 0 /* Pin collsion count */; // Connection tree list definitions struct condes { // Connection descriptor string ctreename /* Connection tree name */; string ctreecell /* Connection tree cell name */; int ctreenum /* Connection tree number */; int ctreeprior /* Connection tree priority */; int ctreeprev /* Connection tree prev. ent. index */; int ctreenext /* Connection tree next entry index */; int ctreehd /* Connection tree head flag */; double ctreerdist /* Connection tree distance */; double ctreerwidth /* Connection tree def. width */; double ctreepwidth /* Connection tree power width */; 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 = 0 /* Next valid tree number */; int instreeidx /* Insert tree index */; // Globals string confname /* Connection list file name */; string libfname /* Library file name */; string layfname /* Layout file name */; string layename /* Layout element name */; string msgbuf /* Message buffer */; STRINGS hl /* Report list */; int hn = 0 /* Report count */; STRINGS msgl /* Message list */; int msgn = 0 /* Message count */; // Attribute definitions string ATTRW_MACRO = bae_inistrval(PAR_EDFCATTRWM,"att_rw") /* routwidth macro name */; string ATTPW_MACRO = bae_inistrval(PAR_EDFCATTPWM,"att_pw") /* powwidth macro name */; string ATTMD_MACRO = bae_inistrval(PAR_EDFCATTMDM,"att_md") /* mindist macro name */; string ATTPR_MACRO = bae_inistrval(PAR_EDFCATTPRM,"att_pr") /* priority macro name */; string ATTRW_NPAT = bae_inistrval(PAR_EDFCATTRWN,"attrw%d") /* routwidth part name pattern */; string ATTPW_NPAT = bae_inistrval(PAR_EDFCATTPWN,"attpw%d") /* powwidth part name pattern */; string ATTMD_NPAT = bae_inistrval(PAR_EDFCATTMDN,"attmd%d") /* mindist part name pattern */; string ATTPR_NPAT = bae_inistrval(PAR_EDFCATTPRN,"attpr%d") /* priority part name pattern */; string ATTRW_ANAM = bae_inistrval(PAR_EDFCATTRWA,"$val") /* routwidth attribute name */; string ATTPW_ANAM = bae_inistrval(PAR_EDFCATTPWA,"$val") /* powwidth attribute name */; string ATTMD_ANAM = bae_inistrval(PAR_EDFCATTMDA,"$val") /* mindist attribute name */; string ATTPR_ANAM = bae_inistrval(PAR_EDFCATTPRA,"$val") /* priority attribute name */; string ATTTY_ANAM = bae_inistrval(PAR_EDFCATTTYA,"$type") /* type attribute name */; string ATTRW_PIN = bae_inistrval(PAR_EDFCATTRWP,"x") /* routwidth pin name */; string ATTPW_PIN = bae_inistrval(PAR_EDFCATTPWP,"x") /* powwidth pin name */; string ATTMD_PIN = bae_inistrval(PAR_EDFCATTMDP,"x") /* mindist pin name */; string ATTPR_PIN = bae_inistrval(PAR_EDFCATTPRP,"x") /* priority pin name */; string ATTPL_PNAM1 = bae_inistrval(PAR_EDFCPROPPL1,"pcb_footprint") /* 1st phys. library property name */; string ATTPL_PNAM2 = bae_inistrval(PAR_EDFCPROPPL2,"modulevalue") /* 2nd phys. library property name */; string ATTRW_PNAM = bae_inistrval(PAR_EDFCPROPRW,"rwidth") /* routwidth property name */; string ATTPW_PNAM = bae_inistrval(PAR_EDFCPROPPW,"pwidth") /* powwidth property name */; string ATTMD_PNAM = bae_inistrval(PAR_EDFCPROPMD,"rdist") /* mindist property name */; string ATTPR_PNAM = bae_inistrval(PAR_EDFCPROPPR,"prioritaet") /* priority property name */; string ATTRW_PANAM = bae_inistrval(PAR_EDFCATTPRW,"$routwidth") /* Pin routwidth attribute name */; string ATTRW_PPNAM = bae_inistrval(PAR_EDFCPROPPRW,"rwidth") /* Pin routwidth property name */; int ATTRW_PNUM = 0 /* routwidth part number */; int ATTPW_PNUM = 0 /* powwidth part number */; int ATTMD_PNUM = 0 /* mindist part number */; int ATTPR_PNUM = 0 /* priority part number */; struct { // Net attribute descriptor string partname /* Part name */; string pinname /* Pin name */; string macro /* Macro name */; int treeidx /* Tree index */; string attname /* Attribute name */; string attvalue /* Attribute value */; } netattl[] /* Net attribute list */; int netattn = 0 /* Net attribute count */; // Main program void main() { int jobclass /* Current job DDB class */; string jobfname /* Current job file name */; string jobename /* Current job element name */; // Save current element with verification on request verifysave(); // Store the current plan designators jobclass=bae_planddbclass(); jobfname=bae_planfname(); jobename=bae_planename(); // Select the connection list file if (bae_askfilename(confname,CONEXT,UPRCONLIST) || confname=="") error_abort(); // Build the layout file name layfname=convstring(confname,0)+DDBEXT; layename=laydefelemname(layfname); // Select the library file if (((libfname=lay_deflibname())=="" || (libfname+=DDBEXT,ddbcheck(libfname,DDBCLLPRT,"")) || (sprintf(msgbuf,UPRUSESTDLIB,libfname),!verify(msgbuf,0))) && (lay_libfname()==libfname || (libfname=lay_libfname())=="" || ddbcheck(libfname,DDBCLLPRT,"") || (sprintf(msgbuf,UPRUSECURLIB,libfname),!verify(msgbuf,0))) && (libfname=askddbfile(UPRLIBRARY,DDBCLLPRT))=="") error_abort(); // Test if the library file is valid if (ddbcheck(libfname,DDBCLLPRT,"")) errormsg(ERRLIBACC,libfname); // Get the pin attribute translation list for (pinattrn=0;pinattrn<1000;pinattrn++) { if ((pinattrl[pinattrn].name=bae_inistrval( bae_inifieldvarname(PAR_EDFPINPL,pinattrn,0),""))=="") { // Check if list defined at all if (pinattrn==0) { // Use pin attribute list pinattrl=defpinattrl; pinattrn=arylength(pinattrl); } break; } pinattrl[pinattrn].value=bae_inistrval( bae_inifieldvarname(PAR_EDFPINPL,pinattrn,1),""); } // Get the part attribute translation list for (partattrn=0;partattrn<1000;partattrn++) { if ((partattrl[partattrn].name=bae_inistrval( bae_inifieldvarname(PAR_EDFPARTPL,partattrn,0),""))=="") { // Check if list defined at all if (partattrn==0) { // Use part attribute list partattrl=defpartattrl; partattrn=arylength(partattrl); } break; } partattrl[partattrn].value=bae_inistrval( bae_inifieldvarname(PAR_EDFPARTPL,partattrn,1),""); } // Read the connection list message(REPCONV,confname); readcon(); // List report header hl[6]=hl[1]=""; hl[0]=REPHD0; sprintf(hl[2],REPHD1,confname); sprintf(hl[3],REPHD2,layfname); sprintf(hl[4],REPHD3,layename); sprintf(hl[5],REPHD4,libfname); hn=7; // 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,4024); popupmenu(0,"",hl,hn,msgl,msgn, UINPOPABORT,0,-1,-1,hn+msgn+2,100,0,""); // Abort return; } // Write the connectivity entry writecon(); // Copy the physical library parts copylibparts(); // Reload the original element if (jobclass!=DDBCLUNDEF && (jobclass!=bae_planddbclass() || jobfname!=bae_planfname() || jobename!=bae_planename())) { bae_setintpar(22,2); loadddbelem(jobfname,jobename,jobclass); } // Mention Packager run request hl[hn++]=REPCONDONE; hl[hn++]=REPRUNPACK; hl[hn++]=""; // Display messages with popup menu bae_setintpar(16,4025); popupmenu(0,"",hl,hn,msgl,msgn, UINPOPABORT,0,-1,-1,hn+msgn+2,100,0,""); // Done bae_prtdialog(""); } void readcon() /* // Read the connections list // Return value : // zero if done or (-1) on error */ { int i, j /* Loop control variables */; // Clear the connection state clrcon(); // Parse the connections file parsefile(confname); // Check the pin collisions for (i=0;i=cnamen) // Library part name missing prterr(ERRPMISLIB,plmisl[i]); } // Test if any non-fatal errors occured if (msgn) return; if (CONSINGLEPIN) // Connect all uncon. pins to synthetically generated nets connectsinglepins(); // Store the net attributes storenetattribs(); } void storenetattribs() /* // Store the net attributes */ { int i /* Loop control variable */; // Loop thru the connection list for (i=0;i0.0) newnetatt(ATTRW_NPAT,ATTRW_PNUM,ATTRW_PIN, ATTRW_MACRO,i,ATTRW_ANAM, ftoa(ctreel[i].ctreerwidth,5)); // Store powwidth if (ctreel[i].ctreepwidth>0.0) newnetatt(ATTPW_NPAT,ATTPW_PNUM,ATTPW_PIN, ATTPW_MACRO,i,ATTPW_ANAM, ftoa(ctreel[i].ctreepwidth,5)); // Store mindist if (ctreel[i].ctreerdist>0.0) newnetatt(ATTMD_NPAT,ATTMD_PNUM,ATTMD_PIN, ATTMD_MACRO,i,ATTMD_ANAM, ftoa(ctreel[i].ctreerdist,5)); // Store priority if (ctreel[i].ctreeprior>0) newnetatt(ATTPR_NPAT,ATTPR_PNUM,ATTPR_PIN, ATTPR_MACRO,i,ATTPR_ANAM,itoa(ctreel[i].ctreeprior)); } } void newnetatt(string npat,int pnum, string pin,string macro,int treeidx,string anam,string aval) /* // Store a new net attribute // Parameters : // string npat : Name pattern // int pnum : Part number // string pin : Pin name // string macro : Macro name // string tree : Tree name // string anam : Attribute name // string aval : Attribute value */ { string partname /* Part name buffer */; // Build unique part name do { sprintf(partname,npat,++pnum); } while (findpart(partname)>=0); // Store attribute definition to the net attribute list netattl[netattn].attvalue=aval; netattl[netattn].attname=anam; netattl[netattn].treeidx=treeidx; netattl[netattn].macro=macro; netattl[netattn].pinname=pin; netattl[netattn].partname=partname; netattn++; } void newpartatt(string attname,string attvalue) /* // Store the current attribute to the current part attribute list // Parameters : // string attname : Attribute name // string attvalue : Attribute value */ { int slb = 0 /* Search lower boundary */; int sub /* Search upper boundary */; int sidx /* Search index */; int compres /* Compare result */; int i /* Loop control variable */; // Check the part index if (inspartidx<0 || inspartidx>cpartn) { if (curinstname!="") { pendattrl[pendattrn].name=attname; pendattrl[pendattrn].value=attvalue; pendattrn++; } return; } // Loop until search area empty sub=cpartl[inspartidx].attn-1; while (slb<=sub) { // Get the search index sidx=(slb+sub)>>1; // Test if attribute found if ((compres=strcmp(attname, cpartl[inspartidx].attl[sidx].name))==0) { // Check if different attribute value defined if (cpartl[inspartidx].attl[sidx].value!=attvalue) { // Print the multiple definitions message sprintf(msgbuf,ERRMULATT,curconpart,attname, cpartl[inspartidx].attl[sidx].value,attvalue); prterr(msgbuf,""); } // Ignore this definition return; } // Update the search area if (compres<0) sub=sidx-1; else slb=sidx+1; } // Update the attribute ist cpartl[inspartidx].attn++; for (i=(cpartl[inspartidx].attn-1)-1;i>=slb;i--) cpartl[inspartidx].attl[i+1]=cpartl[inspartidx].attl[i]; // Insert the new attribute cpartl[inspartidx].attl[slb].value=attvalue; cpartl[inspartidx].attl[slb].name=attname; } int newpinatt(string attname,string attvalue) /* // Store the current attribute to the current pin attribute list // Return value : // zero if done or (-1) on error // Parameters : // string attname : Attribute name // string attvalue : Attribute value */ { int slb = 0 /* Search lower boundary */; int sub /* Search upper boundary */; int sidx /* Search index */; int compres /* Compare result */; int i /* Loop control variable */; // Check if pin known if (preppincon(0)) // Ignore attribute return(0); sub=cpartl[curpartidx].ppinl[curpinidx].attn-1; // Loop until search area empty while (slb<=sub) { // Get the search index sidx=(slb+sub)>>1; // Test if attribute found if ((compres=strcmp(attname, cpartl[curpartidx].ppinl[curpinidx].attl[sidx].name))==0) { // Check if different attribute value defined if (cpartl[curpartidx].ppinl[ curpinidx].attl[sidx].value!=attvalue) { // Print the multiple definitions message sprintf(msgbuf,ERRMULPATT, curconpart,curconpin,attname); prterr(msgbuf,""); } // Ignore this definition return(0); } // Update the search area if (compres<0) sub=sidx-1; else slb=sidx+1; } // Update the attribute list cpartl[curpartidx].ppinl[curpinidx].attn++; for (i=(cpartl[curpartidx].ppinl[curpinidx].attn-1)-1;i>=slb;i--) cpartl[curpartidx].ppinl[curpinidx].attl[i+1]= cpartl[curpartidx].ppinl[curpinidx].attl[i]; // Insert the new attribute cpartl[curpartidx].ppinl[curpinidx].attl[slb].value=attvalue; cpartl[curpartidx].ppinl[curpinidx].attl[slb].name=attname; // Return without errors return(0); } void writecon() /* // Write the connectivity to the layout file */ { struct partdes part /* Current part descriptor */; string partname /* Part name */; struct pindes pl[] /* Part pin list */; struct attrdes pal[] /* Part pin attribute list */; int pn /* Part pin count */; int pan /* Part pin attribute count */; int plpidx /* Physical lib. part list index */; int llpidx /* Logical lib. entry list index */; STRINGS plnames /* Phys. lib. part list */; int plnamen /* Phys. lib. part count */; STRINGS pinl /* Pin name list buffer */; string lastname /* Last net name */; string newname /* New net name */; int lastpn /* Last net pin count */; int sncnt /* Same name net count */; int i,j,k /* Loop control variables */; // Clear the internal connection list con_clear(); // Join nets lastname=""; lastpn=0; sncnt=1; for (i=0;i0) { // Assign new net name sncnt++; sprintf(newname,MULNETPAT, newname,sncnt); } } else { // Prepare scan of next name lastname=newname; sncnt=0; } // Join net names, count pins lastpn=0; for (j=i;j!=(-1);j=ctreel[j].ctreenext) { ctreel[j].ctreename=newname; lastpn+=ctreel[j].ctreepincnt; } } } // Store the parts for (i=0;i=inspartidx;i--) cpartl[i+1]=cpartl[i]; // Pre-store the physical library entry gcplp(plname); // Get the physical library part index if ((part.plpidx=findplp(plname))<0) { // Init the part pin list part.ppinn=0; // Store the part to the list cpartl[inspartidx]=part; // Abort return(0); } // Store the pin count part.ppinn=plpl[part.plpidx].plpinn; // Build the part pin list for (i=0;i=0); // Abort if netlist overflow if (cnamecount<=ovchk) errormsg(ERRNETOVFL,itoa(ovchk)); } else { // Use the given name cname=conname; // Check the name for (i=0;(c=cname[i])!='\0';i++) if (isspace(c) || iscntrl(c) || c=='~') errormsg(ERRNETNAME,cname); } // Test if this tree exists if ((conidx=findcon(cname,cmpcname))!=(-1)) // Tree exists return(conidx); // Create the new tree descriptor con.ctreepincnt=0; con.ctreenum=(ovchk=nexttreenum++); con.ctreename=cname; con.ctreecell=cmpcname; con.ctreeprior=0; con.ctreerdist=0.0; con.ctreerwidth=0.0; con.ctreepwidth=0.0; con.ctreeprev=(-1); con.ctreenext=(-1); con.ctreehd=0; // Abort if netlist overflow if (nexttreenum<=ovchk) errormsg(ERRNETOVFL,itoa(ovchk)); // Store the con. tree descriptor ctreen++; for (i=(ctreen-1)-1;i>=instreeidx;i--) ctreel[i+1]=ctreel[i]; ctreel[instreeidx]=con; // Adjust the chain pointers for (i=0;i=instreeidx) ctreel[i].ctreenext++; if (ctreel[i].ctreeprev>=instreeidx) ctreel[i].ctreeprev++; } // Adjust the attribute pointers for (i=0;i=instreeidx) netattl[i].treeidx++; // Return the con. index return(instreeidx); } int findcon(string conname,string cellname) /* // Search a name specified connection // Return value : // tree list index or (-1) if not found // Parameters : // string conname : Name of connection searched // string cellname : Name of cell 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) if ((compres= strcmp(cellname,ctreel[sidx].ctreecell))==0) // Connection 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, (-1) if pin not found or (-2) if part not found // Parameters : // string partname : Name of part searched // string pinname : Name of pin searched // int partidx : Part index */ { STRINGS pl /* Pin name list buffer */; int pn /* Pin name count buffer */; int plpidx /* Physical library part index */; int slb /* Search lower boundary */; int sub /* Search upper boundary */; int sidx /* Search index */; int compres /* Compare result */; // Search the part descriptor if ((partidx=findpart(partname))<0) // Part not found return(-2); // Get the physical library part index if ((plpidx=cpartl[partidx].plpidx)<0) // Physical library part undefined return(-3); // Get the pin name list buffer pl=plpl[plpidx].plpinl; pn=plpl[plpidx].plpinn; // Search the pin descriptor // Init. the search area variables slb=0; sub=pn-1; // Loop until search area empty while (slb<=sub) { // Get the search index sidx=(slb+sub)>>1; // Test if pin found if ((compres=strcmp(pinname,pl[sidx]))==0) // Pin found return(sidx); // Update the search area if (compres<0) sub=sidx-1; else slb=sidx+1; } // Pin not found return(-1); } int findpart(string partname) /* // Search a name specified part // Return value : // part list index or (-1) if not found // Parameters : // string partname : Name of part searched */ { int slb = 0 /* Search lower boundary */; int sub = cpartn-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(partname,cpartl[sidx].pname))==0) { // Part found inspartidx=sidx; 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); } int gcplp(string plname) /* // Get or create a physical library part entry // Return value : // physical library part index or (-1) if not in library // Parameters : // string plname : Physical library part name */ { struct plpdes plp /* Physical lib. part descriptor */; index L_NREF nref /* Named reference index */; STRINGS pinl /* Pin name list */; string ddbfname /* DDB file name */; int pinn = 0 /* Pin name count */; int i /* Loop control variables */; // Try to find the physical library part if ((i=findplp(plname))>=0) // Physical library part found return(i); // Generate a new physical library part entry plp.plpinn=0; plp.plname=plname; // Update the physical library part list plpn++; for (i=(plpn-1)-1;i>=insplpidx;i--) plpl[i+1]=plpl[i]; plpl[insplpidx]=plp; // Update the part list for (i=0;i=insplpidx) cpartl[i].plpidx++; } // Test if library part in job file if (ddbcheck(ddbfname=layfname,DDBCLLPRT,plname) && ddbcheck(ddbfname=libfname,DDBCLLPRT,plname)) { // Physical library part not found sprintf(msgbuf,ERRMISLIB,plname,ddbfname); prterr(msgbuf,""); // Ignore this part return(-1); } // Load the physical library part bae_setintpar(22,1); if (bae_loadelem(ddbfname,plname,DDBCLLPRT)==(-1)) errormsg(ERRLOADPART,plname); // Create the pin name list buffer forall (nref) pinl[pinn++]=nref.NAME; // Store the pin name list plpl[insplpidx].plpinn=pinn; plpl[insplpidx].plpinl=pinl; // Return the physical library part list index return(insplpidx); } int findplp(string plname) /* // Search a name specified physical library part // Return value : // part list index or (-1) if not found // Parameters : // string plname : Physical library part name */ { int slb = 0 /* Search lower boundary */; int sub = plpn-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(plname,plpl[sidx].plname))==0) // Part found return(sidx); // Update the search area if (compres<0) sub=sidx-1; else slb=sidx+1; } // Store the insert part index insplpidx=slb; // Part not found return(-1); } void newllibentry(string plname) /* // Store new logical library entry // Parameters : // string plname : Physical library name */ { STRINGS plnames /* Phys. lib. part list */; int plnamen = 0 /* Phys. lib. part count */; int insidx /* List insert index */; int i /* Loop control variable */; // Build the phys. lib. part list plnames[plnamen++]=plname; // Try to find the logical library entry if (findllp(plnames,plnamen,insidx)>=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].plnamen=plnamen; llpl[insidx].plnames=plnames; llpl[insidx].llname=""; } int findllp(STRINGS plnames,int plnamen,int insidx=(-1)) /* // Search a name specified logical library part // Return value : // logical part list index or (-1) if not found // Parameters : // STRINGS plnames : Phys. lib. part list // int plnamen : Phys. lib. part count // 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=compstrlists(plnames,plnamen, llpl[sidx].plnames,llpl[sidx].plnamen))==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); } int compstrlists(STRINGS sl1,int sn1,STRINGS sl2,int sn2) /* // Compare string lists // Return value : // zero if string lists equal, 1 if 1st list greater, (-1) else // Parameters : // STRINGS sl1 : String list 1 // int sn1 : String count 1 // STRINGS sl2 : String list 2 // int sn2 : String count 2 */ { int compres = 0 /* Comparison result */; int lastidx /* Last list index */; int i /* Loop control variable */; // Get the last string list index lastidx=(sn1=arylength(ERRS)) sprintf(msg,ERRS[arylength(ERRS)-1],status); else sprintf(msg,ERRS[status], parsefn,synscanline(),synscanstring()); // Print the error message error(msg); // Remove the temporary file if (TMPFLAG) remove(TMPFILE); } // Parser action routines int p_cellname() // Receive a cell name // Returns : zero if done or (-1) on error { // Get the symbol name curcellname=namestk[namestkn]; strlower(curcellname); curview=0; // Return without errors return(0); } int p_cellref() // Receive a cell reference name // Returns : zero if done or (-1) on error { // Get the symbol name curcellref=namestk[namestkn]; strlower(curcellref); // Return without errors return(0); } int p_conname() /* // Receive the connection name // Return value : // zero if done or (-1) on error */ { string msg /* Message string */; // Store the connection name curconname=namestk[namestkn]; strlower(curconname); // Build the message sprintf(msg,REPRDNET,synscanline(),curconname); // Print the message bae_prtdialog(msg); // Get the connection index if ((curconidx=getcon(curconname,curcellname))==(-1)) // Out of memory return(-1); // Store the current con. tree data curconnum=ctreel[curconidx].ctreenum; curportrefflag=0; // Return without errors return(0); } int p_conend() // Receive a connection end // Returns : zero if done or (-1) on error { int cci /* Cur. con. index */; int jci /* Join con. index */; int hci /* Head con. index */; int tci /* Tail con. index */; int sci /* Scan con. index */; int jflag = 0 /* Joined flag */; // Check if current block net is global if (LOCALNET==1 && curportrefflag==0 && curcellname!=topcell) { // Make reference to global net via aux. cell definition if ((cci=getcon(curconname,curcellname))==(-1) || (jci=getcon(curconname,GLOBNET))==(-1)) // Out of memory return(-1); if (cci==jci) jflag=1; // Scan to net tail for (tci=cci;ctreel[tci].ctreenext!=(-1); tci=ctreel[tci].ctreenext) { // Scan to net header for (sci=jci;ctreel[sci].ctreeprev!=(-1); sci=ctreel[sci].ctreeprev) if (sci==tci) { jflag=1; break; } if (jflag) break; // Scan to net tail for (sci=jci;ctreel[sci].ctreenext!=(-1); sci=ctreel[sci].ctreenext) if (sci==tci) { jflag=1; break; } } // Scan to net header for (hci=jci;ctreel[hci].ctreeprev!=(-1); hci=ctreel[hci].ctreeprev) { // Scan to net header for (sci=cci;ctreel[sci].ctreeprev!=(-1); sci=ctreel[sci].ctreeprev) if (sci==hci) { jflag=1; break; } if (jflag) break; // Scan to net tail for (sci=cci;ctreel[sci].ctreenext!=(-1); sci=ctreel[sci].ctreenext) if (sci==hci) { jflag=1; break; } } if (!jflag) { // Scan to net join header for (hci=cci;ctreel[hci].ctreeprev!=(-1); hci=ctreel[hci].ctreeprev) ; // Scan to net join tail for (tci=jci;ctreel[tci].ctreenext!=(-1); tci=ctreel[tci].ctreenext) ; // Join the tree chains ctreel[hci].ctreeprev=tci; ctreel[tci].ctreenext=hci; } } // Clear the connection state clrcon(); // Clear the symbol name field namestkn--; // Return without errors return(0); } int p_decstk() // Receive a name stack pointer decrement // Returns : zero if done or (-1) on error { namestkn--; // Return without errors return(0); } int p_ident() // Receive an identifier // Returns : zero if done or (-1) on error { // Store the current string curid=synscanstring(); // Return without errors return(0); } int p_incstk() // Receive a name stack pointer increment // Returns : zero if done or (-1) on error { namestkn++; // Return without errors return(0); } int p_instance() /* // Store the current part // Return value : // zero if done or (-1) on error */ { string msg /* Message string */; // Store the part name curconpart=namestk[namestkn]; strlower(curconpart); curinstname=curconpart; pendattrn=0; curcellref=""; curplname=""; inspartidx=(-1); // Check if top level cell if (curcellname==topcell) { // Store the instance name cpnames[cnamen]=curinstname; cnamen++; } // Build the message sprintf(msg,REPRDPART,synscanline(),curconpart); // Print the message bae_prtdialog(msg); // Return without errors return(0); } int p_instanceend() // Receive an instance end // Returns : zero if done or (-1) on error { // Check if part library name defined if (curplname=="") { // Store part now. Check against block parts later plmisl[plmisn]=curinstname; plmisn++; } curinstname=""; namestkn--; // Return without errors return(0); } int p_instanceref() // Receive an instance // Returns : zero if done or (-1) on error { curinstrefname=namestk[namestkn]; strlower(curinstrefname); // Return without errors return(0); } int p_name() // Receive a name // Returns : zero if done or (-1) on error { namestk[namestkn]=convspaces(curid); // Return without errors return(0); } int p_namedef(int typ) // Receive a name // Returns : zero if done or (-1) on error { switch (typ) { case 0 : namestk[namestkn]=convspaces(curid); break; default : namestk[namestkn]=convspaces(synscanstring()); } // Return without errors return(0); } int p_pinname() // Receive a pin name // Returns : zero if done or (-1) on error { if (curview!=1) return(0); // Get the symbol name curconpin=namestk[namestkn]; strlower(curconpin); curinstrefname=""; // Return without errors return(0); } int p_portinstance() /* // Store the current port instance // Return value : // zero if done or (-1) on error */ { // Store the port instance name curportinstname=namestk[namestkn]; strlower(curportinstname); curconpin=curportinstname; // Return without errors return(0); } int p_portinstanceend() // Receive a port instance end // Returns : zero if done or (-1) on error { curportinstname=""; curconpin=""; namestkn--; // Return without errors return(0); } int p_portrefend() // Receive a port reference end // Returns : zero if done or (-1) on error { int cci /* Cur. con. index */; int jci /* Join con. index */; int hci /* Head con. index */; int tci /* Tail con. index */; int sci /* Scan con. index */; int jflag = 0 /* Joined flag */; int i /* Loop control variable */; // Check if known connection if (curconidx<0 || curconpin=="") { curinstrefname=""; curconpin=""; namestkn--; return(0); } // Check if ordinary part pin if (curinstrefname!="" && findpart(curinstrefname)>=0) { curconpart=curinstrefname; // Search the pin descriptor if (preppincon(1)) // Pin error, ignore this pin return(0); if (curconidx!=(-1)) { // Store the known connection number ctreel[curconidx].ctreepincnt++; cpartl[curpartidx].ppinl[curpinidx].pinconnum= curconnum; } } // Check if port join else if (LOCALNET==1 && (curconname!=curconpin || (curinstrefname!="" && curinstrefname!=curcellname))) { // Check if different net names joined at this point if (curinstrefname=="") // Use current cell as instance curinstrefname=curcellname; // Transform reference name to library name for (i=0;i=0) { switch (curpropname) { case ATTPR_PNAM : ctreel[curconidx].ctreeprior=atoi(curstrval); break; case ATTMD_PNAM : // Store the connection routing distance ctreel[curconidx].ctreerdist=atof(curstrval); break; case ATTRW_PNAM : // Store the connection default routing width ctreel[curconidx].ctreerwidth=atof(curstrval); break; case ATTPW_PNAM : // Store the connection power routing width ctreel[curconidx].ctreepwidth=atof(curstrval); break; default : ; } } // Return without errors return(0); } int p_strval() // Receive a string value // Returns : zero if done or (-1) on error { curstrval=synscanstring(); // Return without errors return(0); } int p_topcell() // Receive the top level cell name // Returns : zero if done or (-1) on error { // Store the top level cell name topcell=namestk[namestkn]; strlower(topcell); // Return without errors return(0); } int p_view() // Receive a view // Returns : zero if done or (-1) on error { curview++; // Return without errors return(0); } string convspaces(string cstr) /* // Convert a spaces in string to underscores // Return value : // converted string */ { string result /* Result string */; int sidx /* String index */; // Loop for all characters result=cstr; for (sidx=strlen(result)-1;sidx>=0;sidx--) if (result[sidx]==' ') result[sidx]='_'; // Return value return(result); } // User Language program end