diff --git a/examples/soa/bjt-soa.cir b/examples/soa/bjt-soa.cir index a2a155389..f5da0072a 100644 --- a/examples/soa/bjt-soa.cir +++ b/examples/soa/bjt-soa.cir @@ -1,4 +1,6 @@ SOA check for bipolar +* LTSPICE or PSPICE compatability must be enabled to correctly parse the +* model below, for example with "set ngbehavior=psa" in .spiceinit. Vce c 0 -1 Ib b 0 -1u diff --git a/examples/sp/137mhz_bpf.s2p b/examples/sp/137mhz_bpf.s2p new file mode 100644 index 000000000..26590f41e --- /dev/null +++ b/examples/sp/137mhz_bpf.s2p @@ -0,0 +1,102 @@ +# HZ S RI R 50 +1.07000000000000000000e+08 +9.10612811414344691663e-01 -4.13169361932556822303e-01 +3.58748396996190531752e-03 +7.90670646175397305588e-03 +3.58748396996190531752e-03 +7.90670646175397305588e-03 +9.10612811414344691663e-01 -4.13169361932556822303e-01 +1.07600000000000000000e+08 +9.08235089938359885231e-01 -4.18357965192380332198e-01 +3.87160175700515963443e-03 +8.40506184306095451009e-03 +3.87160175700515963443e-03 +8.40506184306095451009e-03 +9.08235089938359885231e-01 -4.18357965192380332198e-01 +1.08200000000000000000e+08 +9.05749587403653522166e-01 -4.23698325415379828396e-01 +4.18204303082422238630e-03 +8.94004890380398729854e-03 +4.18204303082422238630e-03 +8.94004890380398729854e-03 +9.05749587403653522166e-01 -4.23698325415379883907e-01 +1.08800000000000000000e+08 +9.03148132734517106179e-01 -4.29199802742280811518e-01 +4.52173719143059496539e-03 +9.51491234400438264107e-03 +4.52173719143059496539e-03 +9.51491234400438264107e-03 +9.03148132734517106179e-01 -4.29199802742280811518e-01 +1.09400000000000000000e+08 +9.00421705997276333733e-01 -4.34872530176818039571e-01 +4.89400500260515122081e-03 +1.01332414163138578161e-02 +4.89400500260515122081e-03 +1.01332414163138578161e-02 +9.00421705997276222710e-01 -4.34872530176818039571e-01 +1.10000000000000000000e+08 +8.97560326671087205241e-01 -4.40727493499846412206e-01 +5.30262050968193648925e-03 +1.07990126939620512125e-02 +5.30262050968193648925e-03 +1.07990126939620512125e-02 +8.97560326671087205241e-01 -4.40727493499846467717e-01 +1.10600000000000000000e+08 +8.94552923981059566749e-01 -4.46776620978363570025e-01 +5.75188437592742858595e-03 +1.15166388420669847659e-02 +5.75188437592742858595e-03 +1.15166388420669847659e-02 +8.94552923981059566749e-01 -4.46776620978363570025e-01 +1.11200000000000000000e+08 +8.91387185874491061455e-01 -4.53032884216226061636e-01 +6.24671105749824082110e-03 +1.22910243042241851263e-02 +6.24671105749824082110e-03 +1.22910243042241851263e-02 +8.91387185874491061455e-01 -4.53032884216226061636e-01 +1.11800000000000000000e+08 +8.88049382462717695752e-01 -4.59510411684503461416e-01 +6.79273281927252579881e-03 +1.31276289546426536831e-02 +6.79273281927252579881e-03 +1.31276289546426536831e-02 +8.88049382462717584730e-01 -4.59510411684503461416e-01 +1.12400000000000000000e+08 +8.84524158800256921076e-01 -4.66224616682866299655e-01 +7.39642433361215653059e-03 +1.40325409206529441025e-02 +7.39642433361215653059e-03 +1.40325409206529441025e-02 +8.84524158800256921076e-01 -4.66224616682866299655e-01 +1.13000000000000000000e+08 +8.80794290674400959240e-01 -4.73192341717892483999e-01 +8.06525254871107676047e-03 +1.50125599496431123836e-02 +8.06525254871107676047e-03 +1.50125599496431123836e-02 +8.80794290674400959240e-01 -4.73192341717892483999e-01 +1.13600000000000000000e+08 +8.76840395559183138907e-01 -4.80432021535730224837e-01 +8.80785772578509228159e-03 +1.60752928741492231990e-02 +8.80785772578509228159e-03 +1.60752928741492231990e-02 +8.76840395559183138907e-01 -4.80432021535730169326e-01 +1.14200000000000000000e+08 +8.72640588950992834860e-01 -4.87963867306267284896e-01 +9.63427310957915526701e-03 +1.72292629101185625073e-02 +9.63427310957915526701e-03 +1.72292629101185625073e-02 +8.72640588950992834860e-01 -4.87963867306267395918e-01 +1.14800000000000000000e+08 +8.68170073819481191713e-01 -4.95810074706974301950e-01 +1.05561927286469178083e-02 +1.84840346898929169805e-02 +1.05561927286469178083e-02 +1.84840346898929169805e-02 +8.68170073819481191713e-01 -4.95810074706974246439e-01 +1.15400000000000000000e+08 +8.63400647702665446914e-01 -5.03995058866944289910e-01 +1.15872994754173033044e-02 +1.98503570544751144211e-02 +1.15872994754173033044e-02 +1.98503570544751144211e-02 +8.63400647702665446914e-01 -5.03995058866944289910e-01 +1.16000000000000000000e+08 +8.58300107813398716061e-01 -5.12545719254411613619e-01 +1.27436691026065560678e-02 +2.13403256603461738417e-02 +1.27436691026065560678e-02 +2.13403256603461738417e-02 +8.58300107813398716061e-01 -5.12545719254411613619e-01 +1.16600000000000000000e+08 +8.52831529083974415606e-01 -5.21491737538981703359e-01 +1.40442703825286278885e-02 +2.29675673131932087112e-02 +1.40442703825286278885e-02 +2.29675673131932087112e-02 +8.52831529083974415606e-01 -5.21491737538981703359e-01 +1.17200000000000000000e+08 +8.46952382915109547312e-01 -5.30865911093095221851e-01 +1.55115878109843285948e-02 +2.47474474905705343897e-02 +1.55115878109843285948e-02 +2.47474474905705343897e-02 +8.46952382915109658335e-01 -5.30865911093095221851e-01 +1.17800000000000000000e+08 +8.40613454904811319146e-01 -5.40704523886904042662e-01 +1.71724014566747885946e-02 +2.66973015386259178439e-02 +1.71724014566747885946e-02 +2.66973015386259178439e-02 +8.40613454904811319146e-01 -5.40704523886904042662e-01 +1.18400000000000000000e+08 +8.33757507163127353778e-01 -5.51047754704064529641e-01 +1.90587696432502860799e-02 +2.88366881666843703769e-02 +1.90587696432502860799e-02 +2.88366881666843703769e-02 +8.33757507163127242755e-01 -5.51047754704064529641e-01 +1.19000000000000000000e+08 +8.26317613782773907616e-01 -5.61940119254769165913e-01 +2.12092752066929506050e-02 +3.11876605324044979539e-02 +2.12092752066929506050e-02 +3.11876605324044979539e-02 +8.26317613782773907616e-01 -5.61940119254769165913e-01 +1.19600000000000000000e+08 +8.18215074961415989030e-01 -5.73430936892501019742e-01 +2.36706166567796187639e-02 +3.37750444494076887403e-02 +2.36706166567796187639e-02 +3.37750444494076887403e-02 +8.18215074961415989030e-01 -5.73430936892501019742e-01 +1.20200000000000000000e+08 +8.09356783794367262708e-01 -5.85574802618157308487e-01 +2.64996539077710438481e-02 +3.66267034759058598969e-02 +2.64996539077710438481e-02 +3.66267034759058598969e-02 +8.09356783794367151685e-01 -5.85574802618157308487e-01 +1.20800000000000000000e+08 +7.99631876521557427573e-01 -5.98432028175489127975e-01 +2.97660574957424005349e-02 +3.97737542299275784186e-02 +2.97660574957424005349e-02 +3.97737542299275784186e-02 +7.99631876521557538595e-01 -5.98432028175489127975e-01 +1.21400000000000000000e+08 +7.88907437254089627388e-01 -6.12068987795145957875e-01 +3.35557648838942790270e-02 +4.32506678291533358527e-02 +3.35557648838942790270e-02 +4.32506678291533358527e-02 +7.88907437254089738410e-01 -6.12068987795145957875e-01 +1.22000000000000000000e+08 +7.77022945174120960310e-01 -6.26558256937955193600e-01 +3.79755239917851997178e-02 +4.70951474501905345549e-02 +3.79755239917851997178e-02 +4.70951474501905345549e-02 +7.77022945174120960310e-01 -6.26558256937955304622e-01 +1.22600000000000000000e+08 +7.63783036426104788852e-01 -6.41978353306991378346e-01 +4.31589115020280175705e-02 +5.13475949867441897045e-02 +4.31589115020280175705e-02 +5.13475949867441897045e-02 +7.63783036426104899874e-01 -6.41978353306991267324e-01 +1.23200000000000000000e+08 +7.48947991379154576208e-01 -6.58412756234040386083e-01 +4.92743642326537167886e-02 +5.60498498382881113478e-02 +4.92743642326537167886e-02 +5.60498498382881113478e-02 +7.48947991379154465186e-01 -6.58412756234040386083e-01 +1.23800000000000000000e+08 +7.32221133494524778484e-01 -6.75947654675000730862e-01 +5.65359722796431041214e-02 +6.12426619420981047104e-02 +5.65359722796431041214e-02 +6.12426619420981047104e-02 +7.32221133494524667462e-01 -6.75947654675000730862e-01 +1.24400000000000000000e+08 +7.13232018117048838235e-01 -6.94667487538792149948e-01 +6.52180722502373466654e-02 +6.69609822298508489125e-02 +6.52180722502373466654e-02 +6.69609822298508489125e-02 +7.13232018117048838235e-01 -6.94667487538792149948e-01 +1.25000000000000000000e+08 +6.91513879029558520273e-01 -7.14646672219031442452e-01 +7.56750654227188457313e-02 +7.32254973969026640157e-02 +7.56750654227188457313e-02 +7.32254973969026640157e-02 +6.91513879029558742317e-01 -7.14646672219031664497e-01 +1.25600000000000000000e+08 +6.66473286596086511580e-01 -7.35934751791925023667e-01 +8.83683681884297467235e-02 +8.00276880990771627422e-02 +8.83683681884297467235e-02 +8.00276880990771627422e-02 +6.66473286596086400557e-01 -7.35934751791925023667e-01 +1.26200000000000000000e+08 +6.37349418889811336619e-01 -7.58530139785663415353e-01 +1.03902913067786747958e-01 +8.73036650638884248465e-02 +1.03902913067786747958e-01 +8.73036650638884248465e-02 +6.37349418889811336619e-01 -7.58530139785663415353e-01 +1.26800000000000000000e+08 +6.03160016271287791056e-01 -7.82334008994332363862e-01 +1.23075894784645631375e-01 +9.48884464275511901876e-02 +1.23075894784645631375e-01 +9.48884464275511901876e-02 +6.03160016271287791056e-01 -7.82334008994332252840e-01 +1.27400000000000000000e+08 +5.62631768181749869484e-01 -8.07069443849200984786e-01 +1.46939705431997608143e-01 +1.02435976127424777093e-01 +1.46939705431997608143e-01 +1.02435976127424777093e-01 +5.62631768181750091529e-01 -8.07069443849201206831e-01 +1.28000000000000000000e+08 +5.14116722910564871718e-01 -8.32139762338305111200e-01 +1.76877066035562968693e-01 +1.09279067848783703609e-01 +1.76877066035562968693e-01 +1.09279067848783703609e-01 +5.14116722910564760696e-01 -8.32139762338305111200e-01 +1.28600000000000000000e+08 +4.55508881725662506668e-01 -8.56381160970645760599e-01 +2.14673667923626160237e-01 +1.14184859345813238818e-01 +2.14673667923626160237e-01 +1.14184859345813238818e-01 +4.55508881725662451156e-01 -8.56381160970645538555e-01 +1.29200000000000000000e+08 +3.84210082447127954097e-01 -8.77636826483634058249e-01 +2.62538535983115273176e-01 +1.14933591562888362536e-01 +2.62538535983115273176e-01 +1.14933591562888362536e-01 +3.84210082447127676541e-01 -8.77636826483634058249e-01 +1.29800000000000000000e+08 +2.97282439804261167104e-01 -8.92050849400025880342e-01 +3.22933968491662837241e-01 +1.07620095999508322282e-01 +3.22933968491662837241e-01 +1.07620095999508322282e-01 +2.97282439804260945060e-01 -8.92050849400025658298e-01 +1.30400000000000000000e+08 +1.92124026112849011216e-01 -8.93003103562596822762e-01 +3.97877265327953033580e-01 +8.56008022912990995668e-02 +3.97877265327953033580e-01 +8.56008022912990995668e-02 +1.92124026112848844683e-01 -8.93003103562597155829e-01 +1.31000000000000000000e+08 +6.83696830944386380047e-02 -8.69873938402882518339e-01 +4.87011020451681930776e-01 +3.82777177954215439004e-02 +4.87011020451681930776e-01 +3.82777177954215439004e-02 +6.83696830944385824935e-02 -8.69873938402882740384e-01 +1.31600000000000000000e+08 -6.79609918130797963087e-02 -8.07833653901424253441e-01 +5.83418457384371480501e-01 -4.90815117870006464851e-02 +5.83418457384371480501e-01 -4.90815117870006464851e-02 -6.79609918130799073310e-02 -8.07833653901424364463e-01 +1.32200000000000000000e+08 -1.98153839635750228521e-01 -6.92090925495786102317e-01 +6.67267837493468296550e-01 -1.91046695157952195476e-01 +6.67267837493468296550e-01 -1.91046695157952195476e-01 -1.98153839635750284032e-01 -6.92090925495785880273e-01 +1.32800000000000000000e+08 -2.88122535752197594938e-01 -5.21098980196032735002e-01 +7.03079580788580793538e-01 -3.88742022822993749109e-01 +7.03079580788580793538e-01 -3.88742022822993749109e-01 -2.88122535752197039827e-01 -5.21098980196032179890e-01 +1.33400000000000000000e+08 -3.02899090104842838578e-01 -3.23184234498291922399e-01 +6.54154450530631925709e-01 -6.13095462906359078836e-01 +6.54154450530631925709e-01 -6.13095462906359078836e-01 -3.02899090104841950399e-01 -3.23184234498290756665e-01 +1.34000000000000000000e+08 -2.37828639780715223040e-01 -1.50750676934625182923e-01 +5.13708511510395426924e-01 -8.10441445574923924333e-01 +5.13708511510395426924e-01 -8.10441445574923924333e-01 -2.37828639780715112018e-01 -1.50750676934625460479e-01 +1.34600000000000000000e+08 -1.28778381340762526630e-01 -4.31933080860871232431e-02 +3.15050440267938713923e-01 -9.39304895506694381702e-01 +3.15050440267938713923e-01 -9.39304895506694381702e-01 -1.28778381340763359297e-01 -4.31933080860877338658e-02 +1.35200000000000000000e+08 -2.26687593006301701948e-02 -2.32886210872496057789e-03 +1.02169999172554967770e-01 -9.94505904970966247980e-01 +1.02169999172554967770e-01 -9.94505904970966247980e-01 -2.26687593006293930387e-02 -2.32886210872484955559e-03 +1.35800000000000000000e+08 +5.12317245896800610439e-02 -5.08765253339041323422e-03 -9.86895486310297442856e-02 -9.93785590144210084773e-01 -9.86895486310297442856e-02 -9.93785590144210084773e-01 +5.12317245896809492223e-02 -5.08765253339038547864e-03 +1.36400000000000000000e+08 +8.40418978386497927957e-02 -2.47111790981879020368e-02 -2.81008072924272656046e-01 -9.55699105360378831087e-01 -2.81008072924272656046e-01 -9.55699105360378831087e-01 +8.40418978386494597288e-02 -2.47111790981878742812e-02 +1.37000000000000000000e+08 +7.85557334917619254355e-02 -3.95099779062877409785e-02 -4.47583614504772686615e-01 -8.89908347195507376526e-01 -4.47583614504772686615e-01 -8.89908347195507376526e-01 +7.85557334917602601010e-02 -3.95099779062870748447e-02 +1.37600000000000000000e+08 +4.33521236669899279192e-02 -3.27109643899355928554e-02 -6.01428618147698434981e-01 -7.97078542839531056785e-01 -6.01428618147698434981e-01 -7.97078542839531056785e-01 +4.33521236669892617854e-02 -3.27109643899353708107e-02 +1.38200000000000000000e+08 -8.04940534568654442182e-03 +8.85863432498479319577e-03 -7.40049151858467535448e-01 -6.72446268860972695691e-01 -7.40049151858467535448e-01 -6.72446268860972695691e-01 -8.04940534568665544413e-03 +8.85863432498462666231e-03 +1.38800000000000000000e+08 -5.58391713551985857666e-02 +9.30142688617066060175e-02 -8.52308017760986635913e-01 -5.11665296449570261572e-01 -8.52308017760986635913e-01 -5.11665296449570261572e-01 -5.58391713551986690334e-02 +9.30142688617063284617e-02 +1.39400000000000000000e+08 -7.51065097618354160502e-02 +2.16574628409290537157e-01 -9.19641887566338023241e-01 -3.18925134089829143136e-01 -9.19641887566338023241e-01 -3.18925134089829143136e-01 -7.51065097618356380949e-02 +2.16574628409290093067e-01 +1.40000000000000000000e+08 -4.41585566854835187556e-02 +3.60278820495524731982e-01 -9.24877650887353075504e-01 -1.13360152888461893084e-01 -9.24877650887353075504e-01 -1.13360152888461893084e-01 -4.41585566854836297779e-02 +3.60278820495526064249e-01 +1.40600000000000000000e+08 +4.25841585503898278908e-02 +4.93237478947128604734e-01 -8.65631579526607741748e-01 +7.47351813318648527940e-02 -8.65631579526607741748e-01 +7.47351813318648527940e-02 +4.25841585503898834020e-02 +4.93237478947128660245e-01 +1.41200000000000000000e+08 +1.69816611909315795526e-01 +5.88499794210738835787e-01 -7.59475009375782605936e-01 +2.19152961803428608656e-01 -7.59475009375782605936e-01 +2.19152961803428608656e-01 +1.69816611909315740014e-01 +5.88499794210738613742e-01 +1.41800000000000000000e+08 +3.11691537919532690726e-01 +6.36052617943876796858e-01 -6.33875259743318597572e-01 +3.10624544235383104329e-01 -6.33875259743318597572e-01 +3.10624544235383104329e-01 +3.11691537919532857259e-01 +6.36052617943877018902e-01 +1.42400000000000000000e+08 +4.46363884348691120074e-01 +6.41957335175016075013e-01 -5.11847516613783248829e-01 +3.55896308354627821657e-01 -5.11847516613783248829e-01 +3.55896308354627821657e-01 +4.46363884348690953541e-01 +6.41957335175016075013e-01 +1.43000000000000000000e+08 +5.62328031516411086521e-01 +6.19153247397310035893e-01 -4.05752187949748654994e-01 +3.68512690666458253563e-01 -4.05752187949748654994e-01 +3.68512690666458253563e-01 +5.62328031516411086521e-01 +6.19153247397310257938e-01 +1.43600000000000000000e+08 +6.56703034170113220114e-01 +5.79966141570946946970e-01 -3.19101877505562903092e-01 +3.61323112069375451672e-01 -3.19101877505562903092e-01 +3.61323112069375451672e-01 +6.56703034170113664203e-01 +5.79966141570947391060e-01 +1.44200000000000000000e+08 +7.31225299542947571041e-01 +5.33281885204806793688e-01 -2.50632247696477128418e-01 +3.43661852167726378227e-01 -2.50632247696477128418e-01 +3.43661852167726378227e-01 +7.31225299542947126952e-01 +5.33281885204806571643e-01 +1.44800000000000000000e+08 +7.89253603441596229828e-01 +4.84595814808915670291e-01 -1.97341163269705077710e-01 +3.21406457625694363944e-01 -1.97341163269705077710e-01 +3.21406457625694363944e-01 +7.89253603441595785739e-01 +4.84595814808915281713e-01 +1.45400000000000000000e+08 +8.34238858661892845880e-01 +4.36956610777625931163e-01 -1.56049924295309616618e-01 +2.97930978791497547142e-01 -1.56049924295309616618e-01 +2.97930978791497547142e-01 +8.34238858661892956903e-01 +4.36956610777625931163e-01 +1.46000000000000000000e+08 +8.69145732343485355464e-01 +3.91878699879104397397e-01 -1.24003647625265986387e-01 +2.75027045771496170268e-01 -1.24003647625265986387e-01 +2.75027045771496170268e-01 +8.69145732343485466487e-01 +3.91878699879104508419e-01 +1.46600000000000000000e+08 +8.96333661820903238038e-01 +3.49988747700131330731e-01 -9.90060323794834662436e-02 +2.53557979015644252563e-01 -9.90060323794834662436e-02 +2.53557979015644252563e-01 +8.96333661820903238038e-01 +3.49988747700131330731e-01 +1.47200000000000000000e+08 +9.17614949219226927468e-01 +3.11429199085059171814e-01 -7.93727086503074746870e-02 +2.33868835136589070522e-01 -7.93727086503074746870e-02 +2.33868835136589070522e-01 +9.17614949219226927468e-01 +3.11429199085059060792e-01 +1.47800000000000000000e+08 +9.34360276091864228043e-01 +2.76094265020993989701e-01 -6.38341075139270547334e-02 +2.16027863948048792775e-01 -6.38341075139270547334e-02 +2.16027863948048792775e-01 +9.34360276091864339065e-01 +2.76094265020993934190e-01 +1.48400000000000000000e+08 +9.47601398965509655881e-01 +2.43762504731008078362e-01 -5.14389708525672395556e-02 +1.99963652305866934622e-01 -5.14389708525672395556e-02 +1.99963652305866934622e-01 +9.47601398965509877925e-01 +2.43762504731008078362e-01 +1.49000000000000000000e+08 +9.58115897463989729665e-01 +2.14168948404499598359e-01 -4.14742398544802881588e-02 +1.85541035877714699520e-01 -4.14742398544802881588e-02 +1.85541035877714699520e-01 +9.58115897463989951710e-01 +2.14168948404499737137e-01 +1.49600000000000000000e+08 +9.66492476705455239028e-01 +1.87042904238775814507e-01 -3.34032487122101762189e-02 +1.72602049295914855565e-01 -3.34032487122101762189e-02 +1.72602049295914855565e-01 +9.66492476705455016983e-01 +1.87042904238775786752e-01 +1.50200000000000000000e+08 +9.73179715504686182470e-01 +1.62126666826780146957e-01 -2.68196353517203348038e-02 +1.60987242952528530893e-01 -2.68196353517203348038e-02 +1.60987242952528530893e-01 +9.73179715504686071448e-01 +1.62126666826780230224e-01 +1.50800000000000000000e+08 +9.78521947841751504882e-01 +1.39183784557022988126e-01 -2.14134987589714859135e-02 +1.50546118446372279021e-01 -2.14134987589714859135e-02 +1.50546118446372279021e-01 +9.78521947841751504882e-01 +1.39183784557023071393e-01 +1.51400000000000000000e+08 +9.82785550685771336354e-01 +1.18001749656824000967e-01 -1.69466865545634358392e-02 +1.41141624817103600309e-01 -1.69466865545634358392e-02 +1.41141624817103600309e-01 +9.82785550685771447377e-01 +1.18001749656824028722e-01 +1.52000000000000000000e+08 +9.86178216288868814132e-01 +9.83918184497583336867e-02 -1.32347489362253222661e-02 +1.32651487741551277200e-01 -1.32347489362253222661e-02 +1.32651487741551277200e-01 +9.86178216288868814132e-01 +9.83918184497583614423e-02 +1.52600000000000000000e+08 +9.88863134958873568614e-01 +8.01874542817054003496e-02 -1.01337169681433910545e-02 +1.24967916984866367347e-01 -1.01337169681433910545e-02 +1.24967916984866367347e-01 +9.88863134958873679636e-01 +8.01874542817053725940e-02 +1.53200000000000000000e+08 +9.90969491202608132596e-01 +6.32422036209547150376e-02 -7.53036459310523452471e-03 +1.17996545694793272818e-01 -7.53036459310523452471e-03 +1.17996545694793272818e-01 +9.90969491202608132596e-01 +6.32422036209546178931e-02 +1.53800000000000000000e+08 +9.92600283416096629274e-01 +4.74274344189095364843e-02 -5.33499072627072364050e-03 +1.11655065718824664245e-01 -5.33499072627072364050e-03 +1.11655065718824664245e-01 +9.92600283416096740297e-01 +4.74274344189094532176e-02 +1.54400000000000000000e+08 +9.93838191714249141739e-01 +3.26301535992100377737e-02 -3.47603188170799012532e-03 +1.05871804407971059625e-01 -3.47603188170799012532e-03 +1.05871804407971059625e-01 +9.93838191714249252762e-01 +3.26301535992100655292e-02 +1.55000000000000000000e+08 +9.94750013965809976035e-01 +1.87510036058552952143e-02 -1.89601184847547994325e-03 +1.00584366170223482584e-01 -1.89601184847547994325e-03 +1.00584366170223482584e-01 +9.94750013965810087058e-01 +1.87510036058553541949e-02 +1.55600000000000000000e+08 +9.95390044545548469124e-01 +5.70247464609406271019e-03 -5.48474208879234188460e-04 +9.57383944849925644371e-02 -5.48474208879234188460e-04 +9.57383944849925644371e-02 +9.95390044545548358101e-01 +5.70247464609402454627e-03 +1.56200000000000000000e+08 +9.95802666844078254726e-01 -6.59266390241927680016e-03 +6.04357729233382908254e-04 +9.12864734811606737264e-02 +6.04357729233382908254e-04 +9.12864734811606737264e-02 +9.95802666844078476771e-01 -6.59266390241941557804e-03 +1.56800000000000000000e+08 +9.96024356866451077153e-01 -1.82027258011077906763e-02 +1.59337883713245374688e-03 +8.71871690449039227211e-02 +1.59337883713245374688e-03 +8.71871690449039227211e-02 +9.96024356866451077153e-01 -1.82027258011078219013e-02 +1.57400000000000000000e+08 +9.96085242530484138435e-01 -2.91882839409680835963e-02 +2.44399311414590343985e-03 +8.34042000814511491624e-02 +2.44399311414590343985e-03 +8.34042000814511491624e-02 +9.96085242530484249457e-01 -2.91882839409682293130e-02 +1.58000000000000000000e+08 +9.96010325368780979893e-01 -3.96031820734600165101e-02 +3.17719702261206552590e-03 +7.99057266252640729931e-02 +3.17719702261206552590e-03 +7.99057266252640729931e-02 +9.96010325368780868871e-01 -3.96031820734601414102e-02 +1.58600000000000000000e+08 +9.95820443918286279938e-01 -4.94954038628715592418e-02 +3.81042869700090429397e-03 +7.66637404773824887583e-02 +3.81042869700090429397e-03 +7.66637404773824887583e-02 +9.95820443918286279938e-01 -4.94954038628717118975e-02 +1.59200000000000000000e+08 +9.95533038118758040191e-01 -5.89078191406332413171e-02 +4.35823776215493469827e-03 +7.36535445293586832349e-02 +4.35823776215493469827e-03 +7.36535445293586832349e-02 +9.95533038118758040191e-01 -5.89078191406333107061e-02 +1.59800000000000000000e+08 +9.95162759411343800231e-01 -6.78788250619020705479e-02 +4.83281680415686455687e-03 +7.08533081143968568316e-02 +4.83281680415686455687e-03 +7.08533081143968568316e-02 +9.95162759411343800231e-01 -6.78788250619021260590e-02 +1.60400000000000000000e+08 +9.94721960433816665414e-01 -7.64428976009169786066e-02 +5.24442547538221150172e-03 +6.82436871696847635604e-02 +5.24442547538221150172e-03 +6.82436871696847635604e-02 +9.94721960433816665414e-01 -7.64428976009169924843e-02 +1.61000000000000000000e+08 +9.94221090190744782866e-01 -8.46310666735910210878e-02 +5.60173077184180582405e-03 +6.58074994660734491347e-02 +5.60173077184180582405e-03 +6.58074994660734491347e-02 +9.94221090190744671844e-01 -8.46310666735909933323e-02 +1.61600000000000000000e+08 +9.93669014581268883468e-01 -9.24713262330513763310e-02 +5.91208147855264414677e-03 +6.35294465455359391726e-02 +5.91208147855264414677e-03 +6.35294465455359391726e-02 +9.93669014581268994490e-01 -9.24713262330513208198e-02 +1.62200000000000000000e+08 +9.93073277654830777195e-01 -9.99889889758773103834e-02 +6.18173062538227360840e-03 +6.13958752519111056190e-02 +6.18173062538227360840e-03 +6.13958752519111056190e-02 +9.93073277654830888217e-01 -9.99889889758772687500e-02 +1.62800000000000000000e+08 +9.92440315547563511878e-01 -1.07206993821614179896e-01 +6.41601666392979316789e-03 +5.93945728307992901196e-02 +6.41601666392979316789e-03 +5.93945728307992901196e-02 +9.92440315547563511878e-01 -1.07206993821614304796e-01 +1.63400000000000000000e+08 +9.91775632447570609784e-01 -1.14146173068393613770e-01 +6.61951169993050658052e-03 +5.75145905133327833836e-02 +6.61951169993050658052e-03 +5.75145905133327833836e-02 +9.91775632447570498762e-01 -1.14146173068393641525e-01 +1.64000000000000000000e+08 +9.91083945940665955732e-01 -1.20825485059557466427e-01 +6.79614330234650475260e-03 +5.57460912981033313018e-02 +6.79614330234650475260e-03 +5.57460912981033313018e-02 +9.91083945940665955732e-01 -1.20825485059557480305e-01 +1.64600000000000000000e+08 +9.90369307548545241282e-01 -1.27262217295047858068e-01 +6.94929501848177630374e-03 +5.40802183215780413184e-02 +6.94929501848177630374e-03 +5.40802183215780413184e-02 +9.90369307548545241282e-01 -1.27262217295047941334e-01 +1.65200000000000000000e+08 +9.89635203077614988842e-01 -1.33472164162939582743e-01 +7.08188965026093891070e-03 +5.25089807763467059099e-02 +7.08188965026093891070e-03 +5.25089807763467059099e-02 +9.89635203077614988842e-01 -1.33472164162939554988e-01 +1.65800000000000000000e+08 +9.88884636466070721106e-01 -1.39469782829222455067e-01 +7.19645851328123281609e-03 +5.10251548140958008370e-02 +7.19645851328123281609e-03 +5.10251548140958008370e-02 +9.88884636466070832128e-01 -1.39469782829222455067e-01 +1.66400000000000000000e+08 +9.88120200087577504888e-01 -1.45268330288619573754e-01 +7.29519925013716666329e-03 +4.96221972704053923553e-02 +7.29519925013716666329e-03 +4.96221972704053923553e-02 +9.88120200087577504888e-01 -1.45268330288619601509e-01 +1.67000000000000000000e+08 +9.87344133895558750957e-01 -1.50879984129472066723e-01 +7.38002425990905066427e-03 +4.82941703836292576812e-02 +7.38002425990905066427e-03 +4.82941703836292576812e-02 +9.87344133895558639935e-01 -1.50879984129472038967e-01 diff --git a/examples/sp/file.cir b/examples/sp/file.cir new file mode 100644 index 000000000..c3a9bbcdf --- /dev/null +++ b/examples/sp/file.cir @@ -0,0 +1,81 @@ +Example circuit to read a Touchstone-format parameter file. + +* This file contains an an analog filter circuit; SP and AC analyses are run +* and the S-parameters are saved in a file. It also contains a behavioural +* circuit that reproduces the original from its saved S-parameters. +* Results from the two versions are plotted together for comparison. +* The behavioural circuit also illustrates the use of a string-valued +* sub-circuit parameter to pass a file name. + +* Derived from: Qucs 1.0.2 C:/Users/Tom Hajjar/.qucs - S/S-parameter_files_ngspice_prj/137MHz_BPF.sch + +* Original circuit for SP analysis + +VP2 _net0 0 dc 0 ac 0.316228 SIN(0 0.316228 1G) portnum 2 z0 50 +VP1 _net1 0 dc 0 ac 0.316228 SIN(0 0.316228 1G) portnum 1 z0 50 +C1 _net2 _net1 4.7P +C5 _net3 _net0 4.7P +C3 _net3 _net2 1P +C4 _net3 0 15P +C2 0 _net2 15P +L2 0 _net3 66N +L1 0 _net2 66N + +.csparam Rbase=50 ; This is required by "wrs2p", below. + +* A version derived from extracted s-parameters, with option for subcircuit. + +VP3 net1 0 dc 0 ac 0.316228 ; Same as VP1 but that must not be loaded. +ri net1 sin 50 +.param in_file="137MHz_BPF.s2p" +X1 sin sout 0 s2p_generic touchstone=in_file +ro sout 0 50 + +* Control section, run simulations. + +.control +* Run an SP analysis, derive group delay and write a Touchstone file + +SP LIN 71 107MEG 167MEG +let Group_Delay = -1*deriv(cph(S_2_1))/(2*pi) +wrs2p new_137MHz_BPF.s2p + +* Now run AC analysis + +alter vp2 ac = 0 +AC LIN 71 107MEG 167MEG +set xbrushwidth=2 +plot group_delay(_net0) sp1.Group_Delay group_delay(sout) +plot db(_net0) cph(_net0) db(sout) cph(sout) +.endc + +* Subcircuit for SP behavioral device + +.SUBCKT s2p_generic 1 2 3 touchstone={touchstone} +* Pin 3 is the reference plane (usually it should be connected to GND) +* HZ S RI R 50 +* Z1 = 50 Z2 = 50 +R1N 1 100 -5.000000e+01 +R1P 100 101 100.000000 +R2N 2 200 -5.000000e+01 +R2P 200 201 100.000000 + +* S11 FREQ R_I + A0101 %vd 100 3 %vd 101 102 m_a0101 + .model m_a0101 xfer file=touchstone span=9 + +* S12 FREQ R_I + A0102 %vd 200 3 %vd 102 3 m_a0102 + .model m_a0102 xfer file=touchstone span=9 offset=3 + +* S21 FREQ R_I + A0201 %vd 100 3 %vd 201 202 m_a0201 + .model m_a0201 xfer file=touchstone span=9 offset=5 + +* S22 FREQ R_I + A0202 %vd 200 3 %vd 202 3 m_a0202 + .model m_a0202 xfer file=touchstone span=9 offset=7 + +.ENDS + +.END diff --git a/src/frontend/commands.c b/src/frontend/commands.c index a72560cba..8e2988c56 100644 --- a/src/frontend/commands.c +++ b/src/frontend/commands.c @@ -259,7 +259,7 @@ struct comm spcp_coms[] = { { "eprvcd", EVTprintvcd, FALSE, TRUE, { 040000, 040000, 040000, 040000 }, E_BEGINNING, 1, LOTS, arg_enodes, - "node node ... : Print event values into vcd file." }, + "[-a] [-t timescale] node node ... : Print event values into VCD file." }, { "edisplay", EVTdisplay, FALSE, TRUE, { 040000, 040000, 040000, 040000 }, E_BEGINNING, 0, 0, NULL, diff --git a/src/frontend/cpitf.c b/src/frontend/cpitf.c index 484b2ff49..b04900ced 100644 --- a/src/frontend/cpitf.c +++ b/src/frontend/cpitf.c @@ -293,10 +293,20 @@ ft_cpinit(void) if ((fp = fopen(buf, "r")) != NULL) { + /* Set a variable to identify the loadable module directory. + * The standard spinit uses it to load XSPICE and OSDI files. + */ + +#define VARNAME "_module_path_" + cp_vset(VARNAME, CP_STRING, Module_Path); + + /* Run spinit */ + cp_interactive = FALSE; inp_spsource(fp, TRUE, buf, FALSE); cp_interactive = TRUE; found = TRUE; + cp_remvar(VARNAME); break; #if defined(HAS_WINGUI) || defined(__MINGW32__) || defined(_MSC_VER) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index a4b157de3..1726feed6 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -66,6 +66,8 @@ Author: 1985 Wayne A. Christopher #define NPARAMS 10000 #define FCN_PARAMS 1000 +#define DEPENDSON 200 + #define VALIDCHARS "!$%_#?@.[]&" static struct library { @@ -4745,7 +4747,7 @@ struct dependency { int skip; char *param_name; char *param_str; - char *depends_on[100]; + char *depends_on[DEPENDSON]; struct card *card; }; @@ -5055,6 +5057,11 @@ static void inp_sort_params(struct card *param_cards, for (ind = 0; deps[j].depends_on[ind]; ind++) ; deps[j].depends_on[ind++] = param; + if (ind == DEPENDSON) { + fprintf(stderr, "Error in netlist: Too many parameter dependencies (> %d)\n", ind); + fprintf(stderr, " Please check your netlist.\n"); + controlled_exit(EXIT_BAD); + } deps[j].depends_on[ind] = NULL; } } diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c index 346cbfc14..f4185c15b 100644 --- a/src/frontend/numparam/xpressn.c +++ b/src/frontend/numparam/xpressn.c @@ -1207,7 +1207,7 @@ insertnumber(dico_t *dico, char **lp, DSTRINGPTR ustr_p) { const char *u = ds_get_buf(ustr_p); char *s = *lp; // Point to line contents - long id; + long id = 0; int n; char *p = strstr(s, "numparm__________"); @@ -1218,7 +1218,7 @@ insertnumber(dico_t *dico, char **lp, DSTRINGPTR ustr_p) (id > 0) && (id < dynsubst + 1)) { /* Found a target for substitution. */ - n = ds_get_length(ustr_p); + n = (int)ds_get_length(ustr_p); if (n <= ACT_CHARACTS) { char buf[ACT_CHARACTS + 1]; diff --git a/src/frontend/options.c b/src/frontend/options.c index 0a17714a5..d246ad318 100644 --- a/src/frontend/options.c +++ b/src/frontend/options.c @@ -24,7 +24,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group bool ft_acctprint = FALSE, ft_noacctprint = FALSE, ft_listprint = FALSE; bool ft_nodesprint = FALSE, ft_optsprint = FALSE, ft_noinitprint = FALSE; bool ft_norefprint = FALSE; -bool ft_ngdebug = FALSE, ft_stricterror = FALSE; +bool ft_ngdebug = FALSE, ft_nginfo = FALSE, ft_stricterror = FALSE; static void setdb(char *str); static struct variable *cp_enqvec_as_var(const char *vec_name, @@ -305,6 +305,8 @@ cp_usrset(struct variable *var, bool isset) ft_noacctprint = isset; } else if (eq(var->va_name, "ngdebug")) { ft_ngdebug = isset; + } else if (eq(var->va_name, "nginfo")) { + ft_nginfo = isset; } else if (eq(var->va_name, "noinit")) { ft_noinitprint = isset; } else if (eq(var->va_name, "norefvalue")) { diff --git a/src/frontend/variable.c b/src/frontend/variable.c index 9410d4db2..ef28cffed 100644 --- a/src/frontend/variable.c +++ b/src/frontend/variable.c @@ -39,6 +39,7 @@ wordlist *cp_varwl(struct variable *var) wordlist *wl = NULL, *w, *wx = NULL; char *buf; struct variable *vt; + int csnump = 0; switch (var->va_type) { case CP_BOOL: @@ -49,8 +50,10 @@ wordlist *cp_varwl(struct variable *var) buf = tprintf("%d", var->va_num); break; case CP_REAL: - /* This is a case where printnum isn't too good... */ - buf = tprintf("%G", var->va_real); + if (cp_getvar("csnumprec", CP_NUM, &csnump, 0) && csnump > 0) + buf = tprintf("%.*g",csnump, var->va_real); /* csnumprec is set */ + else + buf = tprintf("%G", var->va_real); /* standard behavior */ break; case CP_STRING: buf = copy(var->va_string); diff --git a/src/include/ngspice/complex.h b/src/include/ngspice/complex.h index f13c83f1e..27caafa32 100644 --- a/src/include/ngspice/complex.h +++ b/src/include/ngspice/complex.h @@ -5,7 +5,6 @@ #ifndef ngspice_COMPLEX_H #define ngspice_COMPLEX_H - /* Complex numbers. */ struct ngcomplex { double cx_real; @@ -73,6 +72,15 @@ typedef struct { #define cmag(c) (hypot(realpart(c), imagpart(c))) #define radtodeg(c) (cx_degrees ? ((c) * (180 / M_PI)) : (c)) #define degtorad(c) (cx_degrees ? ((c) * (M_PI / 180)) : (c)) +#ifdef HAS_WINGUI +#define rcheck(cond, name)\ + if (!(cond)) {\ + (void) win_x_fprintf(cp_err, "Error: argument out of range for %s\n",\ + name);\ + xrc = -1;\ + goto EXITPOINT;\ + } +#else #define rcheck(cond, name)\ if (!(cond)) {\ (void) fprintf(cp_err, "Error: argument out of range for %s\n",\ @@ -80,6 +88,7 @@ typedef struct { xrc = -1;\ goto EXITPOINT;\ } +#endif #define cdiv(r1, i1, r2, i2, r3, i3) \ { \ diff --git a/src/include/ngspice/fteext.h b/src/include/ngspice/fteext.h index 4f2ce0c35..9f6848503 100644 --- a/src/include/ngspice/fteext.h +++ b/src/include/ngspice/fteext.h @@ -266,6 +266,7 @@ extern char *ft_setkwords[]; extern struct card *inp_getopts(struct card *deck); extern struct card *inp_getoptsc(char *line, struct card *options); extern bool ft_ngdebug; +extern bool ft_nginfo; extern bool ft_stricterror; /* parse.c */ diff --git a/src/include/ngspice/ngspice.h b/src/include/ngspice/ngspice.h index 0937f597d..8d852e9ba 100644 --- a/src/include/ngspice/ngspice.h +++ b/src/include/ngspice/ngspice.h @@ -277,6 +277,7 @@ extern char *News_File; extern char *Spice_Path; extern char *Help_Path; extern char *Lib_Path; +extern char *Module_Path; extern char *Inp_Path; extern char *Infile_Path; extern char *Spice_Exec_Path; diff --git a/src/misc/ivars.c b/src/misc/ivars.c index ce5446982..b26c66d80 100644 --- a/src/misc/ivars.c +++ b/src/misc/ivars.c @@ -10,6 +10,7 @@ char *Spice_Path; char *News_File; char *Help_Path; char *Lib_Path; +char *Module_Path; char *Inp_Path; char *Spice_Exec_Path; @@ -49,23 +50,39 @@ mkvar(char **p, char *path_prefix, char *var_dir, char *env_var) is given, to ../lib, set by src/makefile.am. With Visual C, it is set manually by an entry to ngspice\visualc\src\include\ngspice\config.h. For Windows GUI and Console the path is set relative to the executable.*/ + void ivars(char *argv0) { - char *temp=NULL; + char *root, *temp=NULL; #if defined (HAS_WINGUI) || defined (__MINGW32__) || defined (_MSC_VER) char *ngpath; #endif + root = getenv("SPICE_ROOT"); + if (root) { + temp = tprintf("%s/share/ngspice", root); + mkvar(&Spice_Lib_Dir, root, "share/ngspice", "SPICE_LIB_DIR"); + mkvar(&Module_Path, root, "lib/ngspice", "SPICE_MODULE_DIR"); + } else { #ifdef HAS_RELPATH - Spice_Lib_Dir = temp = copy("../share/ngspice"); -#elif !defined SHARED_MODULE && (defined (HAS_WINGUI) || defined (__MINGW32__) || defined (_MSC_VER)) - ngpath = ngdirname(argv0); - mkvar(&Spice_Lib_Dir, ngpath, "../share/ngspice", "SPICE_LIB_DIR"); - tfree(ngpath); + Spice_Lib_Dir = temp = copy("../share/ngspice"); +#elif !defined SHARED_MODULE && \ + (defined (HAS_WINGUI) || defined (__MINGW32__) || defined (_MSC_VER)) + + ngpath = ngdirname(argv0); + mkvar(&Spice_Lib_Dir, ngpath, "../share/ngspice", "SPICE_LIB_DIR"); + mkvar(&Module_Path, ngpath, "../lib/ngspice", "SPICE_MODULE_DIR"); + tfree(ngpath); #else - env_overr(&Spice_Lib_Dir, "SPICE_LIB_DIR"); + /* Trim "/share/ngspice" from configured Spice_Lib_Dir. */ + + temp = tprintf("%.*s", strlen(Spice_Lib_Dir) - 14, Spice_Lib_Dir); + mkvar(&Module_Path, temp, "lib/ngspice", "SPICE_MODULE_DIR"); + env_overr(&Spice_Lib_Dir, "SPICE_LIB_DIR"); #endif + } + tfree(temp); /* for printing a news file */ mkvar(&News_File, Spice_Lib_Dir, "news", "SPICE_NEWS"); @@ -75,14 +92,16 @@ ivars(char *argv0) mkvar(&Lib_Path, Spice_Lib_Dir, "scripts", "SPICE_SCRIPTS"); /* used to call ngspice with aspice command, not used in Windows mode */ mkvar(&Spice_Path, Spice_Exec_Dir, "ngspice", "SPICE_PATH"); - tfree(temp); + /* may be used to store input files (*.lib, *.include, ...) */ /* get directory where ngspice resides */ #if defined (HAS_WINGUI) || defined (__MINGW32__) || defined (_MSC_VER) { ngpath = ngdirname(argv0); + /* set path either to /input or, if set, to environment variable NGSPICE_INPUT_DIR */ + mkvar(&Inp_Path, ngpath, "input", "NGSPICE_INPUT_DIR"); tfree(ngpath); } @@ -90,6 +109,7 @@ ivars(char *argv0) NG_IGNORE(argv0); /* set path either to environment variable NGSPICE_INPUT_DIR (if given) or to NULL */ + env_overr(&Inp_Path, "NGSPICE_INPUT_DIR"); Inp_Path = copy(Inp_Path); /* allow tfree */ #endif @@ -100,6 +120,7 @@ ivars(char *argv0) /* Set raw file mode, 0 by default (binary) set in conf.c, may be overridden by environmental variable, not sure if acknowledged everywhere in ngspice */ + env_overr(&temp, "SPICE_ASCIIRAWFILE"); if(temp) AsciiRawFile = atoi(temp); diff --git a/src/spicelib/analysis/cktop.c b/src/spicelib/analysis/cktop.c index 50f2dd374..d46cf1024 100644 --- a/src/spicelib/analysis/cktop.c +++ b/src/spicelib/analysis/cktop.c @@ -30,7 +30,8 @@ CKTop (CKTcircuit *ckt, long int firstmode, long int continuemode, int converged; #ifdef HAS_PROGREP - SetAnalyse("op", 0); + if (!ckt->CKTnoOpIter || ckt->CKTnumGminSteps >= 1 || ckt->CKTnumSrcSteps >= 1) + SetAnalyse("op", 0); #endif ckt->CKTmode = firstmode; diff --git a/src/spicelib/analysis/optran.c b/src/spicelib/analysis/optran.c index 8aba4e1a9..f0c7dd76e 100644 --- a/src/spicelib/analysis/optran.c +++ b/src/spicelib/analysis/optran.c @@ -319,9 +319,9 @@ OPtran(CKTcircuit *ckt, int oldconverged) NOISEAN *nojob = (NOISEAN *) ckt->CKTcurJob; */ if(optime == 0) { - -// int type = ckt->CKTcurJob->JOBtype; - +#ifdef HAS_PROGREP + SetAnalyse("optran init", 0); +#endif SPfrontEnd->IFerrorf(ERR_INFO, "Transient op started"); if (opramptime > 0) { CKTnode* n; @@ -483,11 +483,10 @@ OPtran(CKTcircuit *ckt, int oldconverged) resume: #ifdef HAS_PROGREP - if (optime == 0.) - SetAnalyse( "optran init", 0); - else + if (optime > 0) SetAnalyse( "optran", (int)((optime * 1000.) / opfinaltime + 0.5)); #endif + ckt->CKTdelta = MIN(ckt->CKTdelta,ckt->CKTmaxStep); #ifdef XSPICE diff --git a/src/spinit.in b/src/spinit.in index f1ca1c285..ed1b4b78f 100644 --- a/src/spinit.in +++ b/src/spinit.in @@ -16,29 +16,31 @@ set x11lineararcs * comment out if central osdi management is set up unset osdi_enabled +* XSPICE and OSDI are loaded from a path provided in a variable. + * Load the codemodels if $?xspice_enabled -@XSPICEINIT@ codemodel @pkglibdir@/spice2poly.cm -@XSPICEINIT@ codemodel @pkglibdir@/analog.cm -@XSPICEINIT@ codemodel @pkglibdir@/digital.cm -@XSPICEINIT@ codemodel @pkglibdir@/xtradev.cm -@XSPICEINIT@ codemodel @pkglibdir@/xtraevt.cm -@XSPICEINIT@ codemodel @pkglibdir@/table.cm +@XSPICEINIT@ codemodel $_module_path_/spice2poly.cm +@XSPICEINIT@ codemodel $_module_path_/analog.cm +@XSPICEINIT@ codemodel $_module_path_/digital.cm +@XSPICEINIT@ codemodel $_module_path_/xtradev.cm +@XSPICEINIT@ codemodel $_module_path_/xtraevt.cm +@XSPICEINIT@ codemodel $_module_path_/table.cm end * Load the OpenVAF/OSDI models if $?osdi_enabled - osdi @pkglibdir@/asmhemt.osdi - osdi @pkglibdir@/bjt504t.osdi - osdi @pkglibdir@/BSIMBULK107.osdi - osdi @pkglibdir@/BSIMCMG.osdi - osdi @pkglibdir@/HICUMl0-2.0.osdi - osdi @pkglibdir@/psp103.osdi - osdi @pkglibdir@/r2_cmc.osdi - osdi @pkglibdir@/vbic_4T_et_cf.osdi + osdi $_module_path_/asmhemt.osdi + osdi $_module_path_/bjt504t.osdi + osdi $_module_path_/BSIMBULK107.osdi + osdi $_module_path_/BSIMCMG.osdi + osdi $_module_path_/HICUMl0-2.0.osdi + osdi $_module_path_/psp103.osdi + osdi $_module_path_/r2_cmc.osdi + osdi $_module_path_/vbic_4T_et_cf.osdi end diff --git a/src/winmain.c b/src/winmain.c index 8bc92a97e..2fb22aa0c 100644 --- a/src/winmain.c +++ b/src/winmain.c @@ -131,6 +131,7 @@ static HFONT efont; /* Font for element windows */ static HFONT tfont; /* Font for text window */ static HFONT sfont; /* Font for string window */ +extern bool ft_nginfo; /* some additional info printed */ extern bool ft_ngdebug; /* some additional debug info printed */ extern bool ft_batchmode; extern FILE *flogp; /* definition see xmain.c, stdout redirected to file */ @@ -260,7 +261,7 @@ SetAnalyse(char *Analyse, /* in: analysis type */ timebefore.timezone = timenow.timezone; /* info when previous analysis period has finished */ if (strcmp(OldAn, Analyse)) { - if (ft_ngdebug && (strcmp(OldAn, ""))) + if ((ft_nginfo || ft_ngdebug) && (strcmp(OldAn, ""))) win_x_printf("%s finished after %4.2f seconds.\n", OldAn, seconds()); strncpy(OldAn, Analyse, 127); } diff --git a/src/xspice/evt/evtprint.c b/src/xspice/evt/evtprint.c index 624866257..534cad422 100644 --- a/src/xspice/evt/evtprint.c +++ b/src/xspice/evt/evtprint.c @@ -53,6 +53,8 @@ NON-STANDARD FEATURES #include "ngspice/evtproto.h" +#include "ngspice/fteext.h" + #include #include @@ -466,10 +468,11 @@ get_vcdval(char *xspiceval, char **newval) "0z", "1z", "Uz", "0u", "1u", "Uu" }; + static char *returnmap[] = { "0", "1", "x", "0", "1", "x", - "0", "1", "z", + "z", "z", "z", "0", "1", "x" }; @@ -482,7 +485,7 @@ get_vcdval(char *xspiceval, char **newval) /* is it a real number ? */ retval = INPevaluate(&xspiceval, &err, 1); if (err) { - *newval = copy("unknown"); + *newval = copy(xspiceval); // Assume the node type is coded for this. return 2; } *newval = tprintf("%.16g", retval); @@ -495,6 +498,73 @@ get_vcdval(char *xspiceval, char **newval) #define localtime _localtime64 #endif +/* Function to return a real value to be written to a VCD file. */ + +struct reals { + struct dvec *time; // Scale vector + int v_index, last_i; + double factor; + struct dvec *node_vector[EPRINT_MAXARGS]; // For analog nodes +}; + +static double get_real(int index, double when, struct reals *ctx) +{ + struct dvec *dv; + + if (index < ctx->last_i) { + /* Starting a new pass. */ + + if (!ctx->time) { + ctx->v_index = 0; + ctx->time = vec_get("time"); + if (!ctx->time) { + if (ctx->last_i == EPRINT_MAXARGS) { // First time + fprintf(cp_err, + "ERROR - No vector 'time' in current plot\n"); + } + ctx->node_vector[index] = NULL; // No more calls + return NAN; + } + } + + /* Advance the vector index. */ + + while (ctx->v_index < ctx->time->v_length && + ctx->time->v_realdata[ctx->v_index++] < when) ; + ctx->v_index--; + + /* Calculate interpolation factor. */ + + if (ctx->v_index + 1 < ctx->time->v_length) { + ctx->factor = (when - ctx->time->v_realdata[ctx->v_index]); + ctx->factor /= (ctx->time->v_realdata[ctx->v_index + 1] - + ctx->time->v_realdata[ctx->v_index]); + if (ctx->factor < 0.0 || ctx->factor >= 1.0) + ctx->factor = 0.0; // Rounding + } else { + ctx->factor = 0.0; + } + } + + /* Return interpolated value. */ + + ctx->last_i = index; + dv = ctx->node_vector[index]; + if (ctx->v_index < dv->v_length) { + if (ctx->factor == 0.0) { + return dv->v_realdata[ctx->v_index]; + } else { + return dv->v_realdata[ctx->v_index] + + ctx->factor * + (dv->v_realdata[ctx->v_index + 1] - + dv->v_realdata[ctx->v_index]); + } + } else { + ctx->node_vector[index] = NULL; // No more calls + return dv->v_realdata[dv->v_length - 1]; + } +} + /* * A simple vcd file printer. * command 'eprvcd a0 a1 a2 b0 b1 b2 clk > myvcd.vcd' @@ -510,16 +580,23 @@ EVTprintvcd(wordlist *wl) { int i; int nargs; + int timesteps = 0, tspower = -1; wordlist *w; + struct reals ctx; + + double out_time, last_out_time; + + char *node_name[EPRINT_MAXARGS]; - int node_index[EPRINT_MAXARGS]; - int udn_index[EPRINT_MAXARGS]; + int node_index[EPRINT_MAXARGS]; + int udn_index[EPRINT_MAXARGS]; Evt_Node_t *node_data[EPRINT_MAXARGS]; char *node_value[EPRINT_MAXARGS]; char *old_node_value[EPRINT_MAXARGS]; - char node_ident[EPRINT_MAXARGS + 1]; + char node_ident[EPRINT_MAXARGS + 1]; + char vbuf[24][2][EPRINT_MAXARGS]; // Analog value strings CKTcircuit *ckt; @@ -527,19 +604,43 @@ EVTprintvcd(wordlist *wl) Mif_Boolean_t more; - double step = 0.0; double next_step; double this_step; char *value; + /* Check for the "-a" option (output analog values at timesteps) + * and "-t nn": specifies the VCD timestep with range 1fs to 1s */ + + while (wl && wl->wl_word[0] == '-') { + if (wl->wl_word[1] == 'a' && !wl->wl_word[2]) { + timesteps = 1; + } else if (wl->wl_word[1] == 't' && !wl->wl_word[2]) { + wl = wl->wl_next; + if (wl) { + double input; + int error = 0; + char* inword = wl->wl_word; + input = INPevaluate(&inword, &error, 0); + tspower = (int)ceil(- 1. * log10(input)); + if (tspower < 0) + tspower = 0; + } + else + break; + } else { + break; + } + wl = wl->wl_next; + } + /* Count the number of arguments to the command */ nargs = 0; for (w = wl; w; w = w->wl_next) nargs++; if (nargs < 1) { - printf("Usage: eprvcd ...\n"); + printf("Usage: eprvcd [-a] ...\n"); return; } if (nargs > EPRINT_MAXARGS) { @@ -560,17 +661,41 @@ EVTprintvcd(wordlist *wl) node_table = ckt->evt->info.node_table; /* Get data for each argument */ + w = wl; for (i = 0; i < nargs; i++) { node_name[i] = w->wl_word; node_index[i] = get_index(node_name[i]); - if (node_index[i] < 0) { - fprintf(cp_err, "ERROR - Node %s is not an event node.\n", node_name[i]); - return; - } - udn_index[i] = node_table[node_index[i]]->udn_index; - node_data[i] = ckt->evt->data.node->head[node_index[i]]; + if (node_index[i] >= 0) { + udn_index[i] = node_table[node_index[i]]->udn_index; + node_data[i] = ckt->evt->data.node->head[node_index[i]]; + ctx.node_vector[i] = NULL; + } else { + struct pnode *pn; + struct dvec *dv; + wordlist *save; + + /* Is it an analog parameter/node expression? + * The whole expression must be a single word (no spaces). + */ + + save = w->wl_next; + w->wl_next = NULL; + pn = ft_getpnames_quotes(w, TRUE); + w->wl_next = save; + if (pn) { + dv = ft_evaluate(pn); + free_pnode(pn); + } else { + dv = NULL; + } + if (!dv) { + fprintf(cp_err, "ERROR - Node %s not parsed.\n", node_name[i]); + return; + } + ctx.node_vector[i] = dv; + } node_value[i] = ""; w = w->wl_next; } @@ -606,43 +731,96 @@ EVTprintvcd(wordlist *wl) /* get the sim time resolution based on tstep */ char *unit; - double scale; - double tstep = ckt->CKTstep; + double scale, tick; - /* if selected time step is down to [ms] then report time at [us] etc., always with one level higher resolution */ - if (tstep >= 1e-3) { - unit = "us"; - scale = 1e6; + if (tspower >= 0) { + /* VCD timestep set by "-t" option. */ + + if (tspower == 0) { + unit = "s"; + scale = 1.0; + } else if (tspower < 4) { + unit = "ms"; + tspower = 3 - tspower; + scale = 1e3 * pow(10, (double)-tspower); + } else if (tspower < 7) { + unit = "us"; + tspower = 6 - tspower; + scale = 1e6 * pow(10, (double)-tspower); + } else if (tspower < 10) { + unit = "ns"; + tspower = 9 - tspower; + scale = 1e9 * pow(10, (double)-tspower); + } else if (tspower < 13) { + unit = "ps"; + tspower = 12 - tspower; + scale = 1e12 * pow(10, (double)-tspower); + } else if (tspower < 16) { + unit = "fs"; + tspower = 15 - tspower; + scale = 1e15 * pow(10, (double)-tspower); + } else { // 1 fS is the bottom. + unit = "fs"; + tspower = 0; + scale = 1e15; + } + out_printf("$timescale %g %s $end\n", pow(10, (double)tspower), unit); + } else { + double tstep = ckt->CKTstep; + + /* Use the simulation time step. If the selected time step + * is down to [ms] then report time at [us] etc., + * always with one level higher resolution. + */ + + if (tstep >= 1e-3) { + unit = "us"; + scale = 1e6; + } + else if (tstep >= 1e-6) { + unit = "ns"; + scale = 1e9; + } + else if (tstep >= 1e-9) { + unit = "ps"; + scale = 1e12; + } else { + unit = "fs"; + scale = 1e15; + } + out_printf("$timescale 1 %s $end\n", unit); } - else if (tstep >= 1e-6) { - unit = "ns"; - scale = 1e9; - } - else if (tstep >= 1e-9) { - unit = "ps"; - scale = 1e12; - } - else { - unit = "fs"; - scale = 1e15; - } - out_printf("$timescale 1 %s $end\n", unit); + tick = 1.0 / scale; /* Scan the node data. Go for printing using $dumpvars for the initial values. Also, determine if there is more data following it and if so, what the next step is. */ + + ctx.time = NULL; + ctx.v_index = 0; + ctx.last_i = EPRINT_MAXARGS; // Indicate restart more = MIF_FALSE; next_step = 1e30; for (i = 0; i < nargs; i++) { - step = node_data[i]->step; - g_evt_udn_info[udn_index[i]]->print_val - (node_data[i]->node_value, "all", &value); - old_node_value[i] = node_value[i] = value; - node_data[i] = node_data[i]->next; - if (node_data[i]) { - more = MIF_TRUE; - if (next_step > node_data[i]->step) - next_step = node_data[i]->step; + if (ctx.node_vector[i]) { + /* Analog node or expression. */ + + sprintf(vbuf[0][i], "%.16g", get_real(i, 0.0, &ctx)); + node_value[i] = vbuf[0][i]; + old_node_value[i] = vbuf[1][i]; + strcpy(vbuf[1][i], vbuf[0][i]); + } else { + /* This must return a pointer to a statically-allocated string. */ + + g_evt_udn_info[udn_index[i]]->print_val + (node_data[i]->node_value, "all", &value); + node_data[i] = node_data[i]->next; + old_node_value[i] = node_value[i] = value; + if (node_data[i]) { + more = MIF_TRUE; + if (next_step > node_data[i]->step) + next_step = node_data[i]->step; + } } } @@ -658,7 +836,6 @@ EVTprintvcd(wordlist *wl) } out_printf("$enddefinitions $end\n"); - out_printf("#%lld\n", (unsigned long long)(step * scale)); /* first set of data for initialization or if only op has been calculated */ @@ -676,38 +853,92 @@ EVTprintvcd(wordlist *wl) out_printf("$end\n"); /* While there is more data, get the next values and print */ - while (more) { - more = MIF_FALSE; + last_out_time = 0.0; + while (more || + (timesteps && ctx.time && ctx.v_index + 1 < ctx.time->v_length)) { + int got_one; + this_step = next_step; - next_step = 1e30; - for (i = 0; i < nargs; i++) - if (node_data[i]) { - if (node_data[i]->step == this_step) { - g_evt_udn_info[udn_index[i]]->print_val - (node_data[i]->node_value, "all", &value); - node_value[i] = value; - node_data[i] = node_data[i]->next; - } - if (node_data[i]) { - more = MIF_TRUE; - if (next_step > node_data[i]->step) - next_step = node_data[i]->step; - } + if (timesteps && ctx.time && ctx.v_index + 1 < ctx.time->v_length && + (ctx.time->v_realdata[ctx.v_index + 1] < this_step || + (timesteps && !more))) { + + /* Analogue output at each time step, skipping if they would + * appear simulataneous in the output. + */ + + out_time = ctx.time->v_realdata[ctx.v_index + 1]; + if (out_time - last_out_time < tick) { + ++ctx.v_index; + continue; } - /* timestamp */ - out_printf("#%lld\n", (unsigned long long)(this_step * scale)); + for (i = 0; i < nargs; i++) { + if (ctx.node_vector[i]) + sprintf(node_value[i], "%.16g", + get_real(i, out_time, &ctx)); + } + } else { + /* Process next event. */ + + out_time = this_step; + more = MIF_FALSE; + next_step = 1e30; + for (i = 0; i < nargs; i++) { + if (ctx.node_vector[i]) { + /* Analog node or expression. */ + + sprintf(node_value[i], "%.16g", + get_real(i, this_step, &ctx)); + } else if (node_data[i]) { + if (node_data[i]->step == this_step) { + g_evt_udn_info[udn_index[i]]->print_val + (node_data[i]->node_value, "all", &value); + node_value[i] = value; + node_data[i] = node_data[i]->next; + } + if (node_data[i]) { + more = MIF_TRUE; + if (next_step > node_data[i]->step) + next_step = node_data[i]->step; + } + } + } + } + /* print only values that have changed */ - for (i = 0; i < nargs; i++) { + + for (i = 0, got_one = 0; i < nargs; i++) { if (!eq(old_node_value[i], node_value[i])) { char *buf; + + if (!got_one) { + /* timestamp */ + + out_printf("#%lld\n", + (unsigned long long)(out_time * scale)); + last_out_time = out_time;; + got_one = 1; + } + if (get_vcdval(node_value[i], &buf) == 1) out_printf("r%s %c\n", buf, node_ident[i]); else out_printf("%s%c\n", buf, node_ident[i]); - old_node_value[i] = node_value[i]; + + if (ctx.node_vector[i]) { + char *t; + + /* Swap buffers. */ + + t = old_node_value[i]; + old_node_value[i] = node_value[i]; + node_value[i] = t; + } else {; + old_node_value[i] = node_value[i]; + } tfree(buf); } } diff --git a/src/xspice/icm/analog/xfer/cfunc.mod b/src/xspice/icm/analog/xfer/cfunc.mod index e57cbeaa8..eaa67d5e3 100644 --- a/src/xspice/icm/analog/xfer/cfunc.mod +++ b/src/xspice/icm/analog/xfer/cfunc.mod @@ -1,24 +1,32 @@ /* Transfer function block for AC simulation, based on s_xfer code model. */ #include +#include +#include +#include +#include #define PI 3.141592653589793238462643383279502884197 +#define ALLOC 1024 /* How the table information is stored internally. */ -struct data_pt { - double f; /* Frequency, radians/sec. */ - Mif_Complex_t s; /* The S-parameter. */ +struct data { + int size; /* Table size. */ + double *f; /* Frequency table, radians/sec. */ + Mif_Complex_t *s; /* The S-parameter table. */ }; static void cleanup(ARGS, Mif_Callback_Reason_t reason) { - struct data_pt *table; + struct data *table; switch (reason) { case MIF_CB_DESTROY: - table = (struct data_pt *)STATIC_VAR(table); + table = (struct data *)STATIC_VAR(table); if (table) { + free(table->f); + free(table->s); free(table); STATIC_VAR(table) = NULL; } @@ -26,94 +34,291 @@ static void cleanup(ARGS, Mif_Callback_Reason_t reason) } } +static double *read_file(const char *fn, int span, int offset, + int *size_p, Mif_Boolean_t *ri, Mif_Boolean_t *db) +{ + FILE *fp; + double *file_data; + double mult; + int i, j, line, size, count, skip, want; + char *cp, *word; + double vals[9]; + char buff[1024]; + + fp = fopen_with_path(fn, "r"); + if (fp == NULL) { + cm_message_printf("Can not open file %s: %s", fn, strerror(errno)); + return NULL; + } + + /* Find and examine the option line. */ + + line = 0; + while (fgets(buff, sizeof buff, fp)) { + ++line; + if (buff[0] == '#') + break; + } + if (buff[0] != '#') { + cm_message_printf("No option line found in file %s", fn); + fclose(fp); + return NULL; + } + mult = 1.0e9; // Default to GHz + for (cp = buff + 1; *cp; ++cp) { + while (isspace(*cp)) + ++cp; + if (*cp) { + word = cp; + while (*cp && !isspace(*cp)) + ++cp; + *cp++ = '\0'; + + if (!strcmp(word, "MHz")) + mult = 1.0e6; + else if (!strcmp(word, "KHz")) + mult = 1.0e3; + else if (!strcmp(word, "Hz")) + mult = 1.0; + else if (!strcmp(word, "DB")) + *db = MIF_TRUE; + else if (!strcmp(word, "RI")) + *ri = MIF_TRUE; + } + } + + /* Read the data: at most 9 values per line. */ + + size = ALLOC; + file_data = malloc(size * sizeof(double)); + if (!file_data) + goto bad; + want = skip = i = 0; + + while (fgets(buff, sizeof buff, fp)) { + ++line; + count = sscanf(buff, "%lg%lg%lg%lg%lg%lg%lg%lg%lg", + vals, vals + 1, vals + 2, vals + 3, vals + 4, + vals + 5, vals + 6, vals + 7, vals + 8); + if (!count) + continue; + if (span == 9 && count == 5) { + /* Special case: noise data in 2-port file. */ + + cm_message_printf("Ignoring noise parameters in file %s", fn); + break; + } + if (skip) { + if (count > skip) { + j = skip; + skip = 0; + } else { + skip -= count; + continue; + } + } else { + j = 0; + } + + /* Check allocation. */ + + if (i + 3 > size) { + size += ALLOC; + file_data = realloc(file_data, size * sizeof(double)); + if (!file_data) + goto bad; + } + + while (j < count) { + /* Store value. */ + + file_data[i++] = vals[j]; + switch (want) { + case 0: + /* Stored a frequency value. */ + + if (j != 0) + cm_message_printf("Warning: frequency not at start " + "of line %d", + line); + want = 2; + j += offset; + if (j >= count) + skip = j - count; + break; + case 1: + want = 0; + j += span - offset - 1; + if (j >= count) + skip = j - count; + break; + case 2: + j++; + want = 1; + skip = 0; + break; + } + } + } + + if (want || skip) + cm_message_send("Warning: unexpected end of file data."); + *size_p = i / 3; + bad: + fclose(fp); + return file_data; +} + void cm_xfer(ARGS) /* structure holding parms, inputs, outputs, etc. */ { - struct data_pt *table; + struct data *table; Mif_Complex_t ac_gain; double factor; int span, size, i; - span = PARAM(span); if (INIT) { - Mif_Boolean_t ri, db, rad; - int offset, bad = 0, j; - - /* Validate table. */ + Mif_Boolean_t ri, db, rad; + double *file_data; + int offset, bad = 0, j; offset = PARAM(offset); - size = PARAM_SIZE(table); - bad = size % span; - if (!bad) { - for (i = 0; i < size - span; i += span) { - if (PARAM(table[i]) < 0 || - PARAM(table[i + span]) < PARAM(table[i])) { - bad = 1; - break; + span = PARAM(span); + if (offset < 1 || span < offset + 2) { + cm_message_send("Error: impossible span/offset."); + return; + } + + /* Table or File? */ + + if (PARAM(file) == NULL) { + /* Data given by "table" parameter. */ + + file_data = NULL; + size = PARAM_SIZE(table); + bad = size % span || size == 0; + + /* Validate table. */ + + if (!bad) { + for (i = 0; i < size - span; i += span) { + if (PARAM(table[i]) < 0 || + PARAM(table[i + span]) < PARAM(table[i])) { + bad = 1; + break; + } } } - } - if (bad) { - cm_message_send("Warning: badly formed table."); - return; + if (bad) { + cm_message_send("Error: badly formed table."); + return; + } + size /= span; /* Size now in entries. */ + ri = PARAM(r_i); + db = PARAM(db); + rad = PARAM(rad); + } else { + /* Get data from a Touchstone file. */ + + if (!PARAM_NULL(table)) { + cm_message_send("Error: both file and table " + "parameters given."); + return; + } else { + db = MIF_FALSE; + ri = MIF_FALSE; + file_data = read_file(PARAM(file), span, offset, + &size, &ri, &db); + if (file_data == NULL) + return; + span = 3; + rad = MIF_FALSE; + + /* Explicit parameters override file. */ + + if (!PARAM_NULL(r_i)) + ri = PARAM(r_i); + if (!PARAM_NULL(db)) + db = PARAM(db); + if (!PARAM_NULL(rad)) + rad = PARAM(rad); + } } /* Allocate the internal table. */ - size /= span; - table = (struct data_pt *)calloc(size, sizeof(struct data_pt)); + table = (struct data *)malloc(sizeof(struct data)); + if (!table) + return; + table->size = size; + table->f = (double*)malloc(size * sizeof (double)); + if (!table->f) { + free(table); + return; + } + table->s = ( Mif_Complex_t *)malloc(size * sizeof (Mif_Complex_t)); + if (!table->s) { + free(table->f); + free(table); + return; + } STATIC_VAR(table) = table; CALLBACK = cleanup; /* Fill it. */ - ri = PARAM(r_i); - db = PARAM(db); - rad = PARAM(rad); for (i = 0, j = 0; i < size; i++, j += span) { - table[i].f = PARAM(table[j]) * 2.0 * PI; - if (ri) { - table[i].s.real = PARAM(table[j + offset]); - table[i].s.imag = PARAM(table[j + offset + 1]); - } else { - double phase, mag; + double f, a, b; - mag = PARAM(table[j + offset]); + if (file_data) { + f = file_data[j]; + a = file_data[j + 1]; + b = file_data[j + 2]; + } else { + f = PARAM(table[j]); + a = PARAM(table[j + offset]); + b = PARAM(table[j + offset + 1]); + } + table->f[i] = f * 2.0 * PI; + if (ri) { + table->s[i].real = a; + table->s[i].imag = b; + } else { if (db) - mag = pow(10, mag / 20); - phase = PARAM(table[j + offset + 1]); + a = pow(10, a / 20); if (!rad) - phase *= 2 * PI / 360; - table[i].s.real = mag * cos(phase); - table[i].s.imag = mag * sin(phase); + b *= 2 * PI / 360; + table->s[i].real = a * cos(b); + table->s[i].imag = a * sin(b); } } + if (file_data) + free(file_data); } - - table = (struct data_pt *)STATIC_VAR(table); + table = (struct data *)STATIC_VAR(table); if (!table) return; if (ANALYSIS == MIF_AC) { double rv; - size = PARAM_SIZE(table) / span; + size = table->size; rv = RAD_FREQ; - if (rv <= table[0].f) { - ac_gain = table[0].s; - } else if (rv >= table[size - 1].f) { - ac_gain = table[size - 1].s; + if (rv <= table->f[0]) { + ac_gain = table->s[0]; + } else if (rv >= table->f[size - 1]) { + ac_gain = table->s[size - 1]; } else { for (i = 0; i < size; i++) { - if (table[i].f > rv) + if (table->f[i] > rv) break; } /* Linear interpolation. */ - factor = (rv - table[i - 1].f) / (table[i].f - table[i - 1].f); - ac_gain.real = table[i - 1].s.real + - factor * (table[i].s.real - table[i - 1].s.real); - ac_gain.imag = table[i - 1].s.imag + - factor * (table[i].s.imag - table[i - 1].s.imag); + factor = (rv - table->f[i - 1]) / (table->f[i] - table->f[i - 1]); + ac_gain.real = table->s[i - 1].real + + factor * (table->s[i].real - table->s[i - 1].real); + ac_gain.imag = table->s[i - 1].imag + + factor * (table->s[i].imag - table->s[i - 1].imag); } AC_GAIN(out, in) = ac_gain; } else { /* DC, transient ... */ @@ -124,7 +329,6 @@ void cm_xfer(ARGS) /* structure holding parms, inputs, outputs, etc. */ "transient analysis."); } } - OUTPUT(out) = table[0].s.real * INPUT(in); + OUTPUT(out) = table->s[0].real * INPUT(in); } } - diff --git a/src/xspice/icm/analog/xfer/ifspec.ifs b/src/xspice/icm/analog/xfer/ifspec.ifs index 41f2ac177..1caf58711 100644 --- a/src/xspice/icm/analog/xfer/ifspec.ifs +++ b/src/xspice/icm/analog/xfer/ifspec.ifs @@ -23,11 +23,22 @@ PARAMETER_TABLE: Parameter_Name: table Description: "PWL table: frequency/magnitude/phase" Data_Type: real -Default_Value: - +Default_Value: 0 Limits: - Vector: yes Vector_Bounds: [3 -] -Null_Allowed: no +Null_Allowed: yes + +PARAMETER_TABLE: + +Parameter_Name: file +Description: "File in Touchstone format" +Data_Type: string +Default_Value: - +Limits: - +Vector: no +Vector_Bounds: - +Null_Allowed: yes PARAMETER_TABLE: diff --git a/src/xspice/icm/digital/d_osc/cfunc.mod b/src/xspice/icm/digital/d_osc/cfunc.mod index 6f16a93e4..01e268f74 100644 --- a/src/xspice/icm/digital/d_osc/cfunc.mod +++ b/src/xspice/icm/digital/d_osc/cfunc.mod @@ -1,479 +1,200 @@ -/*.......1.........2.........3.........4.........5.........6.........7.........8 -================================================================================ +/* XSPICE code model for the Controlled Digital Oscillator. + * This is a complete redesign of the original version by the + * Georgia Tech team, as a fix for ngspice Bug #629 - "XSPICE d_osc failures". + */ -FILE d_osc/cfunc.mod - -Public Domain - -Georgia Tech Research Corporation -Atlanta, Georgia 30332 -PROJECT A-8503-405 - - -AUTHORS - - 24 Jul 1991 Jeffrey P. Murray - - -MODIFICATIONS - - 23 Aug 1991 Jeffrey P. Murray - 30 Sep 1991 Jeffrey P. Murray - 09 Nov 2022 Holger Vogt - 05 Jan 2023 Robert Turnbull - -SUMMARY - - This file contains the model-specific routines used to - functionally describe the d_osc code model. - - -INTERFACES - - FILE ROUTINE CALLED - - CMmacros.h cm_message_send(); - - CM.c void *cm_analog_alloc() - void *cm_analog_get_ptr() - - CMevt.c void cm_event_queue() - - -REFERENCED FILES - - Inputs from and outputs to ARGS structure. - - -NON-STANDARD FEATURES - - NONE - -===============================================================================*/ - -/*=== INCLUDE FILES ====================*/ - -#include "d_osc.h" /* ...contains macros & type defns. - for this model. 7/24/91 - JPM */ #include +#define FACTOR 0.75 // Controls timing of next scheduled call. */ -/*=== CONSTANTS ========================*/ +/* PWL table entry. */ +struct pwl { + double ctl, freq; +}; +/* Called at end to free memory. */ - -/*=== MACROS ===========================*/ - - - - -/*=== LOCAL VARIABLES & TYPEDEFS =======*/ - - -typedef struct { - double *x; - double *y; -} Local_Data_t; - - -/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - - - - - -/*============================================================================== - -FUNCTION cm_d_osc() - -AUTHORS - - 24 Jul 1991 Jeffrey P. Murray - -MODIFICATIONS - - 30 Sep 1991 Jeffrey P. Murray - -SUMMARY - - This function implements the d_osc code model. - -INTERFACES - - FILE ROUTINE CALLED - - CMmacros.h cm_message_send(); - - CM.c void *cm_analog_alloc() - void *cm_analog_get_ptr() - - CMevt.c void cm_event_queue() - -RETURNED VALUE - - Returns inputs and outputs via ARGS structure. - -GLOBAL VARIABLES - - NONE - -NON-STANDARD FEATURES - - NONE - -==============================================================================*/ - -static void cm_d_osc_callback(ARGS, - Mif_Callback_Reason_t reason) +static void callback(ARGS, Mif_Callback_Reason_t reason) { - switch (reason) { - case MIF_CB_DESTROY: { - Local_Data_t *loc = STATIC_VAR(locdata); - if (loc) { - if (loc->x) - free(loc->x); - if(loc->y) - free(loc->y); - free(loc); - STATIC_VAR(locdata) = loc = NULL; - } - break; - } /* end of case MIF_CB_DESTROY */ - } /* end of switch over reason being called */ -} /* end of function cm_d_osc_callback */ + struct panel_instance *instance; + if (reason == MIF_CB_DESTROY) { + struct pwl *table = STATIC_VAR(locdata); -/*=== CM_D_OSC ROUTINE ===*/ - -/************************************************************* -* The following is the model for the controlled digital * -* oscillator for the ATESSE Version 2.0 system. * -* * -* Created 7/24/91 J.P.Murray * -*************************************************************/ - -/************************************************************* -* * -* * -* <-----duty_cycle-----> * -* I * -* I t2 t3 * -* I \______________/_____ * -* I | | * -* I | | | | * -* I | | * -* I | | | | * -* I | | * -* I | | | | * -* I-----------------*-----* - - - - - - - - - -*--------- * -* t1 t4 * -* * -* * -* t2 = t1 + rise_delay * -* t4 = t3 + fall_delay * -* * -* Note that for the digital model, unlike for the * -* analog "square" model, t1 and t3 are stored and * -* adjusted values, but t2 & t4 are implied by the * -* rise and fall delays of the model, but are otherwise * -* not stored values. JPM * -* * -*************************************************************/ - - -void cm_d_osc(ARGS) -{ - - double *x, /* analog input value control array */ - *y, /* frequency array */ - cntl_input, /* control input value */ - *phase, /* instantaneous phase of the model */ - *phase_old, /* previous phase of the model */ - *t1, /* pointer to t1 value */ - *t3, /* pointer to t3 value */ - /*time1,*/ /* variable for calculating new time1 value */ - /*time3,*/ /* variable for calculating new time3 value */ - freq = 0.0, /* instantaneous frequency value */ - dphase, /* fractional part into cycle */ - duty_cycle, /* duty_cycle value */ - test_double, /* testing variable */ - slope; /* slope value...used to extrapolate - freq values past endpoints. */ - - - int i, /* generic loop counter index */ - cntl_size, /* control array size */ - freq_size; /* frequency array size */ - - Local_Data_t *loc; /* Pointer to local static data, not to be included - in the state vector (save memory!) */ - - - - - /**** Retrieve frequently used parameters... ****/ - - cntl_size = PARAM_SIZE(cntl_array); - freq_size = PARAM_SIZE(freq_array); - duty_cycle = PARAM(duty_cycle); - - - /* check and make sure that the control array is the - same size as the frequency array */ - - if(cntl_size != freq_size){ - cm_message_send(d_osc_array_error); - return; - } - - - if (INIT) { /*** Test for INIT == TRUE. If so, allocate storage, etc. ***/ - - /* Allocate storage for internal variables */ - cm_analog_alloc(0, sizeof(double)); - cm_analog_alloc(1, sizeof(double)); - cm_analog_alloc(2, sizeof(double)); - - /* assign internal variables */ - phase = phase_old = (double *) cm_analog_get_ptr(0,0); - - t1 = (double *) cm_analog_get_ptr(1,0); - - t3 = (double *) cm_analog_get_ptr(2,0); - - /*** allocate static storage for *loc ***/ - STATIC_VAR (locdata) = calloc (1 , sizeof ( Local_Data_t )); - loc = STATIC_VAR (locdata); - CALLBACK = cm_d_osc_callback; - - x = loc->x = (double *) calloc((size_t) cntl_size, sizeof(double)); - if (!x) { - cm_message_send(d_osc_allocation_error); - return; - } - y = loc->y = (double *) calloc((size_t) cntl_size, sizeof(double)); - if (!y) { - cm_message_send(d_osc_allocation_error); - if(x) - free(x); - return; - } - /* Retrieve x and y values. */ - for (i=0; i *phase ) { - *phase = *phase + 360.0; - } - *phase = *phase / 360.0; - - - /* set phase value to init_phase */ - *phase_old = *phase; - - /* preset time values to harmless values... */ - *t1 = -1; - *t3 = -1; - - } - - loc = STATIC_VAR (locdata); - x = loc->x; - y = loc->y; - - /* Retrieve cntl_input value. */ - cntl_input = INPUT(cntl_in); - - /* Determine segment boundaries within which cntl_input resides */ - /*** cntl_input below lowest cntl_voltage ***/ - if (cntl_input <= x[0]) { - - slope = (y[1] - y[0])/(x[1] - x[0]); - freq = y[0] + (cntl_input - x[0]) * slope; - - } - else - /*** cntl_input above highest cntl_voltage ***/ - - if (cntl_input >= x[cntl_size-1]) { - - slope = (y[cntl_size-1] - y[cntl_size-2]) / - (x[cntl_size-1] - x[cntl_size-2]); - freq = y[cntl_size-1] + (cntl_input - x[cntl_size-1]) * slope; - - } - else { /*** cntl_input within bounds of end midpoints... - must determine position progressively & then - calculate required output. ***/ - - for (i=0; i= x[i]) ) { - - /* Interpolate to the correct frequency value */ - - freq = ( (cntl_input - x[i]) / (x[i+1] - x[i]) ) * - ( y[i+1]-y[i] ) + y[i]; - } - } - } - - /*** If freq < 0.0, clamp to 1e-16 & issue a warning ***/ - if ( 0.0 > freq ) { - freq = 1.0e-16; - cm_message_send(d_osc_negative_freq_error); - } - - - /* calculate the instantaneous phase */ - *phase = *phase_old + freq * (TIME - T(1)); - - /* dphase is the percent into the cycle for - the period */ - dphase = *phase_old - floor(*phase_old); - - - /* Calculate the time variables and the output value - for this iteration */ - - if((*t1 <= TIME) && (TIME <= *t3)) { /* output high */ - - *t3 = T(1) + (1 - dphase)/freq; - - if(TIME < *t3) { - cm_event_queue(*t3); - } - } - else - - if((*t3 <= TIME) && (TIME <= *t1)) { /* output low */ - - if(dphase > (1.0 - duty_cycle) ) { - dphase = dphase - 1.0; - } - *t1 = T(1) + ( (1.0 - duty_cycle) - dphase)/freq; - - if(TIME < *t1) { - - cm_event_queue(*t1); - } - } - else { - - if(dphase > (1.0 - duty_cycle) ) { - dphase = dphase - 1.0; - } - *t1 = T(1) + ( (1.0 - duty_cycle) - dphase )/freq; - - if((TIME < *t1) || (T(1) == 0)) { - cm_event_queue(*t1); - } - - *t3 = T(1) + (1 - dphase)/freq; - } - } - break; - - - case EVENT: /** discrete call...lots to do **/ - - test_double = TIME; - - if ( 0.0 == TIME ) { /* DC analysis...preset values, - as appropriate.... */ - - /* retrieve & normalize phase value */ - *phase = PARAM(init_phase); - if ( 0 > *phase ) { - *phase = *phase + 360.0; - } - *phase = *phase / 360.0; - - - /* set phase value to init_phase */ - *phase_old = *phase; - - /* preset time values to harmless values... */ - *t1 = -1; - *t3 = -1; - } - - /* Calculate the time variables and the output value - for this iteration */ - - /* Output is always set to STRONG */ - OUTPUT_STRENGTH(out) = STRONG; - - if( *t1 == TIME ) { /* rising edge */ - - OUTPUT_STATE(out) = ONE; - OUTPUT_DELAY(out) = PARAM(rise_delay); - } - else { - - if ( *t3 == TIME ) { /* falling edge */ - - OUTPUT_STATE(out) = ZERO; - OUTPUT_DELAY(out) = PARAM(fall_delay); - } - - else { /* no change in output */ - - if ( TIME != 0.0 ) { - OUTPUT_CHANGED(out) = FALSE; - } - - if ( (*t1 < TIME) && (TIME < *t3) ) { - OUTPUT_STATE(out) = ONE; - } - else { - OUTPUT_STATE(out) = ZERO; - } - } - } - - break; + if (table) + free(table); + STATIC_VAR(locdata) = NULL; } } +/* Get the current period. */ +static double get_period(double ctl, struct pwl *table, int csize) +{ + double f; + int i; + for (i = 0; i < csize; ++i) { + if (table[i].ctl > ctl) + break; + } + /* Interpolation outside input range continues slope. */ + if (i > 0) { + if (i == csize) + i -= 2; + else + i--; + } + f = table[i].freq + + (ctl - table[i].ctl) * ((table[i + 1].freq - table[i].freq) / + (table[i + 1].ctl - table[i].ctl)); + return 1.0 / f; +} +/* The state data. */ +struct state { + double last_time; // Time of last output change. + Digital_State_t last; // Last value output. +}; + +/* The code-model function. */ + +void cm_d_osc(ARGS) +{ + struct pwl *table; + struct state *state; + double ctl, delta, when; + int csize, i; + + csize = PARAM_SIZE(cntl_array); + if (INIT) { + + /* Validate PWL table. */ + + for (i = 0; i < csize - 1; ++i) { + if (PARAM(cntl_array[i]) >= PARAM(cntl_array[i + 1])) + break; + } + + if (i < csize - 1 || csize != PARAM_SIZE(freq_array)) { + cm_message_send("Badly-formed control table"); + STATIC_VAR(locdata) = NULL; + return; + } + + /* Allocate PWL table. */ + + table = malloc(csize * sizeof (struct pwl)); + STATIC_VAR(locdata) = table; + if (!table) + return; + + for (i = 0; i < csize; ++i) { + table[i].ctl = PARAM(cntl_array[i]); + table[i].freq = PARAM(freq_array[i]); + if (table[i].freq <= 0) { + cm_message_printf("Error: frequency %g is not positve, " + "value replaced by 1e-16.", + table[i].freq); + table[i].freq = 1.0e-16; + } + } + + /* Allocate state data. */ + + cm_event_alloc(0, sizeof (struct state)); + return; + } + + table = STATIC_VAR(locdata); + if (!table) + return; + state = (struct state *)cm_event_get_ptr(0, 0); + + if (CALL_TYPE != EVENT) { + if (TIME == 0.0) { + double phase; + + /* Set initial output and state data. */ + + ctl = INPUT(cntl_in); + delta = get_period(ctl, table, csize); + + phase = PARAM(init_phase); + phase /= 360.0; + if (phase < 0.0) + phase += 1.0; + + /* When would a hypothetical previous transition have been? */ + + state->last_time = delta * (1.0 - PARAM(duty_cycle) - phase); + if (state->last_time < 0.0) { + state->last = ONE; + } else { + state->last = ZERO; + state->last_time = -delta * phase; + } + } + return; + } + + /* Event call; either one requested previously or just before + * a time-step is accepted. + */ + + if (TIME == 0.0) { + OUTPUT_STATE(out) = state->last; + OUTPUT_STRENGTH(out) = STRONG; + return; + } + + /* When is the next transition due? */ + + ctl = INPUT(cntl_in); + delta = get_period(ctl, table, csize); + if (state->last) + delta *= PARAM(duty_cycle); + else + delta *= (1.0 - PARAM(duty_cycle)); + when = state->last_time + delta; + + if (TIME >= when) { + /* If the frequency rose rapidly, the transition has been missed. + * Force a shorter time-step and schedule then. + */ + + cm_analog_set_temp_bkpt(state->last_time + FACTOR * delta); + OUTPUT_CHANGED(out) = FALSE; + return; + } + + if (TIME >= state->last_time + FACTOR * delta) { + /* TIME is reasonably close to transition time. Request output. */ + + state->last_time = when; + state->last ^= ONE; + OUTPUT_STATE(out) = state->last; + OUTPUT_STRENGTH(out) = STRONG; + OUTPUT_DELAY(out) = when - TIME; + + /* Request a call in the next half-cycle. */ + + cm_event_queue(when + FACTOR * delta); + } else { + OUTPUT_CHANGED(out) = FALSE; + + if (TIME < state->last_time) { + /* Output transition pending, nothing to do. */ + + return; + } else { + /* Request a call nearer to transition time. */ + + cm_event_queue(state->last_time + FACTOR * delta); + } + } +} diff --git a/src/xspice/icm/digital/d_osc/ifspec.ifs b/src/xspice/icm/digital/d_osc/ifspec.ifs index d28b93014..b70c86058 100644 --- a/src/xspice/icm/digital/d_osc/ifspec.ifs +++ b/src/xspice/icm/digital/d_osc/ifspec.ifs @@ -62,6 +62,10 @@ Vector_Bounds: - - Null_Allowed: yes yes +/* Rise and fall delay parameter are unused, but retained, + * to be compatible with an earlier version. + */ + PARAMETER_TABLE: Parameter_Name: rise_delay fall_delay diff --git a/src/xspice/mif/mif_inp2.c b/src/xspice/mif/mif_inp2.c index 41f606b9a..e09d8c378 100644 --- a/src/xspice/mif/mif_inp2.c +++ b/src/xspice/mif/mif_inp2.c @@ -579,10 +579,6 @@ MIF_INP2A ( tfree(emessage); gc_end(); return; - } else if((param_info->is_array) && (! param_info->has_conn_ref)) { - LITERR("Defaulted array parameter must have associated array connection"); - gc_end(); - return; } } if((! mdfast->param[i]->is_null) && (param_info->is_array)) { diff --git a/visualc/sharedspice.vcxproj b/visualc/sharedspice.vcxproj index 89bc0fbbe..cb905fbb0 100644 --- a/visualc/sharedspice.vcxproj +++ b/visualc/sharedspice.vcxproj @@ -187,7 +187,7 @@ - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj @@ -235,7 +235,7 @@ - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj @@ -325,7 +325,7 @@ - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj diff --git a/visualc/vngspice-fftw.vcxproj b/visualc/vngspice-fftw.vcxproj index 10bb37c03..62b98b0c8 100644 --- a/visualc/vngspice-fftw.vcxproj +++ b/visualc/vngspice-fftw.vcxproj @@ -296,7 +296,7 @@ lib /machine:x86 /def:..\..\fftw-3.3-dll32\libfftw3-3.def /out:$(IntDir)libfftw3 - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3-3.lib @@ -345,7 +345,7 @@ lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3 - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3-3.lib @@ -498,7 +498,7 @@ lib /machine:x86 /def:..\..\fftw-3.3-dll32\libfftw3-3.def /out:$(IntDir)libfftw3 - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3-3.lib @@ -547,7 +547,7 @@ lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3 - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3-3.lib @@ -654,7 +654,7 @@ lib /machine:x86 /def:..\..\fftw-3.3-dll32\libfftw3-3.def /out:$(IntDir)libfftw3 - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3-3.lib @@ -765,7 +765,7 @@ lib /machine:x86 /def:..\..\fftw-3.3-dll32\libfftw3-3.def /out:$(IntDir)libfftw3 - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3-3.lib diff --git a/visualc/vngspice.vcxproj b/visualc/vngspice.vcxproj index 3d14b4ed2..998225ba1 100644 --- a/visualc/vngspice.vcxproj +++ b/visualc/vngspice.vcxproj @@ -302,7 +302,7 @@ - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj @@ -352,7 +352,7 @@ - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj @@ -504,7 +504,7 @@ - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj @@ -554,7 +554,7 @@ - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj @@ -661,7 +661,7 @@ - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj @@ -772,7 +772,7 @@ - force recompilation of conf.c with actual date + force recompilation of conf.c with current date if exist $(IntDir)conf.obj del $(IntDir)conf.obj