Merge branch 'pre-master' into bt_dev

This commit is contained in:
Brian Taylor 2023-08-01 10:31:25 -07:00
commit 7b2e382ec6
26 changed files with 1045 additions and 636 deletions

View File

@ -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

102
examples/sp/137mhz_bpf.s2p Normal file
View File

@ -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

81
examples/sp/file.cir Normal file
View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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];

View File

@ -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")) {

View File

@ -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);

View File

@ -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) \
{ \

View File

@ -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 */

View File

@ -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;

View File

@ -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 <ngspice-bin-directory>/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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -53,6 +53,8 @@ NON-STANDARD FEATURES
#include "ngspice/evtproto.h"
#include "ngspice/fteext.h"
#include <time.h>
#include <locale.h>
@ -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 <node1> <node2> ...\n");
printf("Usage: eprvcd [-a] <node1> <node2> ...\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);
}
}

View File

@ -1,24 +1,32 @@
/* Transfer function block for AC simulation, based on s_xfer code model. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#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);
}
}

View File

@ -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:

View File

@ -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 <stdlib.h>
#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<cntl_size; i++) {
x[i] = PARAM(cntl_array[i]);
y[i] = PARAM(freq_array[i]);
}
}
else { /*** This is not an initialization pass...retrieve storage
addresses and calculate new outputs, if required. ***/
/** Retrieve previous values... **/
/* assign internal variables */
phase = (double *) cm_analog_get_ptr(0,0);
phase_old = (double *) cm_analog_get_ptr(0,1);
t1 = (double *) cm_analog_get_ptr(1,0);
t3 = (double *) cm_analog_get_ptr(2,0);
}
switch (CALL_TYPE) {
case ANALOG: /** analog call **/
test_double = TIME;
if ( AC == ANALYSIS ) { /* this model does not function
in AC analysis mode. */
return;
}
else {
if ( 0.0 == TIME ) { /* DC analysis */
/* 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;
}
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<cntl_size-1; i++) {
if ( (cntl_input < x[i+1]) && (cntl_input >= 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);
}
}
}

View File

@ -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

View File

@ -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)) {

View File

@ -187,7 +187,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>if exist $(IntDir)conf.obj del $(IntDir)conf.obj</Command>
</PreBuildEvent>
<CustomBuildStep>
@ -235,7 +235,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>if exist $(IntDir)conf.obj del $(IntDir)conf.obj</Command>
</PreBuildEvent>
<CustomBuildStep>
@ -325,7 +325,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseOMP|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>if exist $(IntDir)conf.obj del $(IntDir)conf.obj</Command>
</PreBuildEvent>
<CustomBuildStep>

View File

@ -296,7 +296,7 @@ lib /machine:x86 /def:..\..\fftw-3.3-dll32\libfftw3-3.def /out:$(IntDir)libfftw3
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>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</Command>
</PreBuildEvent>
@ -345,7 +345,7 @@ lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>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</Command>
</PreBuildEvent>
@ -498,7 +498,7 @@ lib /machine:x86 /def:..\..\fftw-3.3-dll32\libfftw3-3.def /out:$(IntDir)libfftw3
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='console_debug|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>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</Command>
</PreBuildEvent>
@ -547,7 +547,7 @@ lib /machine:x64 /def:..\..\fftw-3.3-dll64\libfftw3-3.def /out:$(IntDir)libfftw3
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='console_release|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>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</Command>
</PreBuildEvent>
@ -654,7 +654,7 @@ lib /machine:x86 /def:..\..\fftw-3.3-dll32\libfftw3-3.def /out:$(IntDir)libfftw3
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseOMP|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>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</Command>
</PreBuildEvent>
@ -765,7 +765,7 @@ lib /machine:x86 /def:..\..\fftw-3.3-dll32\libfftw3-3.def /out:$(IntDir)libfftw3
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='console_release_omp|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>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</Command>
</PreBuildEvent>

View File

@ -302,7 +302,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>if exist $(IntDir)conf.obj del $(IntDir)conf.obj</Command>
</PreBuildEvent>
<Midl>
@ -352,7 +352,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>if exist $(IntDir)conf.obj del $(IntDir)conf.obj</Command>
</PreBuildEvent>
<Midl>
@ -504,7 +504,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='console_debug|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>if exist $(IntDir)conf.obj del $(IntDir)conf.obj</Command>
</PreBuildEvent>
<Midl>
@ -554,7 +554,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='console_release|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>if exist $(IntDir)conf.obj del $(IntDir)conf.obj</Command>
</PreBuildEvent>
<Midl>
@ -661,7 +661,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseOMP|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>if exist $(IntDir)conf.obj del $(IntDir)conf.obj</Command>
</PreBuildEvent>
<Midl>
@ -772,7 +772,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='console_release_omp|x64'">
<PreBuildEvent>
<Message>force recompilation of conf.c with actual date</Message>
<Message>force recompilation of conf.c with current date</Message>
<Command>if exist $(IntDir)conf.obj del $(IntDir)conf.obj</Command>
</PreBuildEvent>
<Midl>