/* SPICESIM (SCM) -- Spice Circuit Data Output */ /* SPICESIM (SCM) -- Spice-Netzlistenausgabe */ /* // 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 (061107) ENHANCEMENT: // Added parameter attribute array support. // rl (061027) ENHANCEMENT: // Added automatic spice tool call option. // rl (060829) RELEASED FOR BAE V6.8. // rl (060421) ENHANCEMENT: // Added output file header insertion options. // rl (050915) RELEASED FOR BAE V6.6. // rl (050915) BUGFIX: // Fixed problem with multiple fixed net nodes. // rl (040811) RELEASED FOR BAE V6.4. // rl (040206) ENHANCEMENT: // Added variant attribute support. // Added secondary extra parameter attribute support. // Added fix net to node number assignment support. // rl (031001) ENHANCEMENT: // Added output of optional new parameter. // 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 (010529) ENHANCEMENT: // Added optional parameter settings from bae.ini file. // rl (010314) ORIGINAL CODING. // Derived from pspice.ulc. // // DESCRIPTION // // Netlist Conversion BAE to Spice3 // The SPICESIM User Language program creates a // Spice Circuit File Format file with file name extension // ".cir" from the netlist of the currently loaded SCM plan. // Additional commands such as ".LIB" and ".INCLUDE" for // addressing the Spice target system libraries, for defining // Simulation Control Parameters, etc. should be added to // prepare the SPICESIM output file for the Spice Simulator. //________________________________________________________________ */ /*________________________________________________________________*/ // Includes #include "pop.ulh" // User Language popup utilities #include "scm.ulh" // User Language SCM utilities // Disable undo state request #pragma ULCALLERNOUNDO // Messages string UPRABORT = M_UPRABORT(); string UPRELEMMODE = M("Bearbeitungsmodus waehlen!", "Select Element Mode!"); string UPRELEM1 = M("Gesamtes &Blatt","Whole &Sheet"); string UPRELEM2 = M("&Gruppensymbole","&Group Symbols"); string REPHD0 = M("SPICESIM -- Spice Netzlistenausgabe", "SPICESIM -- Spice Netlist Output Utility"); string REPHD1 = M("Circuit-Datei ......: '%s'", "Circuit File ......: '%s'"); string REPHD2 = M("Projektdatei .......: '%s'", "Project File ......: '%s'"); string REPHD3 = M("Schaltplanblatt ....: '%s'", "Schematic Sheet....: '%s'"); string REPHD4A = M("Gruppensymbole","Group Symbols"); string REPHD4B = M("Alle Symbole","All Symbols"); string REPDONE = M("Netzlistendaten ausgegeben ('%s').", "Net list output to '%s'."); string WRNSYMMODEL = M("Symbol '%s' ('%s') hat keine Modellzuweisung!", "Symbol '%s' ('%s') without model assignment!"); string WRNPINMODEL = M("Symbol '%s' ('%s'), Pin '%s' hat keine Indexzuweisung!", "Symbol '%s' ('%s'), Pin '%s' without index assignment!"); string WRNPINGAP = M("Symbol '%s' kein Pin zu Index %d!", "Symbol '%s' no Pin for Index %d!"); string WRNMISVAL = M("Symbol '%s' hat keinen Wert zugewiesen!", "Symbol '%s' has no value assigned!"); string ERRDIFFNODE = M("Knoten %d ist mehreren Netzen zugewiesen!", "Multiple assignments for node %d!"); string ERRNETGAP = M("Luecke in der festen Netznummernzuweisung (%d)!", "Gap in node number assignment (%d)!"); string ERRPINDBL = M("Symbol '%s' Pinindex %d doppelt belegt '%s'<->'%s'!", "Symbol '%s' Pin Index %d double usage '%s'<->'%s'!"); string ERRNOLOAD = M("Kein Schaltplan geladen!", "No Schematic loaded!"); // INI file parameter name definitions #define PAR_CIRCFEXT "CIRCFEXT_SCM" // Circuit output file name extension #define PAR_PRIMVATT "PRIMVATT_SCM" // Primary value attribute name #define PAR_SECVATT "SECVATT_SCM" // Secondary value attribute name #define PAR_ADDPATT "ADDPATT_SCM" // Additional param. attribute name #define PAR_SADDPATT "SADDPATT_SCM" // Secondary add. param. attr. name #define PAR_NODESYM "NODESYM_SCM" // Fixed node assignment symbol name #define PAR_NODEATT "NODEATT_SCM" // Fixed node assignment attr. name #define PAR_SPICEHEAD "SPICEHEAD_SCM" // Output file header specification #define PAR_AUTORUN "SPICEARUN_SCM" // Automatic simulation tool run flag #define PAR_CIRCMD "SPICECMD_SCM" // Spice simulation tool location // File extensions string CIREXT = bae_inistrval(PAR_CIRCFEXT,".cir") /* Circuit output file name ext. */; // Attribute defintions string PRIMVATT = bae_inistrval(PAR_PRIMVATT,"$val") /* Primary value attribute name */; string SECVATT = bae_inistrval(PAR_SECVATT,"$wert") /* Secondary value attribute name */; string ADDPATT = bae_inistrval(PAR_ADDPATT,"$spicepar") /* Additional parameter attr. name */; string SADDPATT = bae_inistrval(PAR_SADDPATT,"$type") /* Secondary add. param. attr. name */; string NODESYM = bae_inistrval(PAR_NODESYM,"att_nodenum") /* Fixed node assignment symbol name */; string NODEATT = bae_inistrval(PAR_NODEATT,"$node") /* Fixed node assignment attr. name */; string SPICEHEAD = bae_inistrval(PAR_SPICEHEAD,".TRAN 0.01ms 100ms") /* Output file header specification */; string CIRCOMMAND = bae_inistrval(PAR_CIRCMD,"") /* CIR file access command name */; int AUTORUN = bae_iniintval(PAR_AUTORUN,1) /* Auto. simulation tool run flag */; int netnl[] /* Net number list */; int netnn = 0 /* Net number count */; struct pindes { // Pin descriptor int idx /* Pin level index */; string name /* Pin name */; }; struct symdes { // Symbol descriptor struct pindes pl[] /* Symbol pin list */; int pn /* Symbol pin count */; struct pindes upl[] /* Symbol unspecified pin list */; int upn /* Symbol unspecified pin count */; string macname /* Symbol macro name */; string symname /* Symbol name */; string osymname /* Symbol original name */; } syml[] /* Symbol list */; int symn = 0 /* Symbol count */; string cursymname /* Current symbol name */; string cursymmacro /* Current symbol macro */; STRINGS hl /* Report list */; int hn = 0 /* Report count */; STRINGS msgl /* Message list */; int msgn = 0 /* Message count */; int varnum /* Variant number */; int fixnodenum /* Current fix node number */; /*________________________________________________________________*/ // Main program void main() { index C_FIGURE fig /* Figure list index */; index C_CNET net /* Connection list index */; int netnum /* Net number */; string jobfname /* Job file name */; string jobename /* Job element name */; string cirfname /* Circuit file name */; string incfname /* Header include file name */; string modelname /* Spice model name */; string attrval /* Attribute value */; string paramval /* Parameter value */; string nextval /* Next parameter value */; string sname /* Symbol name */; string msg /* Message buffer */; string g_dis = "," /* Group items disable */; int paridx /* Parameter value index */; int grpmode /* Group mode */; int cirfh /* Circuit file handle */; int hdfh /* Header file handle */; int pc /* Pin counter */; int c /* Character buffer */; int i,j /* Loop control variables */; // Abort if invalid plan class if (bae_planddbclass()!=DDBCLSCM) error(ERRNOLOAD); // Perform BAE Demo check with abort option BAE_Demo_check(2); // Check if element type scan if (bae_iniintval(PAR_METYPSCAN,1)==1 && !bae_peekiact()) { forall (fig where fig.GROUP) { g_dis=""; break; } } else { // Enable all menu items g_dis=""; } // Select the element mode bae_promptdialog(UPRELEMMODE); if ((grpmode=bae_askmenu(3,UPRELEM1,g_dis+UPRELEM2,UPRABORT))<0 || grpmode>1) // Abort error_abort(); // Get the plan file and element names jobfname=bae_planfname(); jobename=bae_planename(); // Query the current active variant if (cap_rulequery(3,0,RS_SCMSUBJ,RS_VARIANT,"?d",varnum)<1) // Use base variant varnum=0; // Loop for all node symbols forall (fig where fig.TYP==C_FIGNREF && fig.NREF.MACRO.NAME==NODESYM) { if ((attrval=getattribval(fig.NAME,NODEATT,0))=="") continue; fixnodenum=atoi(attrval); if (cap_scanfelem(fig,0.0,0.0,0.0,0, fixnetmacfunc,NULL,NULL,NULL)) error_scan(); } // Check fixed nodes for (i=0;i=0) { // Repetively get characters from input file while ((c=fgetc(hdfh))!=(-1)) if (fputc(c,cirfh)) break; fclose(hdfh); } fseterrmode(1); } // Loop for all selected symbols forall (fig where fig.TYP==C_FIGNREF && (grpmode==0 || fig.GROUP)) { // Check if symbol (not label) if (fig.NREF.MACRO.CLASS!=DDBCLSSYM || fig.NREF.MACRO.NAME==NODESYM) continue; cursymname=fig.NAME; cursymmacro=fig.NREF.MACRO.NAME; strupper(cursymname); strupper(cursymmacro); // Query the current symbol model if (cap_rulequery(RS_OCPOOL,fig.NREF.MACRO,RS_SCMSUBJ, RS_SPICEMODEL,"?s",modelname)<1) { sprintf(msgl[msgn],WRNSYMMODEL,cursymname,cursymmacro); msgn++; // Set unspecified model modelname="X"; } syml[symn].pn=0; if (strextract(cursymname,0,strlen(modelname)-1)==modelname) syml[symn].symname=cursymname; else syml[symn].symname=modelname+"_"+cursymname; syml[symn].macname=cursymmacro; syml[symn].osymname=fig.NAME; if (cap_scanfelem(fig,0.0,0.0,0.0,0, pinmacfunc,NULL,NULL,NULL)) error_scan(); symn++; } fprintf(cirfh,"\n* Circuit symbols\n\n",i); // Output symbol net list for (i=0;i=netnn) netnn=fixnodenum+1; // Abort scan return(0); } // Continue scan return(1); } int pinmacfunc(index C_MACRO macro,index C_POOL pool,int macinws, string refname,index C_LEVEL level,index C_LEVEL buslevel) /* // Pin macro function // Return value : // 0 if out of workspace, 1 if inside, 2 if unknown, or (-1) on error // Parameters : // index C_MACRO macro : Macro index // index C_POOL pool : Macro pool index // int macinws : Macro in workspace flag // string refname : Macro reference name // index C_LEVEL level : Macro level // index C_LEVEL buslevel : Macro bus level */ { index C_CNET net /* Net index */; int netnum /* Net number */; int netidx /* Net number index */; int pinidx /* Symbol pin index */; int upn /* Symbol unspecified pins count */; // Check if pin macro if (macro.CLASS==DDBCLSMRK) { // Search net number forall (net of level) { netnum=net.NUMBER; break; } for (netidx=0;netidx" ") { sprintf(msgl[msgn],ERRPINDBL,cursymname, pinidx,syml[symn].pl[pinidx].name,refname); msgn++; } // Store pin to symbol pin list syml[symn].pl[pinidx].idx=netidx; syml[symn].pl[pinidx].name=refname; if (pinidx>=syml[symn].pn) syml[symn].pn=pinidx+1; } // Abort scan return(0); } // Continue scan return(1); } string getattribval(string name,string attname,int nilval) /* // Get attribute value // Return value : // attribute value or empty string if not found // Parameters : // string name : Part name // string attname : Attribute name // int nilval : Nilval recognition flag */ { index C_FIGURE fig /* Figure list index */; index C_NREF part /* Part index */; index C_ATTRIBUTE att /* Attribute index */; string vattname /* Variant attribute name */; string attval /* Attribute value */; // Search part reference if (cap_nrefsearch(name,fig)!=0) return(""); part=fig.NREF; // Set default attribute value attval=nilval ? PA_NILVAL : ""; // Build the variant attribute name vattname=varattrname(attname,varnum); // Search for first attribute forall (att of part where att.NAME==vattname || att.NAME==attname) { // Check if active variant attribute if (att.NAME==vattname) // Attribute value found return(att.VALUE); // Store the base variant attribute value attval=att.VALUE; } // Return the attribute value return(attval); } // User Language program end