/* -*-c-*- */ %{ /* * scan_spice.lpp - scanner for a Spice netlist * * Copyright (C) 2004-2009 Stefan Jahn * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, * Boston, MA 02110-1301, USA. * * $Id$ * */ #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-register" #endif #if HAVE_CONFIG_H # include #endif #include #include #include #include #ifdef __MINGW32__ #include #endif #ifdef HAVE_UNISTD_H #include #endif #include "check_spice.h" #include "parse_spice.hpp" #if !HAVE_STRCHR # define strchr index # define strrchr rindex #endif /* fixing invalid identifiers */ static void spice_fix_identifier (char * ident) { char * p; for (p = ident; *p != '\0'; p++) switch (*p) { case '+': *p = 'P'; break; case '-': *p = 'N'; break; case '/': *p = '_'; break; } } %} WS [ \t\n\r] TITLE [* \t0-9A-Za-z][A-Za-z0-9\- \t;#:=()/\.,*\\]*\r*\n SPACE [ \t] NAME [A-Z][A-Z0-9]* IDENT [A-Za-z_][A-Za-z0-9_\-/]* IDENT2 [A-Za-z0-9_][A-Za-z0-9_\-/]* FILE [/A-Za-z0-9_][/\\:A-Za-z0-9_\.]* DIGIT [0-9] EXPONENT [Ee][+-]?{DIGIT}+ INT [+-]?{DIGIT}+ FLOAT1 [+-]?{DIGIT}+{EXPONENT} FLOAT2 [+-]?{DIGIT}*"."{DIGIT}+({EXPONENT})? FLOAT3 [+-]?{DIGIT}+"." NUMBER ({INT}|{FLOAT1}|{FLOAT2}|{FLOAT3}){SFX}?{UNIT}? SFX ([tT]|[gG]|[mM]|[kK]|[uU]|[nN]|[pP]|[fF]|[mM][iI][lL]|[mM][eE][gG]) UNIT ([sS]|[vV]|[aA]|[oO][hH][mM]|[mM][hH][oO]|[fF]|[hH]) NODE ([A-Za-z0-9_#\+-]+|[\+]|[-]) EOL \r*\n CSFX [A-Za-z0-9_]* /* Source functions */ FUN1 ([dD][eE][cC]|[lL][iI][nN]|[oO][cC][tT]|[dD][cC]|[aA][cC]) FUN2 ([sS][iI][nN]|[pP][uU][lL][sS][eE]|[pP][wW][lL]|[eE][xX][pP]) FUN3 ([dD][iI][sS][tT][oO][fF][12]) FUNCTION ({FUN1}|{FUN2}|{FUN3}) /* Device Models */ MODEL1 ([rR]|[cC]|[sS][wW]|[cC][sS][wW]|[uU][rR][cC]|[lL][tT][rR][aA]) MODEL2 ([dD]|[nN][pP][nN]|[pP][nN][pP]|[nN][jJ][fF]|[pP][jJ][fF]) MODEL3 ([nN][mM][oO][sS]|[pP][mM][oO][sS]|[nN][mM][fF]|[pP][mM][fF]) MODEL4 ([rR][eE][sS]|[vV][sS][wW][iI][tT][cC][hH]) MODEL ({MODEL1}|{MODEL2}|{MODEL3}|{MODEL4}) /* Voltage derivatives */ VFUN ([vV]|[vV][rR]|[vV][iI]|[vV][mM]|[vV][pP]|[vV][dD][bB]) /* Options specials */ OPT1 ([aA][cC][cC][tT]|[lL][iI][sS][tT]|[nN][oO][mM][oO][dD]) OPT2 ([nN][oO][pP][aA][gG][eE]|[nN][oO][dD][eE]|[oO][pP][tT][sS]) OPT3 ([tT][rR][yY][tT][oO][cC][oO][mM][pP][aA][cC][tT]) OPT4 ([kK][eE][eE][pP][oO][pP][iI][nN][fF][oO]|[bB][aA][dD][mM][oO][sS]3) OPT5 ([pP][oO][sS][tT]|[tT][rR][aA][nN][sS]) OPTS ({OPT1}|{OPT2}|{OPT3}|{OPT4}|{OPT5}) /* Model specific properties */ MOD1 ([nN][oO][cC][oO][nN][tT][rR][oO][lL]) MOD2 ([sS][tT][eT][pP][lL][iI][mM][iI][tT]) MOD3 ([qQ][uU][aA][dD][iI][nN][tT][eE][rR][pP]) MOD4 ([nN][oO][pP][rR][iI][nN][tT]) MODS ({MOD1}|{MOD2}|{MOD3}|{MOD4}) /* Plot/Print specific identifiers */ SIM1 ([aA][cC]|[dD][cC]|[tT][rR][aA][nN]|[nN][oO][iI][sS][eE]) SIM2 ([dD][iI][sS][tT][oO]|[pP][zZ]) SIMS ({SIM1}|{SIM2}) /* MOS specific device properties */ MOS1 ([lL]|[wW]|[aA][dDsS]|[pP][dDsS]|[nN][rR][dDsS]|[dD][eE][bB][uU][gG]) MOS2 ([rR][gG][eE][oO][mM][oO][dD]|[tT][sSdD]|[mM]) MOS ({MOS1}|{MOS2}) /* analog behavioural */ TABLE [tT][aA][bB][lL][eE] VALUE [vV][aA][lL][uU][eE] FREQ [fF][rR][eE][qQ] LAPLACE [lL][aA][pP][lL][aA][cC][eE] POLY [pP][oO][lL][yY] %x COMMENT IVREF DEVPROP LREF MODREF1 MODREF2 IGNORE FUNREF FILEREF VREF %x STARTUP VSINGLE ISWITCH VSWITCH CONTROL GEVALS INLINE SUBCKT TLPROP RLCPROP %x FHVALS %option yylineno noyywrap nounput noinput prefix="spice_" %% ^{TITLE} { /* detect initial title lines */ spice_lval.str = strdup (spice_text); BEGIN(STARTUP); return TitleLine; } ^{SPACE}+ { /* Spice3 ignores any lines starting spaces */ BEGIN(COMMENT); } ^"*" { /* ignored region begins here */ BEGIN(COMMENT); } [\*\$] { /* ignored inline region begins here (3f5, 2g6 and hspice) */ BEGIN(INLINE); } ^"."[cC][oO][nN][tT][rR][oO][lL] { /* control (interactive) region start */ BEGIN(CONTROL); } . { /* skip any character in here */ } {EOL} { /* skip any character in here */ } ^"."[eE][nN][dD][cC] { BEGIN(STARTUP); } \x1a { /* skip EOF character */ } ^"."[sS][uU][bB][cC][kK][tT] { /* subcircuit definition start */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(SUBCKT); return SUBCKT_Action; } ^"."[eE][nN][dD][sS] { /* subcircuit definition end */ BEGIN(SUBCKT); return ENDS_Action; } ^[rRlLcC]{CSFX} { /* R, L and C instances */ spice_lval.ident = strdup (spice_text); BEGIN(RLCPROP); return RLC_Device; } ^[kK]{CSFX} { /* Mutual inductor instances */ spice_lval.ident = strdup (spice_text); BEGIN(LREF); return K_Device; } ^[iIvV]{CSFX} { /* voltage and current source instances */ spice_lval.ident = strdup (spice_text); BEGIN(FUNREF); return IV_Source; } ^[gGeE]{CSFX} { /* voltage controlled source instances */ spice_lval.ident = strdup (spice_text); BEGIN(GEVALS); return GE_Source; } ^[fFhH]{CSFX} { /* current controlled source instances */ spice_lval.ident = strdup (spice_text); BEGIN(FHVALS); return FH_Source; } ^[bB]{CSFX} { /* non-linear dependent source instances */ spice_lval.ident = strdup (spice_text); BEGIN(IGNORE); return B_Source; } ^[xX]{CSFX} { /* subcircuit instances */ spice_lval.ident = strdup (spice_text); BEGIN(STARTUP); return X_Device; } ^[oO]{CSFX} { /* lossy transline */ spice_lval.ident = strdup (spice_text); BEGIN(STARTUP); return O_Device; } ^[tT]{CSFX} { /* lossless transline */ spice_lval.ident = strdup (spice_text); BEGIN(TLPROP); return T_Device; } ^[uU]{CSFX} { /* distributed lossy transline */ spice_lval.ident = strdup (spice_text); BEGIN(STARTUP); return U_Device; } ^[sS]{CSFX} { /* voltage controlled switch */ spice_lval.ident = strdup (spice_text); BEGIN(VSWITCH); return S_Device; } ^[wW]{CSFX} { /* current controlled switch */ spice_lval.ident = strdup (spice_text); BEGIN(ISWITCH); return W_Device; } ^"."[mM][oO][dD][eE][lL] { /* device Model definitions */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(MODREF1); return MODEL_Action; } ^"."[tT][rR][aA][nN] { /* transient analysis */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(STARTUP); return TRAN_Action; } ^"."[pP][lL][oO][tT] { /* plotting action */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(IVREF); return PLOT_Action; } ^"."[aA][cC] { /* AC analysis */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(FUNREF); return AC_Action; } ^"."[dD][iI][sS][tT][oO] { /* distortion analysis */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(FUNREF); return DISTO_Action; } ^"."[nN][oO][dD][eE][sS][eE][tT] { /* nodeset functionality */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(VSINGLE); return NODESET_Action; } ^"."[iI][cC] { /* nodeset functionality */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(VSINGLE); return NODESET_Action; } ^"."[dD][cC] { /* DC analysis */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(IVREF); return DC_Action; } ^"."[oO][pP] { /* operating point analysis */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(STARTUP); return OP_Action; } ^"."[tT][eE][mM][pP] { /* temperature analysis (Spice 2g6) */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(STARTUP); return TEMP_Action; } ^"."[pP][rR][iI][nN][tT] { /* printing action */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(VREF); return PRINT_Action; } ^"."[oO][pP][tT][iI][oO][nN][sS] { /* general options */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(STARTUP); return OPTIONS_Action; } ^"."[oO][pP][tT] { /* general options (abbrev.) */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(STARTUP); return OPTIONS_Action; } ^"."[oO][pP][tT][iI][oO][nN] { /* general options (abbrev.) */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(STARTUP); return OPTIONS_Action; } ^"."[wW][iI][dD][tT][hH] { /* special width of ??? */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(STARTUP); return WIDTH_Action; } ^"."[nN][oO][iI][sS][eE] { /* noise analysis */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(IVREF); return NOISE_Action; } ^"."[iI][nN][cC][lL][uU][dD][eE] { /* file include */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(FILEREF); return INCLUDE_Action; } ^"."[pP][zZ] { /* pole-zero analysis */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(STARTUP); return PZ_Action; } ^"."[sS][aA][vV][eE] { /* save line */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(IGNORE); return SAVE_Action; } ^"."[sS][eE][nN][sS] { /* sensitivity analysis */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(IGNORE); return SENS_Action; } ^"."[tT][fF] { /* transfer function analysis */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(IGNORE); return TF_Action; } ^"."[fF][oO][uU][rR] { /* fourier analysis */ spice_lval.ident = strdup (&spice_text[1]); BEGIN(IGNORE); return FOUR_Action; } [cC][uU][rR]|[vV][oO][lL] { /* pole-zero specials */ spice_lval.ident = strdup (spice_text); return CurVol; } [pP][oO][lL]|[zZ][eE][rR]|[pP][zZ] { /* other pole-zero specials */ spice_lval.ident = strdup (spice_text); return PoleZero; } {FILE} { /* a file reference */ spice_lval.ident = strdup (spice_text); return File; } [aA][lL][lL] { /* a print special */ spice_lval.ident = strdup (spice_text); return ALL_Special; } [tT][cC] { /* a TC special */ spice_lval.ident = strdup (spice_text); return TC_Special; } [oO][fF][fF] { /* a device special */ spice_lval.ident = strdup (spice_text); return OFF_Special; } [oO][nN] { /* a device special */ spice_lval.ident = strdup (spice_text); return ON_Special; } [iI][cC] { /* another device special */ spice_lval.ident = strdup (spice_text); return IC_Special; } [tT][eE][mM][pP] { /* another device special */ spice_lval.ident = strdup (spice_text); return TEMP_Special; } {MOS} { /* another device special */ spice_lval.ident = strdup (spice_text); return MOS_Special; } {VFUN} { /* voltage derivatives (plotting and printing) */ spice_lval.ident = strdup (spice_text); return VoltFunc; } [vV] { /* voltage derivatives (plotting and printing) */ spice_lval.ident = strdup (spice_text); return VoltFunc; } {OPTS} { /* option specials */ spice_lval.ident = strdup (spice_text); return Options; } {MODS} { /* Model specials */ spice_lval.ident = strdup (spice_text); return ModelProps; } [vV]{CSFX} { /* voltage source references */ spice_lval.ident = strdup (spice_text); return V_Source; } [iI]{CSFX} { /* current source references */ spice_lval.ident = strdup (spice_text); return I_Source; } [iI] { /* I function (plotting and printing) */ spice_lval.ident = strdup (spice_text); return CurrFunc; } {SIMS} { /* print/plot specific identifiers */ spice_lval.ident = strdup (spice_text); return SIM_Type; } [lL]{CSFX} { /* inductor references */ spice_lval.ident = strdup (spice_text); return L_Device; } ^[dD]{CSFX} { /* diode instances */ spice_lval.ident = strdup (spice_text); BEGIN(DEVPROP); return Diode_Device; } ^[qQ]{CSFX} { /* BJT instances */ spice_lval.ident = strdup (spice_text); BEGIN(DEVPROP); return Bipolar_Device; } ^[jJ]{CSFX} { /* JFET instances */ spice_lval.ident = strdup (spice_text); BEGIN(DEVPROP); return JFET_Device; } ^[mM]{CSFX} { /* MOSFET instances */ spice_lval.ident = strdup (spice_text); BEGIN(DEVPROP); return MOSFET_Device; } ^[zZ]{CSFX} { /* MESFET instances */ spice_lval.ident = strdup (spice_text); BEGIN(DEVPROP); return MESFET_Device; } "."[Ee][Nn][Dd]{SPACE}*{EOL}* { /* identify end of netlist */ return End; } {DIGIT}+ { /* identify node (containing digits) */ spice_lval.ident = strdup (spice_text); return Digits; } {NUMBER} { /* identify float (any kind) */ spice_lval.ident = strdup (spice_text); return Floats; } {POLY} { /* identify analog behaviour */ spice_lval.ident = strdup (spice_text); return Behave; } {TABLE}|{VALUE}|{FREQ}|{LAPLACE} { /* identify analog behaviour */ spice_lval.ident = strdup (spice_text); BEGIN(IGNORE); return Behave; } {FUNCTION} { /* function specials (e.g. in sources) */ spice_lval.ident = strdup (spice_text); return Function; } {MODEL} { /* Model specification specials */ spice_lval.ident = strdup (spice_text); BEGIN(STARTUP); return MODEL_Spec; } {IDENT} { /* arbitrary identifier */ spice_lval.ident = strdup (spice_text); spice_fix_identifier (spice_lval.ident); return Identifier; } {IDENT2} { /* arbitrary identifier */ spice_lval.ident = strdup (spice_text); spice_fix_identifier (spice_lval.ident); BEGIN(STARTUP); return Identifier; } {IDENT2} { /* arbitrary identifier */ spice_lval.ident = strdup (spice_text); spice_fix_identifier (spice_lval.ident); BEGIN(MODREF2); return Identifier; } [vV]{CSFX}#[bB][rR][aA][nN][cC][hH] { /* I function (plotting and printing) */ spice_lval.ident = strdup (spice_text); return BranchFunc; } @[a-zA-Z]{CSFX}\[[a-zA-Z]{CSFX}\] { /* operating point (plotting and printing) */ spice_lval.ident = strdup (spice_text); return OpFunc; } {NODE} { /* identify node */ spice_lval.ident = strdup (spice_text); return Nodes; } {EOL} { /* detect end of line */ BEGIN(STARTUP); return Eol; } <*>{SPACE}|{EOL}+\+|[()=,] { /* skip spaces, '=', '(', ')', ',' and the leading '+' */ } {EOL} { BEGIN(STARTUP); /* skipping ends here */ } . { /* skip any character in here */ } . { /* skip any character in here */ } {EOL} { BEGIN(STARTUP); return Eol; /* skipping ends here */ } . { /* skip any character in here */ } <*>. { /* skip any character in here */ } <*>. { /* any other character is invalid */ fprintf (stderr, "line %d: syntax error, unrecognized character: `%s'\n", spice_lineno, spice_text); return InvalidCharacter; } %%