ocs/0000755000076500000000000000000011706606202010620 5ustar carlowheelocs/COPYING0000644000076500000000000004314111601145313011651 0ustar carlowheel GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ocs/DESCRIPTION0000644000076500000000000000052311706605746012342 0ustar carlowheelName: OCS Version: 0.1.3 Date: 2011-08-08 Author: Carlo de Falco, Culpo Massimiliano, Marco Merlin Maintainer: Culpo Massimiliano Title: Octave Circuit Simulator Description: Package for solving DC and transient electrical circuit equations Depends: octave (>= 3.0.0), odepkg Autoload: no License: GPL version 2 or later SVNRelease: 9554 ocs/doc/0000755000076500000000000000000011706606201011364 5ustar carlowheelocs/doc/and.cir0000644000076500000000000000110311005317740012617 0ustar carlowheel% 0.1b1 % A Simple CMOS AND GATE % % N-Mosfets % There are 3 N-Mosfets Mnmosfet simple 4 3 3 3 k Vth rd 1e-4 0.1 1e7 1e-4 0.1 1e7 1e-4 0.1 1e7 1 3 4 0 2 0 3 0 4 0 5 0 % % P-Mosfets Mpmosfet simple 4 3 3 3 k Vth rd -1e-4 -0.1 1e7 -1e-4 -0.1 1e7 -1e-4 -0.1 1e7 1 6 4 6 2 6 4 6 4 6 5 6 % % Input voltage sources Mvoltagesources sinwave 2 4 2 4 Ampl f delay shift 0.5 1 0.0 0.5 0.5 2 0.25 0.5 1 0 2 0 END % % Power supply Mvoltagesources DC 2 1 1 1 V 1 6 0 ENDocs/doc/and.nms0000644000076500000000000000006311005317740012643 0ustar carlowheel% 0.1b1 1 Va 2 Vb 5 Va_and_b 6 Vdd 7 I1 8 I2 9 I3 ocs/doc/and.spc0000755000076500000000000000073111706574500012647 0ustar carlowheel* AND (simple Algebraic MOS-FET model) .MODEL mynmos NMOS(LEVEL=simple k=2.94e-05 Vth=0.08 rd=.957e7) .MODEL mypmos PMOS( k=-2.94e-05 Vth=-0.08 rd=.957e7) M1 Va 3 4 0 mynmos M2 Vb 0 3 0 mynmos * nside of the inverter M3 4 0 Va_and_b 0 mynmos M4 Va Vdd 4 Vdd mypmos M5 Vb Vdd 4 Vdd mypmos * pside of the inverter M6 4 Vdd Va_and_b Vdd mypmos V1 Va 0 SIN(0.5 0.5 1 0 0) V2 Vb 0 SIN(0.5 0.5 2 0.25 0) V3 Vdd 0 1 .END ocs/doc/and2.spc0000755000076500000000000000076511706574500012740 0ustar carlowheel* A Simple CMOS AND GATE * models declarations .MODEL mynmos NMOS(LEVEL=lincap k=4.354e-5 Vth=0.7 rd=1e6 Cb=13e-14) .MODEL mypmos PMOS(LEVEL=lincap k=-4.354e-5 Vth=-0.7 rd=1e7 Cb=13e-14) * N-Mosfets M1 Va 3 4 0 mynmos M2 Vb 0 3 0 mynmos M3 4 0 Va_and_b 0 mynmos * P-Mosfets M4 Va Vdd 4 Vdd mypmos M5 Vb Vdd 4 Vdd mypmos M6 4 Vdd Va_and_b Vdd mypmos * Input voltage sources V2 Vb 0 SIN(0.8 -0.8 4MEG -0.0625u 0) * Power supply V1 Va 0 1.6 V3 Vdd 0 1.6 .END ocs/doc/AND_BW.png0000644000076500000000000002311311005317740013063 0ustar carlowheelPNG  IHDR Xb% IDATxٶ@|W/>EcRJOUgrIzDb+J`+JOz^?N?s"ޑs%2:x5ΔyZ֋'aھf2.ô̙Շywj|y>J`<=XU\|aN?XSr>ABeU/eV,a2+Aj8rr%Vj%4i5?5XF Y+O{$ac&_d|^<~0vGe%0 ô8Y2Ί,T):ؑN`+J`+z]uiߌ0|a`%0X _7ֶ TV`%0X V@@e%0X V`%0X V`%{,&;9kMfVЛ[Cq=zZ*h;4WnjxJ`+J`mFv_-R]N`e;`}s* 3 V}JsB SU }ԬxfLEsvࣃuA֛oI VwfKfcϫ gwȬeV]Ha!V;y.VqQdyI_V=]wp9/8/3Xh)M`+J`+A'T3 V`%0Xy0J`+J`h(ZH "E(,PX(>[ǢBhN-,*R ݶ;Uq[q&a-Zݮ>_ª=* ~Srֹ>򢪿ocyKF nVЛBQX(u^}V}a+\)vXYnU@vNiDZ,&VUUI %\Xfc=VE7XͮF)?R~NF6"MAMai>ReIXɹ)ܲaVB #<::P )BaQªeE "E !*&3d#)/!e搯8p?2~-YX? 0' 4>Kެ̉fyUm.7ƴOgr EyEenwE J~(E kwAm HaNp~mVL{U|YٯW(^Xgntrhb+ohZDaџz;?@DBSM!E`5fkdSH6(BaQ¢E "E(,PX(BaQ¢E "E(,PX(⨰vobol-E.E "E(,PX(BaQ¢E }7o> )BbQ¢E "E(,PX(BaQ¢E "E8ÖC`a, !0X@ C`a, !0?} {l /Aϴo:, z8l-3nU谀0F-<M (^/jLoT' jh'{j֜SҪ7Ff-ר:JA7K7aIL|:/t+?XuWIJ̀Q.BX#jL2ȼ^6ly-zSuIߚӼӠF?˷囪`H/i?7Byֵ零K!`h ,Z>!0X@N&aH`e0DdC`a, v6]J-6{];xze.}3c쭾rIXЫ9K]wO&QЇ׿1cCV_yXsU),d՗=M/m;#+> VHK*gcrsd;F/͉4¸Vz}Tv?JKp_ Fb`M!DX^SkN,`qy#E_[VvE#X`m)br( v} EMakEҁkcH u3՘;gF#Z ,UR#Ђam`7@i:~wy] w OrFtDE-zf,S{C`ԍ&XأUaIOc Xg7;0 o;kr7yg ׄ ϳ>S)5&נoÚάN$D2M`+Lꤶߝ}~z~ri05K}!H5;CE]:Ir46K K`a, !0X@ C`a, !0X@ C`a, !0?̦͇$,O°K!0X@ C`a, !0X@ C`a, !0X@ C`a, !0<C!0X@ C`a, !0X@ C`a, !0X@ C`a, !0^?w%]m ,[eq?ӾR@ rr5a}3}@>rՍ׫ÑM7?PqdLa, !0¨XNΫsrG繬7 NjGPZtX% ZԕK^.R%8Ϥ;bQy d5Z\yД'z-7M[ϨKϒ[=CV['ׅ9NٛB; [d;H׿ yov(W+jy@ލcv,K Z#]̃[k\Ά>,95(icN}8&niyRK+%HBPqKW`]#fy>9Y :o~1v ]3e ؗth[;, y'OfcQxMFhg/?ѷyg(n}Z{X@ 敆 XklZM X]lZM XNgo<&LNj<&OI`, !0X@nr-Esg qܹ{<Xy\^]bLBr%0X@ C`a4XFm> Pg~vN9q:uigζ3wp^s9 Iҷ9c(-aMg>c˥ V9UWo$I1 :XVJ` =ǁ ,B,:8I`5E`#Zdk; qFk|{<b`߲jI䞥0+o-z0X 밴YCouIZ='nAI::V) 횸\og֙wmynAì]rCg?~F:^o5fpһAdoo$ጶ+l> Ngx{%v#`X-ִDi4Vl`'9с , !0Q97鰀0Z?;ZB`LBչwa@V=1R 8G$ U K}*ؓJ][2-v`ڱ%XJŖ/5rZ+؅G ̳9Y[#֤5gά˩}!KU-RBPW X\nFj1L% X ,^`/&<ؓM϶$E=)dI`a, !2ˀQdoA@߂֙Dz)Ο.K+iٜ4'L`]4YЙ0~& :&Q7x𤐁Yu!,>aO1X]nJ{ UrՅ["@ a:iyv_@atx%Oa X#Sb#b˳{G*R`M2NZ hYozuX/f7@Sz8UoTr<%WeˀX@ VV3\-XVD]K!0X@ C`a, !0X@ C`a, !0X@ C`a, !0X@ C`a, !0X@ ~+?c\[aҌp20Z9a=ϸfTW.vX^jaC`a, !0X@ C`a, !0X@ C`aE2 #SsA]B @Uф:, X@ C`a, !0X@ C`a, !0X@ C`a, !0X@ ~k/@WdL 3 @f,4Xi2`dL 3 @f,4Xi2`dL 3 @f,4Xi2`dL?~~I-Hpg@ ]Վ˟s(k:f@p5\1qW, 8(R ;D 3 @f,4Xx'w E`͗:D8wW(1<TDžlf\g@Q`>X{) `M{=˷M׻?zs>oӠB_0N*53 a=ت.[;%-~aiO.XWikrK]3 8 '`+s~fɭ͐W !B꫾1ʆ6mooYkIV4XTfaTZ+ v`Q~'nuշiDz0N*5ӟLO;=< 4R0R3#֋<֖\mXlh{ۇo^.,U!n#pNf^v%`@mF$R-`Qn֮p.P6X$6\npL_MrPQ;8X4I50dw]zp'2q0G~ 3 @f,4X0 א6u'i`DwXT=@fi`v/C5ύFir1 3 @f,4Xi2`d>X^n61 _9}mZJdօl[ׇ/Nh:t:xk4XlۅN?LϙSYI-?}1,B:7w!LJ Rێ Lk 93[dakcm;oo:3U6}9w ~2.|w2`9C 糯y7 >+fnMMDjiqmMz,1t``VU`srꋴ&|>h}ĵMfo0A'zqg1`:2o/Kl2]g01qta|`Z 4X ?Rk`]UڞVjx+'f:*iµ(A7cYIDATn 3 @f0O:t| -E8D 3 @f,֜7iZ9n`/D\4X4XZA ,)6"@ B!H1&`dk dFw4ByӖJw5yL{Tx|~A.fRu1) 2hA^Jk > 梸`OP]'OsQh8^}V9DxcjBCз4Xt|>\p+6}%TwhW?;b`]qfsA"X|P}ܡ\Ե}::*k:|:>rнIHt>sXC:N҄@tfrctW9v !@f,4X9 :-aFUmC1K7'7̫B`77I:0 VAI;^(GUDNH m+}YF *AZ+fvI󳟗_COy> >z2ñܩ52qizn牨o?7y\jiOk/4iZW۟<\x|ߵ^9sF60`5ah AtX9XOGFz-vT?h(-/]H`ʯkj< @OUDgڔ;1ƌ &2YUn4/FUX[Rrny&ܡzȪY9so<p:h`kKAijkD{,4Xi2`dL), :݃ -4X. Y,m5h bQ4Ii2`dL 3 @f,4Xi2`dL 3 @f,4Xi2`dL 3 @f,4Xi2`dL 3 @f,4X~12,j.PoD˯Yۃ-Ftjs(k;? y¬_ ѩa8Ch^ 2`dL 3 @f,4Xi2`dL 3 @f,4Xi2{z.n݈ 32`dL 3 @f,4Xi2`dL 3 @f,4Xi2`dL 3 @f,4Xi2`dL 3 @f,4Xi2?.qVXIENDB`ocs/doc/and_output.png0000644000076500000000000001470711005317740014264 0ustar carlowheelPNG  IHDR,sBITO)PLTE@ @@```@0``@@@@`````@```` ``` @@ @` ```@ ```@@@``` @ @``@@`pT&sGtEXtSoftwaregnuplot version 4.0 patchlevel 0 on Linux 2.6.15-1.2054_FC5smp7/IDATxb: ɖ/[Z Xe[ 3lNdk vd]|4 D,a2SA@ T0 \1: 8mϽ^! |vI-m*{GU "L@d-;Y޿0g+Aϖw }_ "M¾Կ4R~ Bpd;[e-/6PvMSQ۔ `=;dk;3L]vu{o_wsk޾j+ڲenq֟<nV~})˖'`S hY~uR.<6WmcE[H;)VP+b2EO3D[-TPh&%[n]AK^hwl't! gW٧?=І<د?}І+E@І5}ʻ# /B%V/~m&EK@@.,Vu@@z,4)h]@ z!_EN)F5 we嗣$$w<Z5tׯUw0^ Yvx\T/]ڰ a9 x^Qo4a~ׂ՟kok 0 g5 x |ЫNm~ʫa޿?4M|SЄZi\bhB+`W~K =?(^KUЄJ1;_0Mh_[B`  {kb*`E" #+`oЄP! XhB$ӿl#p~mʮh 8̿-7 8ο3Mu.]Hm#B@g*o* M 8?ʷa }9pwe.LRđ3 !+o D@eg0s~Г*h$ Zm D@?NQOli  8?Gì\h{7FFi 08&Rh 6 D@"q^?fU@/NM6ha+\Mt+[hb#d4<23({i g"zᕐ7 ,lB[pZϧT0 8?n70bV# R@W,p A"Sl60G涚)`zg_x P? 8(z* Ra@c a |j2x$l{\xEXoJ*/xPVō|r;|:D@-n~Y1 rg50B?x .[#)'$) ,`v,lߘ0Z8Iw1,B~XpfM{1g0;I )Fr E&{O@ގgѡw D@=y0x+=0ssMoJʢ4 G_3YU,Ľ:r(LQEщw7P D>B@)iz-xY *PfR; ( sHJ D@9)ufKnQ@(cǤpu&z\@(a?gp<`1y?d"d2^ l>ܾRN~%@Ne?_o+* ~ {e"`D=! RFb VM#x&'2+ `L~ PHz},`aO$T")6[!k~|;N)b )O& T& DGvUXU4X33<촲& `qtl' Xy䆀 "`ڳ'pיeS!`B54 D@*C_ ´OPp&;$בBN-nkv'WI @L7E3^6Vz'ߜJ>P6~N( g FOV ''0b|#|l&S\τn/݌Qn6.wm݊oڋy Rvͷ'p;ƿ0Sd0 G[_N,t2N٫F؈2=οH X: TvV1_= EJ"uEY|Mf//ڿHX|I!Pٷ״#޿H<W|YIN \5m:,h;73G븐^/P'/%9Wſ@y0!N'm#?ǿ@]H@'uj_NֿgKw':y=S0!N'_vj'OWϿ@Q]D@Guk_NvO_d>YWտ@[ :yQt=^G.#:ymGv~ ɟI TWn _N^Wg߿@!`8V5E:w;Wgt:yiS ſ@V5>a_N~+ T+ ɿ@?W^}!`JNV'^V~q:AH/tqY4:t9fѼH#J'02/GY4W*I=&H'04P{Rv…e`N"`l.004G@ .F$F0 WwtsiFyD -&\Y00 I<h6 5" ̻nwgwu|@̎&l[Pm:. mN,[m7U\ "o X; \nr PЛxvʢ/8 73 X;JA@mt v|]6a|O• QKzkpO%pR+7s%?p4p^'wQP 6A@]t0Z\qh fpR%?MЛkS8{gN&@@r}P[ˠX": `*A\NdZ<F `Bnt2S:F `@|.dp J=@BNdl  ]@K #S@tF@-蚍ZwP3FXw蚍ZFwT1F\w蚍Z5 d^Aݭ"k6jr D@lԂeh'jEf f#<#s\w蚍ZvN V]AJ-"k6j*02 D@l2/"`eW@F@%蛍JFuV!F^@F@%:Y##j`!X L8G`n蛍Jt^FT@F@%蛍JFtRPFV@F@%:) C#b f#Um0}P fwRVѝ@yj{wRXsѽ/[)عroVe\2l[iVطbПp۰_صRП+ ?Hu줢g+ ?/ю}tv],ɟƽ4e|wb0@sJz;|"%Rrd>k| `;uruF@n펵Y^ g{}ثw]6} ` G! ɻ2{{ <h>I+EOSZاwm6 PLu ɻ:C{p(Esl8܃C1-1C'_E=B`';E=n{'WD=jw';D=fs'7C=bo';C=@Nv{0=!@tFQ&A=)ࡁ蜍)cL{>T#:AtFe:X"s6)l<ANp X2D$hLh[Ӵ l?D8T*V E:cVwL}6&.3#`lnfOhF8ml^gFxm~ lG x8߻[J@=xCX- >B0&8[Żnӧ@=qI2L&#p[ |P;}@="l C\0R07Mbz{v1h=~uߵ ;zX2 st'_sR:[;M]n?’UަU/[c).nc}pb X> -`]/wXZe xfO^m!4.JݍI6^"X6[jfnM@ n7'ݾ3;?ޏ/?sE#<:s?" gp 0\>G WqaWlH:F_vw=hKc Yi$URΊ$:t+.[7ʲM#O!ׅ✣Oi6c^Yї;OuVc&{'Pyhȱ ( {"{!phר?Z(ѧP{hɱ (Q-8gxf3zE9F5W)qZ1:G@965W)Qz)e/ ^±O,0$ p?.ka \E (ͱ(ȶrug^/w--9٦W_j+`!njl򲵻QfW`>-S8eTݍ2[%`Dznx (ʶѪC ܷ9NʲmʶMbJ]є.Pm_VmS)ګ}zf'޶GWo$.cir} \item 1 {\nms} ({\bf N}a{\bf m}e{\bf s}) file: an {\tt ASCII } text file with filename {$<$circuitname$>$.nms} \item $N \geq 1$ {\sbn} ({\bf S}u{\bf bn}et) files: a set of M-functions or DLD-functions following the template described in \autoref{ssecsbn} below. %\item 1 {\ord} (Re{\bf ord}ering ) file: an M-function or DLD-function %following the template described in \autoref{ssecord} below. \end{itemize} {\sbn} files are not necessarily specific to one circuit and can be grouped in \emph{libraries} as long as the directory containing the library is added to the path when the {\Iff} parser is run. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{File Formats} Below we describe the purpose and the syntax of each of file categories. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsubsection{{\cir} files} The {\cir} file is divided into two sections describing the linear time--independent ({\lcr} = {\bf l}inear {\bf c}i{\bf r}cuit) and the non--linear and/or time--dependent ({\nlc} = {\bf n}on--{\bf l}inear {\bf c}ircuit) partitions of the circuit respectively. The syntax for the {\lcr} and {\nlc} section is identical. {\nlc} can also contain linear elements, in fact the whole circuit could be described only by the {\nlc} section but this could result in the evaluator unnecessarily recomputing local matrices for linear time--independent elements The content of {\cir} files is organized as follows\footnote{ This description makes use of Extended Backus-Naur Form (EBNF) see this \hyperref{http://www.garshol.priv.no/download/text/bnf.html}{}{}{article} or the EBNF entry in the \hyperref{http://en.wikipedia.org}{}{}{wikipedia} for an explanation of (E)BNF }: \begin{lstlisting}[language=Mathematica,mathescape=true,backgroundcolor={}] cir := header nlc separator lcr separator ; header := '%' version_id '$\nl$' comment* ; comment:= '%' text '$\nl$' ; nlc := block* ; block := blockcomment? blockheader pv_matrix vnum_matrix ; block_comment := '%' text '$\nl$' ; block_header := func section n_extvar n_par '$\nl$' n_rows n_parnames '$\nl$' par_name*; section := string ; n_extvar := number ; n_par := number ; n_rows := number ; n_parnames := number ; par_name := string ; pv_matrix := matrix ; vnum_matrix := matrix ; matrix := number+ ; separator := 'END $\nl$' ; lcr := block* ; \end{lstlisting} where \begin{description} \item {\tt version\_id} is a string identifying the version on {\Iff} in which the file is encoded \item $\nl$ is the new-line character \item {\tt string} represents anything that the {\oct} command {\tt s=fscanf(file,\%s) } would parse as a string {\it i.e.} any sequence of chars without white-space \item {\tt text} is any sequence of chars without a $\nl$, this differs from {\tt string} because it can contain white--space \item {\tt number} represents anything that the {\oct} command {\tt s=fscanf(file,\%g) } would parse as a number \item {\tt func} is the name of a function to evaluate the elements described in the block \item {\tt n\_extvar} Is the number of {\it external variables} for the elements of a block \item {\tt n\_par} Is the number of {\it parameters} for the elements of a block \item {\tt n\_rows} Is the number of {\it elements} in a block \item {\tt n\_parnames} Is the number of {\it parameter names} for the elements of a block, it corresponds to the number of {\tt par\_name} entries. If {\tt n\_parnames} is 0 the line with the {\tt par\_name}s is missing. \item {\tt pv\_matrix} Is a list of {\tt n\_rows} $\times$ {\tt n\_par} numbers separated by any character the {\oct} command {\tt s=fscanf(file,\%g) } would consider whitespace (including $\nl$). \item [] every row (a set of {\tt n\_par} contiguous entries) in {\tt pv\_matrix} refers to an element of the circuit. The {\tt n\_par} numbers in a row represent the values of the parameters to be passed to the function that evaluates that element. \item {\tt vnum\_matrix} Is a list of {\tt n\_rows} $\times$ {\tt n\_extvar } numbers separated by any character the {\oct} command {\tt s=fscanf(file,\%g) } would consider white-space (including $\nl$). \item [] every row (a set of {\tt n\_extvar} contiguous entries) in {\tt vnum\_matrix} refers to an element of the circuit. The {\tt n\_extvar} numbers in the row represent the global numbering of the element external variables. \end{description} \subsubsection{{\nms} files} {\nms} files are meant to contain the names of the circuit variables, the format of {\nms} is just a list of variable names one on each row preceded by the variable number: \begin{lstlisting}[language=Mathematica,mathescape=true,backgroundcolor={}] nms := version_id '$\nl$' comment* line* ; line := var_number var_name ; var_number := number ; var_name := string ; \end{lstlisting} the variable are ordered as follows: \begin{itemize} \item first all external variables of all elements in the order given by the global numbering of external variables as explicitly written in the {\cir} files \item then the internal variables of the elements in the same order as the corresponding elements appear in the {\cir} file ( internal variables of non-linear elements first, then those of linear elements) \end{itemize} Notice that the number of internal variables of each element is not included in the {\Iff} files. This is because elements with a number of internal variables that is huge, that depends on the value of some parameter, or even that changes in time (for example distributed elements treated with a FEM with adaptive meshing, a large linear sub-circuit that is reduce via MOR...) and therefore it is more convenient to compute the number of internal variables when initializing the system. \subsubsection{{\sbn} files} \label{ssecsbn} {\sbn} files are {\oct} functions, implemented as (M-scripts or as DLD functions) with a header as follows: \begin{lstlisting} function [a,b,c,] =... func (string, m(i,:), extvar, intvar, t) \end{lstlisting} i.e. it should get as inputs: \begin{itemize} \item the string entry of the block header \item one row of the {\tt pv\_matrix} entry of the block \item the current values of all internal and external variables \item the current time \end{itemize} and it should produce as outputs three matrices: \begin{itemize} \item $a,b \in \mathbb{R}^{ \mbox{\tt (n\_extvar + n\_intvar})\times \mbox{\tt (n\_extvar + n\_intvar)}}$ \item $c\in \mathbb{R}^{\mbox{\tt (n\_extvar + n\_intvar)}} $ \end{itemize} where {\tt n\_intvar} is the number of \emph{internal variables} (see \autoref{sec:appintext} for explanation of \emph{internal variables} and \emph{external variables} ) that can be assembled in the complete system matrices. We assume that the full DAE system can be written in the form \begin{equation}\label{eqdaesystem} \left(A(t) \mathbf{x}\right)_{,t} + B \mathbf{x} + \mathbf{C} + \mathbf{f}(\mathbf{x},t)= 0 \end{equation} The local matrices $a$,$b$,$c$ of a linear element $E_{l}$, will contain the contributions to $A$, $B$, $C$ due to $E_{l}$. At a given instant of time $t=\tilde{t}$ and for a given set of state variables $\mathbf{x}=\mathbf{\tilde{x}}$, the local matrices of a non-linear element $E_{nl}$, will contain the local contributions to: \begin{itemize} \item $a$ to $A(\tilde{t})$ \item $b$ to the Jacobian matrix $\left.\frac{\partial \mathbf{f}}{\partial\mathbf{x}}\right|_{\mathbf{x}= \mathbf{\tilde{x}},t=\tilde{t}}$ \item $c$ to $\mathbf{f}(\mathbf{\tilde{x}},\tilde{t})$ \end{itemize} due to $E_{nl}$. \subsection{Internal and External Variables}\label{sec:appintext} To better understand what is intended by \emph{internal} and \emph{external} variables we consider below an example with a linear system, For another example see~\cite{freund99}, Pag.398. Consider the system below, where, for sake of simplicity, we assume all coefficient matrices to be independent of time and of the state vector $\mathbf{x}$ \begin{equation}\label{eq:coupledlinsys} S: \,\, A \mathbf{x}_{,t} + B \mathbf{x} + \mathbf{C} = 0. \end{equation} We assume that the system $S$ obeying~\eqref{eq:coupledlinsys} can be partitioned into two subsystems $S1$ and $S2$ and therefore the state vector $\mathbf{x}$ can be written as: \newcommand{\xprtd}{\left[\begin{array}{c}% \mathbf{x}_{c} \\ \mathbf{x}_{1} \\ \mathbf{x}_{2} \\ \end{array}\right]} \begin{equation}\label{eq:staepart} \mathbf{x} = \xprtd \end{equation} where $\mathbf{x}_{1}$ represents the vector of the unknowns belonging only to $S1$, $\mathbf{x}_{2}$ represents the vector of the unknowns belonging only to $S2$ and $\mathbf{x}_{c}$ represents the vector of the unknowns common to $S1$ and $S2$. If $\mathbf{x}_{1}$ and $\mathbf{x}_{2}$ depend on each other only through $\mathbf{x}_{c}$, then the \emph{flat} representation~\eqref{eq:coupledlinsys} takes the form \newcommand{\MTT}[9]{\left[ \begin{array}{ccc}#1 & #2 & #3 \\#4 & #5 & #6 \\#7 & #8 & #9 \end{array} \right]} \begin{equation}\label{eq:partitionedcoupledlinsys} S: \,\, \MTT{A_{cc1}+A_{cc2}}{A_{c1}}{A_{c2}} {A_{1c}}{A_{11}}{0} {A_{2c}}{0}{A_{22}} \left(\xprtd\right)_{,t} + \MTT{B_{cc1}+B_{cc2}}{B_{c1}}{B_{c2}}{B_{1c}}{B_{11}}{0}{B_{2c}}{0}{B_{22}} \xprtd + \left[ \begin{array}{c}% \mathbf{C}_{c1}+\mathbf{C}_{c2} \\ \mathbf{C}_{1} \\ \mathbf{C}_{2} \\ \end{array}\right] = 0. \end{equation} which is equivalent to $$ \begin{array}{ll} (A_{cc1}+A_{cc2}) \mathbf{x}_{c,t} + A_{c1} \mathbf{x}_{1,t} + A_{c2} \mathbf{x}_{2,t} + (B_{cc1}+B_{cc2}) \mathbf{x}_{c} + B_{c1} \mathbf{x}_{1} + B_{c2} \mathbf{x}_{2} + (C_{c1} + C_{c2}) &= 0\\ % A_{1c} \mathbf{x}_{c,t} + A_{11} \mathbf{x}_{1,t} + B_{1c} \mathbf{x}_{c} + B_{11} \mathbf{x}_{1} + C_{1} &= 0\\ % A_{2c} \mathbf{x,t}_{c} + A_{22} \mathbf{x}_{2,t} + B_{2c} \mathbf{x}_{c} + B_{22} \mathbf{x}_{1} + C_{2} &= 0\\ \end{array} $$ Then $S$ can be represented as the coupling of two systems $S1$ and $S2$ in the following way: \newcommand {\matrow}[2]{\left[ \begin{array}{cc} #1 & #2 \end{array}\right]} \newcommand {\matcol}[2]{\left[ \begin{array}{c} #1 \\ #2 \end{array}\right]} \begin{eqnarray} \label{eq:s1} S1 : & & \,\, \matrow{A_{1c}}{A_{11}} \matcol{ \mathbf{x}_{1,t}^{(e)}}{ \mathbf{x}_{1,t}} + \matrow{B_{1c}}{B_{11}} \matcol{ \mathbf{x}_{1}^{(e)}}{ \mathbf{x}_{1}} + C_{1} = 0 \\ % \label{eq:s2} S2 : & &\,\, \matrow{A_{2c}}{A_{22}} \matcol{ \mathbf{x}_{2,t}^{(e)}} { \mathbf{x}_{2,t}} + \matrow{B_{2c}}{B_{22}} \matcol{ \mathbf{x}_{2}^{(e)}}{ \mathbf{x}_{2}} + C_{2} = 0 \\ % \label{eq:s1s2coupling} COUPLING : & & \,\, \left\{\begin{array}{l} \mathbf{x}_{1}^{(e)} = \mathbf{x}_{2}^{(e)} = \mathbf{x}_{c} \\[.5cm] \matrow{A_{cc1}}{A_{c1}} \matcol{ \mathbf{x}_{1,t}^{(e)}}{ \mathbf{x}_{1,t}} + \matrow{A_{cc2}}{A_{c2}} \matcol{ \mathbf{x}_{2,t}^{(e)}}{ \mathbf{x}_{2,t}} + \\ + \matrow{B_{cc1}}{B_{c1}} \matcol{ \mathbf{x}_{1}^{(e)}}{ \mathbf{x}_{1}} + \matrow{B_{cc2}}{B_{c2}} \matcol{ \mathbf{x}_{2}^{(e)}}{ \mathbf{x}_{2}} + C_{c1} + C_{c2} = 0 \end{array}\right. \end{eqnarray} It is easy to see that, reversing the procedure shown above, it is possible to reconstruct the full system $S$ from the subsystems $S1$ and $S2$ the information that is needed for this purpose is the following: \begin{itemize} \item the local matrices \begin{eqnarray} \label{eq:locmati} A_{i} = & & \left[ \begin{array}{cc} A_{cci} & A_{ci} \nonumber \\ A_{ic} & A_{ii} \end{array} \right]\\ B_{i} = & & \left[ \begin{array}{cc} B_{cci} & B_{ci} \\ B_{ic} & B_{ii} \end{array} \right] \nonumber \\ C_{i} = & & \left[ \begin{array}{c} C_{ci} \\ C_{i} \end{array} \right] \nonumber \\ i=1,2 && \nonumber \end{eqnarray} \item a partitioning of the state variables of each subsystem in \emph{internal} ($\mathbf{x}_{i}$) and \emph{external} ($\mathbf{x}_{i}^{(e)}$) variables: \item a \emph{global numbering} of external variables {\it i.e.} an equation of the form of~\eqref{eq:s1s2coupling} or more generally, in the case the ordering of the external variables is different in the subsystems, a set of identities of the form $$ x_{i}^{(e)} (j) = x_c (j)$$ \end{itemize} \subsection{Examples} In this section a set of examples is provided to show how to represent some circuit topologies in the {\Iff} format, how to parse {\Iff} files and how to build the systems of equations to be solved at each linearization step within each time-step of a transient simulation. The programs shown are simplified versions of thos included in the OCS package. \begin{table} \begin{tabular}{|p{.15\linewidth}|l|l|l|l|l|} \hline description & script & flag & {\cir} file & {\nms} file & {\sbn} file(s) \\ \hline \hline %% An inverting amplifier with one n-channel MOSFET and a resistive load & \mylink{listing:runme.m}{\tt runme.m} & \mylink{listing:runme.m}{\tt nmos} & \mylink{listing:nmos.cir}{\tt nmos.cir} & \mylink{listing:nmos.nms}{\tt nmos.nms} & \begin{minipage}{.2\linewidth} \mylink{listing:Mnmosfet.m}{\tt Mnmosfet.m}\\ \mylink{listing:Mvoltagesources.m}{\tt Mvoltagesources.m}\\ \mylink{listing:Mresistors.m}{\tt Mresistors.m} \end{minipage}\\ \hline %% An inverting amplifier with one p-channel MOSFET and a resistive load & \mylink{listing:runme.m}{\tt runme.m} & \mylink{listing:runme.m}{\tt pmos} & \mylink{listing:pmos.cir}{\tt pmos.cir} & \mylink{listing:pmos.nms}{\tt pmos.nms} & \begin{minipage}{.2\linewidth} \mylink{listing:Mpmosfet.m}{\tt Mpmosfet.m}\\ \mylink{listing:Mvoltagesources.m}{\tt Mvoltagesources.m}\\ \mylink{listing:Mresistors.m}{\tt Mresistors.m} \end{minipage}\\ \hline %% A CMOS inverter with one n-channel and one p-channel MOSFET & \mylink{listing:runme.m}{\tt runme.m} & \mylink{listing:runme.m}{\tt inverter} & \mylink{listing:inverter.cir}{\tt inverter.cir} & \mylink{listing:inverter.nms}{\tt inverter.nms} & \begin{minipage}{.2\linewidth} \mylink{listing:Mpmosfet.m}{\tt Mpmosfet.m}\\ \mylink{listing:Mvoltagesources.m}{\tt Mvoltagesources.m}\\ \mylink{listing:Mnmosfet.m}{\tt Mnmosfet.m} \end{minipage}\\ \hline %% A CMOS AND gate with three n-channel and three p-channel MOSFETs & \mylink{listing:runme.m}{\tt runme.m} & \mylink{listing:runme.m}{\tt and} & \mylink{listing:and.cir}{\tt and.cir} & \mylink{listing:and.nms}{\tt and.nms} & \begin{minipage}{.2\linewidth} \mylink{listing:Mpmosfet.m}{\tt Mpmosfet.m}\\ \mylink{listing:Mvoltagesources.m}{\tt Mvoltagesources.m}\\ \mylink{listing:Mnmosfet.m}{\tt Mnmosfet.m} \end{minipage}\\ \hline %% An inverting amplifier with one n-channel MOSFET and a capacitive load & \mylink{listing:runmedaspk.m}{\tt runmedaspk.m} & \mylink{listing:runmedaspk.m}{\tt nmos2} & \mylink{listing:nmos2.cir}{\tt nmos2.cir} & \mylink{listing:nmos2.nms}{\tt nmos2.nms} & \begin{minipage}{.2\linewidth} \mylink{listing:Mvoltagesources.m}{\tt Mvoltagesources.m}\\ \mylink{listing:Mnmosfet.m}{\tt Mnmosfet.m} \mylink{listing:Mcapacitors.m}{\tt Mcapacitors.m} \end{minipage}\\ \hline %% A small element of a (lossy) transmission line modeled with lumped parameters & \mylink{listing:runmedaspk.m}{\tt runmedaspk.m} & \mylink{listing:runmedaspk.m}{\tt TLelement} & \mylink{listing:TLelement.cir}{\tt TLelement.cir} & \mylink{listing:TLelement.nms}{\tt TLelement.nms} & \begin{minipage}{.2\linewidth} \mylink{listing:Mvoltagesources.m}{\tt Mvoltagesources.m}\\ \mylink{listing:Mcapacitors.m}{\tt Mcapacitors.m} \mylink{listing:Minductors.m}{\tt Minductors.m} \end{minipage}\\ \hline \end{tabular} \caption{List of examples}\label{tab:exmpl} \end{table} \subsubsection{A CMOS AND Gate} In this section we discuss in slightly deeper detail the CMOS AND gate example, to point out more clearly some features of the {\Iff} format. \autoref{fig:and} depicts the schematic of the circuit, while \autoref{fig:andout} represents the output of a transient simulation. The file \mylink{listing:runme.m}{\tt runme.m} is a script that performs all the operations needed to simulate transient behavior of the circuit at hand. Notice that a time independent model is used for the MOSFETs (for the description of the adopted model see~\cite{neamen} Sec.11.3) and that no energy storing elements are present in the circuit so no time discretization is used and at each time-step a non-linear system of equations is solved via a damped Newton method. The main steps of the simulation are the following: \begin{itemize} \item Parsing the {\cir} and {\nms} files. This is accomplished by the call \begin{lstlisting} outstruct = parseIFF("and"); \end{lstlisting} it produces as output the structure {\tt outstruct } which will be described below. \item Initializing the system. This is accomplished by the call \begin{lstlisting} [A,Jac,res,B,C,outstruct] = initsystemIFF(outstruct,x,t(0)); \end{lstlisting} which builds the linear and time independent matrices {\tt A}, {\tt B} and {\tt C} and the initial value of the Jacobian matrix {\tt Jac} and of the residual {\tt res}. \item Cycle over time-steps and Newton steps \begin{lstlisting} for it=1:length(t) for ii=1:maxit ... end end \end{lstlisting} \item Rebuild time or state dependent components of the system \begin{lstlisting} [A,Jac,res] = buildsystemIFF(outstruct,x,t(it)); \end{lstlisting} \item Update the state vector \begin{lstlisting} xnew = (B+Jac)\(-res - C + Jac*x); x = (1-damp)*x+damp*xnew; \end{lstlisting} \item Plot the solution \begin{lstlisting} plotbynameIFF(t(1:it),out,outstruct,pltvars) \end{lstlisting} \end{itemize} The run-time representation of the circuit that {\tt parseIFF} builds from the {\Iff} file is the {\tt outstruct} structure which is composed as follows: \begin{lstlisting} outstruct = { LCR: struct % the fields of LCR are shown below NLC: struct % NLC has the same fields as LCR namesn: matrix % numbers of vars that are assigned a name in and.nms namess: cell % the names corresponding to the vars above totextvar: scalar % the total number of external variables totintvar: scalar % the total number of internal variables } outstruct.LCR = { 1x2 struct array containing the fields: % array has one element per block func % name of the sbn file corresponding to each block section % string parameter to be passed to the sbn files nextvar % number of external variables for each element of the block vnmatrix % numbers of the external variables of each element nintvar % number of internal variables for each element of the block osintvar % number of the first internal variable npar % number of parameters nparnames% number of parameter names nrows % number of rows in the block parnames % list of parameter names pvmatrix % list of parameter values for each element } \end{lstlisting} \begin{figure} \begin{center} \includegraphics[width=.99\linewidth]{AND_BW.png} \end{center} \caption{Schematic of a CMOS AND Gate}\label{fig:and} \end{figure} \begin{figure} \begin{center} \includegraphics[width=.66\linewidth]{and_output.png} \end{center} \caption{Result of the CMOS AND Gate transient simulation}\label{fig:andout} \end{figure} %\part*{Appendices} %\appendix \subsection{Source Code of the Examples}\label{app:source} \subsubsection{{\sbn} Files } \mylistingm{Mvoltagesources} \mylistingm{Mcurrentsources} \mylistingm{Mresistors} \mylistingm{Mnmosfet} \mylistingm{Mpmosfet} \mylistingm{Minductors} \mylistingm{Mcapacitors} \subsubsection{{\cir} and {\nms} Files} \mylisting{nmos.cir} \mylisting{nmos.nms} \mylisting{pmos.cir} \mylisting{pmos.nms} \mylisting{inverter.cir} \mylisting{inverter.nms} \mylisting{and.cir} \mylisting{and.nms} \mylisting{nmos2.cir} \mylisting{nmos2.nms} \mylisting{TLelement.cir} \mylisting{TLelement.nms} \subsubsection{Example Parser and Matrix Asembler} \mylistingm{parseIFF} \mylistingm{initsystemIFF} \mylistingm{buildsystemIFF} \subsubsection{Example Transient Simulations} \mylistingm{runme} \mylistingm{runmedaspk} \mylistingm{plotbynameIFF} \mylistingm{funres} \mylistingm{funjac} \end{document}ocs/doc/initsystemIFF.m_in0000644000076500000000000001000511533542746014774 0ustar carlowheelfunction [varargout] = initsystemIFF(instruct,x); ## Check number of internal variables intvar = 0; ## NLC section nblocks = length(instruct.NLC); for ibl = 1:nblocks for iel = 1:instruct.NLC(ibl).nrows ## evaluate element il = instruct.NLC(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil)=x(il(nzil)); [a,b,c] = feval(instruct.NLC(ibl).func,... instruct.NLC(ibl).section,... instruct.NLC(ibl).pvmatrix(iel,:),... instruct.NLC(ibl).parnames,... y,[],0); instruct.NLC(ibl).nintvar(iel) = columns(a)-instruct.NLC(ibl).nextvar; instruct.NLC(ibl).osintvar(iel) = intvar; intvar += instruct.NLC(ibl).nintvar(iel); end ## endfor end ## endfor ## LCR section nblocks = length(instruct.LCR); for ibl = 1:nblocks for iel = 1:instruct.LCR(ibl).nrows ## evaluate element il = instruct.LCR(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil)=x(il(nzil)); [a,b,c] = feval(instruct.LCR(ibl).func,... instruct.LCR(ibl).section,... instruct.LCR(ibl).pvmatrix(iel,:),... instruct.LCR(ibl).parnames,... y,[],0); instruct.LCR(ibl).nintvar(iel) = columns(a)-instruct.LCR(ibl).nextvar; instruct.LCR(ibl).osintvar(iel) = intvar; intvar += instruct.LCR(ibl).nintvar(iel); end ## endfor end ## endfor instruct.totintvar = intvar; ##################################### ## ## Build initial system ## ##################################### n = instruct.totextvar+instruct.totintvar; A = spalloc(n,n,0); ###### ## LCR section ###### B = spalloc(n,n,0); C = spalloc(n,1,0); nblocks = length(instruct.LCR); for ibl = 1:nblocks for iel = 1:instruct.LCR(ibl).nrows ## evaluate element if instruct.LCR(ibl).nintvar(iel) intvars = instruct.totextvar+instruct.LCR(ibl).osintvar(iel)+... [1:instruct.LCR(ibl).nintvar(iel)]'; else intvars=[]; end il = instruct.LCR(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil)=x(il(nzil)); z = x(intvars); [a,b,c] = feval(instruct.LCR(ibl).func,... instruct.LCR(ibl).section,... instruct.LCR(ibl).pvmatrix(iel,:),... instruct.LCR(ibl).parnames,... y,z,0); ## assemble matrices vars = [il;intvars]; for irow=1:rows(a) if (vars(irow)) for icol=1:columns(a) if (vars(icol)) A(vars(irow),vars(icol)) += a(irow,icol); B(vars(irow),vars(icol)) += b(irow,icol); end ## endif end ## endfor C(vars(irow)) += c(irow); end ## endif end ## endfor end ## endfor end ## endfor varargout{4}=B; varargout{5}=C; end ## endif ###### ## NLC section ###### Jac = spalloc(n,n,0); res = spalloc(n,1,0); nblocks = length(instruct.NLC); for ibl = 1:nblocks for iel = 1:instruct.NLC(ibl).nrows ## evaluate element if instruct.NLC(ibl).nintvar(iel) intvars = instruct.totextvar+instruct.NLC(ibl).osintvar(iel)+... [1:instruct.NLC(ibl).nintvar(iel)]'; else intvars=[]; end il = instruct.NLC(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil)=x(il(nzil)); z = x(intvars); [a,b,c] = feval(instruct.NLC(ibl).func,... instruct.NLC(ibl).section,... instruct.NLC(ibl).pvmatrix(iel,:),... instruct.NLC(ibl).parnames,... y,z,0); ## assemble matrices vars = [il;intvars]; for irow=1:rows(a) if (vars(irow)) for icol=1:columns(a) if (vars(icol)) A(vars(irow),vars(icol)) += a(irow,icol); Jac(vars(irow),vars(icol)) += b(irow,icol); end ## endif end ## endfor res(vars(irow)) +=... c(irow); end ## endif end ## endfor end ## endfor end ## endfor varargout{1}=A; varargout{2}=Jac; varargout{3}=res; varargout{6}=instruct; ocs/doc/inverter.cir0000644000076500000000000000062211005317740013720 0ustar carlowheel%0.1b1 % A Simple MOSFET inverter % Input voltage sources Mvoltagesources sinwave 3 4 1 4 Ampl f delay shift 0.5 1 0.0 0.5 1 0 4 % P-Mosfet Mpmosfet simple 4 3 1 3 k Vth rd -1e-4 -0.1 1e6 1 3 2 3 % N-Mosfet Mnmosfet simple 4 3 1 3 k Vth rd 1e-4 0.1 1e6 1 0 2 0 END % Power supply Mvoltagesources DC 3 1 1 1 V 1 3 0 5 END ocs/doc/inverter.nms0000644000076500000000000000003111005317740013732 0ustar carlowheel% 0.1b1 1 Vgate 2 Vdrain ocs/doc/inverter.spc0000755000076500000000000000042611706574500013744 0ustar carlowheel* A Simple MOSFET inverter * Input voltage sources V1 Vgate 0 SIN(0.5 0.5 1 0 0) * P-Mosfet .MODEL mypmos PMOS( k=-1e-4 Vth=-0.1 rd=1e6) M2 Vgate 3 Vdrain 3 mypmos * N-Mosfet .MODEL mynmos NMOS( k=1e-4 Vth=0.1 rd=1e6) M3 Vgate 0 Vdrain 0 mynmos * Power supply V4 3 0 1 .END ocs/doc/Mcapacitors.m_in0000644000076500000000000000103611533542746014510 0ustar carlowheelfunction [a,b,c] =... Mcapacitors(string,parameters,parameternames,extvar,intvar,t) ## Mcapacitors(string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) intvar = 0; end switch string case "LIN" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end q = intvar(1); a = [0 0 1; 0 0 -1; 0 0 0]; b = [0 0 0;0 0 0;C -C -1]; c = [0 0 0]'; break otherwise error (["unknown section:" string]) end ocs/doc/Mcurrentsources.m_in0000644000076500000000000000132311533542746015445 0ustar carlowheelfunction [a,b,c] =... Mcurrentsources(string,parameters,parameternames,extvar,intvar,t) ## [a,b,c] = ... ## Mcurrentsources(string,parameters,parameternames,extvar,intvar,t) switch string case "DC" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end a = zeros(2); b = a; c = [I -I]'; break case "sinwave" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end I = shift+Ampl * sin(2*pi*(t+delay)*f ); a = zeros(2); b = a; c = [I -I]'; break otherwise error (["unknown section:" string]) end ocs/doc/Minductors.m_in0000644000076500000000000000111211533542746014365 0ustar carlowheelfunction [a,b,c] =... Minductors(string,parameters,parameternames,extvar,intvar,t) ## Minductors(string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) intvar = [0 0]; end switch string case "LIN" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end phi = intvar(1); jl = intvar(2); a = [0 0 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 -L]; b = [0 0 -1 0; 0 0 0 1; 1 -1 -1 0; 0 0 1 0]; c = [0 0 0 0]'; otherwise error (["unknown section:" string]) end ocs/doc/Mnmosfet.m_in0000644000076500000000000000213611533542746014035 0ustar carlowheelfunction [a,b,c]=Mnmosfet... (string,parameters,parameternames,extvar,intvar,t) ## [a,b,c]=Mnmosfet... ## (string,parameters,parameternames,extvar,intvar,t) switch string case 'simple', rd = 1e6; for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]) end vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); vgs = vg-vs; vds = vd-vs; if (vgs < Vth) gm = 0; gd = 1/rd; id = vds*gd; elseif ((vgs-Vth)>=(vds))&(vds>=0) id = k*((vgs-Vth)*vds-(vds^2)/2)+vds/rd; gm = k*vds; gd = k*(vgs-Vth-vds)+1/rd; elseif ((vgs-Vth)>=(vds))&(vds<0) gm = 0; gd = 1/rd; id = vds*gd; else # (i.e. if 0 <= vgs-vth <= vds) id = k*(vgs-Vth)^2/2+vds/rd; gm = k*(vgs-Vth); gd = 1/rd; end a = zeros(4); b = [0 0 0 0; -gm (gm+gd) -gd 0; gm -(gm+gd) gd 0; 0 0 0 0]; c = [0 -id id 0]'; break; otherwise error(["unknown option:" string]); end ocs/doc/Mpmosfet.m_in0000644000076500000000000000211611533542746014035 0ustar carlowheelfunction [a,b,c]=Mpmosfet... (string,parameters,parameternames,extvar,intvar,t) ## [a,b,c]=Mpmosfet... ## (string,parameters,parameternames,extvar,intvar,t) switch string case 'simple', rd = 1e6; for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]); end vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); vgs = vg-vs; vds = vd-vs; if (vgs > Vth) gm = 0; gd = 1/rd; id = vds*gd; elseif ((vgs-Vth)<=(vds))&(vds<=0) id = k*((vgs-Vth)*vds-(vds^2)/2)+vds/rd; gm = k*vds; gd = k*(vgs-Vth-vds)+1/rd; elseif ((vgs-Vth)<=(vds))&(vds>0) gm = 0; gd = 1/rd; id = vds*gd; else id = k*(vgs-Vth)^2/2+vds/rd; gm = k*(vgs-Vth); gd = 1/rd; end a = zeros(4); b = [0 0 0 0; -gm (gm+gd) -gd 0; gm -(gm+gd) gd 0; 0 0 0 0 ]; c =[0 -id id 0]'; break; otherwise error(["unknown option:" string]); end ocs/doc/Mresistors.m_in0000644000076500000000000000103711533542746014416 0ustar carlowheelfunction [a,b,c] =... Mresistors(string,parameters,parameternames,extvar,intvar,t) ## [a,b,c] = Mresistors(string,parameters,parameternames,extvar,intvar,t) switch string case "LIN" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end vp = extvar(1); vm = extvar(2); a = zeros(2); b = [1 -1 ;-1 1]/R; c = -[0; 0]; break otherwise error (["unknown section:" string]) end ocs/doc/Mvoltagesources.m_in0000644000076500000000000000237511533542746015434 0ustar carlowheelfunction [a,b,c] =... Mvoltagesources(string,parameters,parameternames,extvar,intvar,t) ## Mvoltagesources(string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) intvar = 0; end switch string case "DC" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end j = intvar(1); a = zeros(3); b = [0 0 1;0 0 -1;1 -1 0]; c = [0 0 -V]; break case "sinwave" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end DV = shift+Ampl * sin(2*pi*(t+delay)*f ); j = intvar(1); a = zeros(3); b = [0 0 1;0 0 -1;1 -1 0]; c = [0 0 -DV]' + b * [extvar;intvar]; break case "squarewave" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end if t0)|(ii>1) [A,Jac,res] = buildsystemIFF(outstruct,x,t(it)); end xnew = (B+Jac)\(-res - C + Jac*x); nrm(it) = norm(x-xnew,inf); damp = dmp; if (ii>2)&(nrm(it)1 axis([min(t) max(t) 0 1]); plotbynameIFF(t(1:it),out,outstruct,pltvars) end end ocs/doc/runme.m_in0000644000076500000000000000265211533542746013376 0ustar carlowheelexmpl ="nmos" out=[]; nrm=[]; switch exmpl case "nmos" outstruct = parseIFF("nmos"); x = [1 .03 1 0 0]'; t = linspace(0,1,50); dmp = .1; pltvars={"Vgate","Vdrain"}; case "pmos" outstruct = parseIFF("pmos"); x = [1 .1 1 0 -1e-6]'; t = linspace(0,.5,50) dmp = .1; pltvars={"Vgate","Vdrain"}; case "inverter" outstruct = parseIFF("inverter"); x = [.5 .5 1 0 0]'; t = linspace(0,1,50); dmp=.1; pltvars={"Vgate","Vdrain"}; case "and" outstruct = parseIFF("and"); x = [.5 .5 .33 .66 .5 1 0 0 1]'; t = linspace(0,.5,50); dmp = .1; pltvars = {"Va","Vb","Va_and_b"}; end tol = 1e-6; dtol= 1e-5; maxit = 200; [A,Jac,res,B,C,outstruct] = initsystemIFF(outstruct,x,0); for it=1:length(t) for ii=1:maxit if (t(it)>0)|(ii>1) [A,Jac,res] = buildsystemIFF(outstruct,x,t(it)); end xnew = (B+Jac)\(-res - C + Jac*x); nrm(it) = norm(x-xnew,inf); damp = dmp; if (ii>2)&(nrm(it)1 axis([min(t) max(t) 0 1]); plotbynameIFF(t(1:it),out,outstruct,pltvars) end end ocs/doc/runmedaspk.m_in0000644000076500000000000000140711533542746014416 0ustar carlowheelexmpl ="nmos" out=[]; nrm=[]; switch exmpl case "nmos" outstruct = parseIFF("nmos2"); x = [0 1 1 0 0 0 ]'; t = linspace(0,10,200); pltvars={"Vgate","Vdrain"}; case "TLelement" outstruct = parseIFF("TLelement"); x = [0 0 0 0 0 ]'; t = linspace(0,1,200); pltvars={"Vin","Vout"}; end global A_MATRIX_IFF B_MATRIX_IFF C_MATRIX_IFF OUTSTRUCT_IFF [A_MATRIX_IFF,Jac,res,B_MATRIX_IFF,C_MATRIX_IFF,OUTSTRUCT_IFF] =... initsystemIFF(outstruct,x,0); daspk_options("algebraic variables",[1 1 1 1 1 0 ]'); daspk_options("compute consistent initial condition",2); #daspk_options("relative tolerance",1e-); [x,xdot,istate,msg]= daspk(["funres";"funjac"],x,zeros(size(x)),t); axis([min(t) max(t) 0 1]); plotbynameIFF(t,x',OUTSTRUCT_IFF,pltvars) ocs/doc/spice2ocs_demo.m_in0000755000076500000000000000573211706605532015146 0ustar carlowheelclear all; clc; ## Circuit cir = menu ("Chose the circuit to analyze:",\ "AND (Simple algebraic MOS-FET model)",\ "AND (Simple MOS-FET model with parasitic capacitances)",\ "Diode clamper (Simple exponential diode model)",\ "CMOS-inverter circuit (Simple algebraic MOS-FET model)",\ "n-MOS analog amplifier (Simple algebraic MOS-FET model)",\ "Linear RC circuit",\ "Diode bridge rectifier"); switch cir case 1 outstruct = prs_spice ("and"); x = [.5 .5 .33 .66 .5 1 0 0 1 ]'; t = linspace (0,.5,100); pltvars = {"Va","Vb","Va_and_b"}; dmp = .2; tol = 1e-15; maxit = 100; case 2 outstruct = prs_spice ("and2") x = [.8;.8;0.00232;0.00465;.8; .8;0.00232;0.00465;0.00000; 0.0;0.0;0.0;0.00232;0.0; 0.0;0.0;0.0;1.0;0.0;-0.0; 0.0;1.0;0.00465;0.0;0.0; -0.0;1.0;0.00465;0.0; 0.0;0.0;1.0;1.0;0.0;0.0;0.0; 0.0;0.0;0.0]; t = linspace (.25e-6,.5e-6,100); dmp = .1; pltvars = {"Va","Vb","Va_and_b"}; tol = 1e-15; maxit = 100; case 3 outstruct = prs_spice ("diode"); x = [0 0 0 0 0]'; t = linspace (0, 3e-10, 200); dmp = .1; pltvars = {"Vin", "Vout","V2"}; tol = 1e-15; maxit = 100; case 4 outstruct = prs_spice ("inverter"); x = [.5 .5 1 0 0]'; t = linspace (0,1,100); dmp = .1; pltvars={"Vgate","Vdrain"}; tol = 1e-15; maxit = 100; case 5 outstruct = prs_spice ("nmos"); x = [1 .03 1 0 0]'; t = linspace (0,1,50); dmp = .1; pltvars = {"Vgate","Vdrain"}; tol = 1e-15; maxit = 100; case 6 outstruct = prs_spice ("rcs"); x = [0 0 0 0]'; t = linspace (0,2e-5,100); dmp = 1; pltvars = {"Vout"}; tol = 1e-15; maxit = 100; case 7 outstruct = prs_spice ("rect"); x = [0 0 0 0 ]'; t = linspace (0, 3e-10, 60); dmp = .1; pltvars = {"Vin","Voutlow","Vouthigh"}; tol = 1e-15; maxit = 100; otherwise error ("unknown circuit"); endswitch #clc; ## DAE solver slv = menu("Chose the solver to use:", "BWEULER", # 1 "DASPK", # 2 "THETA", # 3 "ODERS", # 4 "ODESX", # 5 "ODE2R", # 6 "ODE5R" # 7 ); out = zeros(rows(x),columns(t)); switch slv case 1 out = tst_backward_euler (outstruct,x,t,tol,maxit,pltvars); case 2 out = tst_daspk (outstruct,x,t,tol,maxit,pltvars); case 3 out = tst_theta_method (outstruct,x,t,tol,maxit,.5,pltvars,[0 0]); case 4 out = tst_odepkg (outstruct,x,t,tol,maxit,pltvars,"oders",[0,1]); case 5 out = tst_odepkg (outstruct,x,t,tol,maxit,pltvars,"odesx",[0,1]); case 6 out = tst_odepkg (outstruct,x,t,tol,maxit,pltvars,"ode2r",[0,1]); case 7 out = tst_odepkg (outstruct,x,t,tol,maxit,pltvars,"ode5r",[0,1]) otherwise error ("unknown solver"); endswitch utl_plot_by_name (t,out,outstruct,pltvars); axis ("tight"); ocs/doc/spice2ocs_syntax.txt0000755000076500000000000000706511706605532015446 0ustar carlowheelspice2ocs Syntax Case ---- The parser is case sensitive for parameters, while it is insensitive for element names. Therefore vm1 1 2 3 is the same as: VM1 1 2 3 While M2 3 4 mynmos Vth=0.7 is NOT the same as: M2 3 4 mynmos vth=0.7 Representing numbers: -------------------- Both octave syntax and spice syntax are allowed to be used for representing numbers. For instance, "1U" and "1e-6" are both valid expressions for 10^(-6). SPICE syntax for numbers: MIL -> 25.4e-6 A -> 1e-18 F -> 1e-15 P -> 1e-12 N -> 1e-9 U -> 1e-6 M -> 1e-3 K -> 1e3 MEG -> 1e6 G -> 1e9 T -> 1e12 Elements Cards -------------- - Capacitors: Cname n+ n- cvalue - Diodes: Cname anode knode modelname - MOS: Mname gnode dnode snode bnode modelname N.B.: one instance of a MOS element MUST be preceeded (everywhere in the file) by the declaration of the related model. For instance: .MODEL mynmos NMOS( k=1e-4 Vth=0.1 rd=1e6) M2 Vgate 0 Vdrain 0 mynmos - Resistors: Rname n+ n- rvalue - Voltage sources: Vname n+ n- Transvalue specifies a transient voltage source SIN(VO VA FREQ TD THETA) where: VO (offset) VA (amplitude) FREQ (frequency) TD (delay) THETA (damping factor) 0 to TD: V0 TD to TSTOP: VO + VA*exp(-(time-TD)*THETA)*sine(twopi*FREQ*(time+TD)) Currently the damping factor has no effect. Pulse PULSE(V1 V2 TD TR TF PW PER) parameters meaning V1 (initial value) V2 (pulsed value) TD (delay time) TR (rise time) TF (fall time) PW (pulse width) PER (period) Currently rise and fall time are not implemented yet. - .MODEL cards Defines a model for semiconductor devices .MODEL MNAME TYPE(PNAME1=PVAL1 PNAME2=PVAL2 ... ) TYPE can be: NMOS N-channel MOSFET model PMOS P-channel MOSFET model D diode model The parameter "LEVEL" is currently assigned to the field "section" in the call of the element functions by the solver. Currently supported values for the parameter LEVEL for NMOS and PMOS are: - simple - lincap (see OCS documentation of function Mdiode). Currently supported values for the parameter LEVEL for D are: - simple (see OCS documentation of functions Mdiode and Mpmosfet). Variable names -------------- While in IFF, the variable names are specified into an .nms file, using spice2ocs the variable names are automatically generated by te parser. Particularly, each node is identified by a name (string), related to a(-n external) variable into the state matrix vector. The ground node (index 1 into the variable vector) is by default assigned to the name "0", and it must always appear into the netlist. The parser assigns to each node name an index into the state variable vector. The assigned index depends on the order of appearance of the node name into the netlist. Internal variables represent currents and charges into the system. The name of the internal variables is automatically generated by the parser. For instance, given the element V1 Va Vb 1 It will be related to the variable I(V1) into the vector outstruct.namesn. outstruct.namesn{iv1}="I(V1)" If more internal variables belong to a same element, a variable name is generated just for the first variable. For instance: if the element V1 had 3 internal variables starting from the index iv1, it would result: outstruct.namesn{iv1}="I(V1)" outstruct.namesn{iv1+1}="" outstruct.namesn{iv1+2}="" One is allowed to plot internal and/or external variable of a circuit solved (out) by IFF, by listing them into the pltvars field, when calling the function utl_plot_by_name (t, out, outstruct, pltvars); ocs/doc/TLelement.cir0000644000076500000000000000047611005317740013762 0ustar carlowheel% 0.1b1 % A transmition line element % Input voltage source Mvoltagesources sinwave 2 4 1 4 Ampl f delay shift .5 1 0.75 0.5 1 0 END % Resistors Mresistors LIN 2 1 1 1 R 1e6 2 0 % Capacitors %Mcapacitors LIN 2 1 %1 1 %C %1e-7 %3 0 % Inductors Minductors LIN 2 1 1 1 L 1e5 1 2 END ocs/doc/TLelement.nms0000644000076500000000000000003211005317740013766 0ustar carlowheel% 0.1b1 1 Vin 2 Vrl 3 Voutocs/INDEX0000644000076500000000000000075611334211056011416 0ustar carlowheelOCS >> Octave Circuit Simulator Matrix Assembly Functions asm_initialize_system asm_build_system Netlist Parsing Functions prs_iff Time Stepping Functions tst_backward_euler tst_daspk tst_theta_method tst_odepkg Non Linear Solvers nls_stationary nls_newton_raphson UTiLity Functions utl_plot_by_name utl_sbn_server SuBNet Function Library Mcapacitors Mcurrentsources Mdiode Minductors Mnmosfet Mpmosfet Mresistors Mshichmanhodgesmosfet Mvoltagesources ocs/inst/0000755000076500000000000000000011706606202011575 5ustar carlowheelocs/inst/asm/0000755000076500000000000000000011706606201012354 5ustar carlowheelocs/inst/asm/asm_build_system.m0000644000076500000000000000640111334211056016073 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco, Culpo Massimiliano ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## author: culpo@math.uni-wuppertal.de ## -*- texinfo -*- ## @deftypefn{Function File} {[@var{A},@var{Jac},@var{res}] =}@ ## asm_build_system(@var{instruct},@var{x},@var{t}) ## ## Cycle through the circuit description structure @var{instruct} ## to build the system matrices @var{A}, @var{Jac}, @var{res} for ## the current step of the Newton method. ## ## @var{x} is the current value of the state variables, while @var{t} is the current time point. ## ## See the @cite{IFF file format specifications} for details about ## the output matrices. ## ## @seealso{asm_initialize_system,prs_iff} ## ## @end deftypefn function [A,Jac,res] = asm_build_system(instruct,x,t); ## Check input if nargin != 3 error("asm_build_system: wrong number of input parameters."); elseif !(isstruct(instruct) && isfield(instruct,"LCR") && isfield(instruct,"NLC")) error("asm_build_system: first input is not a valid structure."); elseif !isvector(x) error("asm_build_system: second input is not a valid vector."); elseif !isscalar(t) error("asm_build_system: third input is not a valid scalar."); endif n = instruct.totextvar + instruct.totintvar; A = sparse(n,n); Jac = sparse(n,n); res = sparse(n,1); ## NLC section nblocks = length(instruct.NLC); for ibl = 1:nblocks for iel = 1:instruct.NLC(ibl).nrows ## Evaluate element if instruct.NLC(ibl).nintvar(iel) intvars = instruct.totextvar+instruct.NLC(ibl).osintvar(iel) + \ [1:instruct.NLC(ibl).nintvar(iel)]'; else intvars=[]; endif il = instruct.NLC(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil) = x(il(nzil)); z = x(intvars); [a,b,c] = feval(instruct.NLC(ibl).func,\ instruct.NLC(ibl).section,\ instruct.NLC(ibl).pvmatrix(iel,:),\ instruct.NLC(ibl).parnames,\ y,z,t); ## Assemble matrices ## Global indexing vars = [il(nzil);intvars]; ## Local indexing lclvars = [nzil; instruct.NLC(ibl).nextvar + (1:length(intvars))' ]; ## Reshaping sparse stamps a = a(lclvars,lclvars); b = b(lclvars,lclvars); c = reshape(c(lclvars),[],1); [na,ma,va] = find(a); [nb,mb,vb] = find(b); [nc,mc,vc] = find(c); ## Stamping A += sparse(vars(na),vars(ma),va,n,n); Jac += sparse(vars(nb),vars(mb),vb,n,n); res += sparse(vars(nc),1,vc,n,1); endfor endfor endfunctionocs/inst/asm/asm_initialize_system.m0000644000076500000000000000657111703660103017146 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco, Culpo Massimiliano ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## author: culpo@math.uni-wuppertal.de ## -*- texinfo -*- ## ## @deftypefn{Function File} {[@var{A},@var{B},@var{C}] =}@ ## asm_initialize_system(@var{instruct},@var{x}) ## ## Cycle through the circuit description structure @var{instruct} ## to build the system matrices @var{A}, @var{B}, @var{C} for ## the linear and time-invariant part of the system. ## ## @var{x} is the current value of the state variables. ## ## See the @cite{IFF file format specifications} for details about ## the output matrices. ## ## @seealso{asm_build_system,prs_iff} ## ## @end deftypefn function [A,B,C] = asm_initialize_system(instruct,x); ## Check input if nargin != 2 error("asm_initialize_system: wrong number of input parameters."); elseif !(isstruct(instruct) && isfield(instruct,"LCR") && isfield(instruct,"NLC")) error("asm_initialize_system: first input is not a valid structure."); elseif !isvector(x) error("asm_initialize_system: second input is not a valid vector."); endif ## Build linear part of the system n = instruct.totextvar + instruct.totintvar; # Number of variables ## Initialize to zero any state variable that is not in the input argument lx = length(x); if lx < n x(lx+1:n) = 0; endif ## FIXME: should a warning be passed if lx != n ? A = sparse(n,n); ## LCR section B = sparse(n,n); C = sparse(n,1); nblocks = length(instruct.LCR); for ibl = 1:nblocks for iel = 1:instruct.LCR(ibl).nrows ## Evaluate element if instruct.LCR(ibl).nintvar(iel) intvars = instruct.totextvar + instruct.LCR(ibl).osintvar(iel) + [1:instruct.LCR(ibl).nintvar(iel)]'; else intvars=[]; endif il = instruct.LCR(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil) = x(il(nzil)); z = x(intvars); [a,b,c] = feval(instruct.LCR(ibl).func, instruct.LCR(ibl).section, instruct.LCR(ibl).pvmatrix(iel,:), instruct.LCR(ibl).parnames, y,z,0); ## Assemble matrices ## Global indexing vars = [il(nzil);intvars]; ## Local indexing lclvars = [nzil; instruct.LCR(ibl).nextvar + (1:length(intvars))' ]; ## Reshaping sparse stamps a = a(lclvars,lclvars); b = b(lclvars,lclvars); c = reshape(c(lclvars),[],1); [na,ma,va] = find(a); [nb,mb,vb] = find(b); [nc,mc,vc] = find(c); ## Stamping A += sparse(vars(na),vars(ma),va,n,n); B += sparse(vars(nb),vars(mb),vb,n,n); C += sparse(vars(nc),1,vc,n,1); endfor endfor endfunctionocs/inst/nls/0000755000076500000000000000000011706606202012371 5ustar carlowheelocs/inst/nls/nls_newton_raphson.m0000644000076500000000000000636611334211056016476 0ustar carlowheel## Copyright (C) 2006-2009 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## author: Massimiliano Culpo ## -*- texinfo -*- ## @deftypefn{Function File}{[@var{y},@var{numit},@var{resnrm}] =} @ ## nls_newton_raphson (@var{y0},@var{RES},@var{JAC},@var{tol},@ ## @var{maxit},@var{verbosity},@var{update}); ## ## Solve a non-linear system of equations using the Newton-Raphson ## method with damping and return the computed solution vector @var{y}. ## ## The initial guess for the algorithm is set to @var{y0}. ## ## The Jacobian and residual at each step are computed via the function ## handles @var{RES} and @var{JAC}. ## ## The variables @var{tol} and @var{maxit} are the relative tolerance on the ## error of the computed solution and the maximum number of iterations to be ## performed by the algorithm. ## ## The optional parameter @var{verbosity} produce verbose output if non-zero. ## ## The optional function handle @var{update} may be used to provide ## a faster mean to update Jacobian and residual at runtime. ## ## @var{numit} is the number of performed iterations while @var{resnrm} ## is a vector containing the residual norm at each step. ## ## @seealso{nls_stationary,tst_backward_euler,tst_theta_method,tst_daspk,tst_odepkg} ## @end deftypefn function [y,ii,resnrm] = nls_newton_raphson(y0,RES,JAC,tol,maxit,\ verbosity,update); ## Check input ## FIXME: add input check! if ((nargin < 5) || (nargin > 7)) error("nls_newton_raphson: wrong number of input parameters."); endif if ~exist("verbosity") verbosity = 0; endif if ~exist("update") update = @(x) ({}); endif jjtot = 0; y = y0; uptodate = update(y); res_y = RES(y,uptodate{:}); resnrm(1) = norm(res_y,inf); for ii = 1:maxit jac_y = JAC(y,uptodate{:}); ynew = jac_y\(-res_y+jac_y*y); uptodate = update(ynew); res_y = RES(ynew,uptodate{:}); resnrm(ii+1) = norm(res_y,inf); jj = 0; while ((resnrm(ii+1)>resnrm(ii))&&(jj<10)) jj++; damp = 2^(-jj); ynew = y*(1-damp) + ynew*damp; uptodate = update(ynew); res_y = RES(ynew,uptodate{:}); resnrm(ii+1) = norm(res_y,inf); endwhile jjtot += jj; y = ynew; if resnrm(ii+1). ## ## author: Carlo de Falco ## -*- texinfo -*- ## @deftypefn{Function File} {[@var{out}, @var{niter}]} = nls_stationary @ ## (@var{instruct},@var{x},@var{tol},@var{maxit}) ## Compute the stationary state solution @var{out} of the system described ## by @var{instruct}. ## ## @var{x} is the initial guess used by the Newton-Raphson algorithm implemented in ## @code{nls_newton_raphson}, while @var{tol} and @var{maxit} are the corresponding ## parameters. ## ## The optional output @var{niter} returns the number of Newton iterations ## needed to reach convergence. ## ## @seealso{nls_newton_raphson} ## @end deftypefn function [out, varargout] = nls_stationary(outstruct,x,tol,maxit) ## Check input ## FIXME: add input check! if nargin != 4 error("nls_stationary: wrong number of input parameters."); endif [A0,B,C] = asm_initialize_system(outstruct,x); JAC = @(x) TSTSTATFUNJAC(outstruct,x,B); RES = @(x) TSTSTATFUNRES(outstruct,x,B,C); UPD = @(x) TSTSTATUP(outstruct,x); [out,ii,resnrm] = nls_newton_raphson(x,RES,JAC,tol,maxit,0,UPD); if nargin > 1 varargout{1} = ii; endif endfunction ## Jacobian for steady state problems function lhs = TSTSTATFUNJAC(outstruct,x,B,Jac,res) if nargin < 5 [A1,Jac,res] = asm_build_system(outstruct,x,0); endif lhs = (B + Jac); endfunction ## Residual for steady state problem function rhs = TSTSTATFUNRES(outstruct,x,B,C,Jac,res) if nargin < 6 [A1,Jac,res] = asm_build_system(outstruct,x,0); endif rhs = (res + C + B*x); endfunction ## Update for transient problem function update = TSTSTATUP(outstruct,x) [A1,Jac,res] = asm_build_system(outstruct,x,0); update = {Jac,res}; endfunctionocs/inst/prs/0000755000076500000000000000000011706606202012401 5ustar carlowheelocs/inst/prs/prs_iff.m0000644000076500000000000002235111706605115014214 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with OCS; If not, see . ## ## author: Carlo de Falco ## author: Massimiliano Culpo ## -*- texinfo -*- ## @deftypefn{Function File} @var{outstruct} = prs_iff(@var{name}) ## Parse a netlist in IFF format and produce the system description ## structure @var{outstruct}. ## ## @var{name} is the basename of the CIR and NMS files to ## be parsed. ## ## See the @cite{IFF file format specifications} (distributed together ## with the OCS package) for more details on the file format. ## ## @var{outstruct} has the following fields: ## ## @example ## outstruct = ## @{ ## LCR: struct % the fields of LCR are shown below ## NLC: struct % NLC has the same fields as LCR ## namesn: matrix % numbers of vars named in .nms file ## namess: cell % the names corresponding to the vars above ## totextvar: scalar % the total number of external variables ## totintvar: scalar % the total number of internal variables ## @} ## ## outstruct.LCR = ## outstruct.NLC = ## @{ ## struct array containing the fields: % array has one element per block ## ## func % name of the sbn file corresponding to each block ## section % string parameter to be passed to the sbn files ## nextvar % number of external variables for each element of the block ## vnmatrix % numbers of the external variables of each element ## nintvar % number of internal variables for each element of the block ## osintvar % number of the first internal variable ## npar % number of parameters ## nparnames% number of parameter names ## nrows % number of rows in the block ## parnames % list of parameter names ## pvmatrix % list of parameter values for each element ## ## @} ## @end example ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## @seealso{prs_spice} ## @end deftypefn function outstruct = prs_iff(name) ## Check input if (nargin != 1 || !ischar(name)) error("prs_iff: wrong input.") endif ## Initialization version ="0.1b1"; outstruct = struct("NLC",[],\ "LCR",[],\ "totextvar",0); ## Open cir file filename = [name ".cir"]; if isempty(file_in_path(".",filename)) error(["prs_iff: .cir file not found:" filename]); endif fid = fopen(filename,"r"); ## Check version ## FIXME: this part can be improved a lot!! line = fgetl(fid); if line(1)!="%" error(["prs_iff: missing version number in file " filename]); endif if ~strcmp(version,sscanf(line(2:end),"%s")); error(["prs_iff: conflicting version number in file " filename]); endif ndsvec = []; # Vector of circuit nodes intvar = 0; # Number of internal variables ## NLC section NLCcount = 0; while !strcmp(line,"END") ## Skip comments while line(1)=="%" line = fgetl(fid); endwhile if strcmp(line,"END") break else NLCcount++; endif ## parse NLC block [outstruct,intvar] = parseNLCblock(fid,line,outstruct,NLCcount,intvar); ndsvec = [ndsvec ; \ outstruct.NLC(NLCcount).vnmatrix(:)]; ## skip the newline char after the matrix line = fgetl(fid); ## proceed to next line line = fgetl(fid); endwhile ## LCR section LCRcount = 0; line = fgetl(fid); while (!strcmp(line,"END")) ## Skip comments while line(1)=="%" line = fgetl(fid); endwhile if strcmp(line,"END") break else LCRcount++; endif ## parse block header [outstruct,intvar] = parseLCRblock(fid,line,outstruct,LCRcount,intvar); ndsvec = [ndsvec ; \ outstruct.LCR(LCRcount).vnmatrix(:)]; ## skip the newline char after the matrix line = fgetl(fid); ## proceed to next line line = fgetl(fid); endwhile ## Set the number of internal and external variables outstruct.totintvar = intvar; nnodes = length(unique(ndsvec)); maxidx = max(ndsvec); if nnodes <= (maxidx+1) ## If the valid file is a subcircuit it may happen ## that nnodes == maxidx, otherwise nnodes == (maxidx+1) outstruct.totextvar = max(ndsvec); else error("prs_iff: hanging nodes in circuit %s",name); endif ## fclose cir file fclose(fid); ## Open nms file filename = [name ".nms"]; if isempty(file_in_path(".",filename)) error(["prs_iff: .nms file not found:" filename]); endif fid = fopen(filename,"r"); ## Check version line = fgetl(fid); if line(1)~="%" error(["prs_iff: missing version number in file " filename]); endif if ~strcmp(version,sscanf(line(2:end),"%s")); error(["prs_iff: conflicting version number in file " filename]); endif ## Initialization cnt = 1; outstruct.namesn = []; outstruct.namess = {}; nnames = 0; while cnt [nn,cnt] = fscanf(fid,"%d","C"); [ns,cnt] = fscanf(fid,"%s","C"); if cnt outstruct.namesn(++nnames)=nn; outstruct.namess{nnames}=ns; endif endwhile ## fclose nms file fclose(fid); endfunction ############################################## function [outstruct,intvar] = parseNLCblock(fid,line,outstruct,NLCcount,intvar); ## Parse first line of the header and retrieve: ## 1 - SBN function name ## 2 - Section ## 3 - Number of external variables ## 4 - Number of parameters [func,section,nextvar,npar] = sscanf(line,"%s %s %g %g","C"); outstruct.NLC(NLCcount).func = func; outstruct.NLC(NLCcount).section = section; outstruct.NLC(NLCcount).nextvar = nextvar; outstruct.NLC(NLCcount).npar = npar; ## Parse second line of the header and retrieve: ## 1 - Number of elements of this type ## 2 - Number of parameter names to be parsed [nrows,nparnames] = fscanf(fid,"%g %g","C"); outstruct.NLC(NLCcount).nrows = nrows; outstruct.NLC(NLCcount).nparnames = nparnames; outstruct.NLC(NLCcount).parnames = {}; for ii=1:nparnames outstruct.NLC(NLCcount).parnames{ii} = fscanf(fid,"%s","C"); endfor ## Parse the matrix containing the values of parameters [outstruct.NLC(NLCcount).pvmatrix] = fscanf(fid,"%g",[npar,nrows])'; ## Parse the connectivity matrix [outstruct.NLC(NLCcount).vnmatrix] = fscanf(fid,"%g",[nextvar,nrows])'; ## Compute internal variables cycling over each ## element in the section for iel = 1:nrows [a,b,c] = feval(func,section,outstruct.NLC(NLCcount).pvmatrix(iel,:),\ outstruct.NLC(NLCcount).parnames,zeros(nextvar,1),[],0); ## FIXME: if all the element in the same section share the ## same number of internal variables, the for cycle can be ## substituted by only one call outstruct.NLC(NLCcount).nintvar(iel) = columns(a) - outstruct.NLC(NLCcount).nextvar; outstruct.NLC(NLCcount).osintvar(iel) = intvar; intvar += outstruct.NLC(NLCcount).nintvar(iel); endfor endfunction ############################################## function [outstruct,intvar] = parseLCRblock(fid,line,outstruct,LCRcount,intvar); ## Parse first line of the header and retrieve: ## 1 - SBN function name ## 2 - Section ## 3 - Number of external variables ## 4 - Number of parameters [func,section,nextvar,npar] = sscanf(line,"%s %s %g %g","C"); outstruct.LCR(LCRcount).func = func; outstruct.LCR(LCRcount).section = section; outstruct.LCR(LCRcount).nextvar = nextvar; outstruct.LCR(LCRcount).npar = npar; ## Parse second line of the header and retrieve: ## 1 - Number of elements of this type ## 2 - Number of parameter names to be parsed [nrows,nparnames] = fscanf(fid,"%g %g","C"); outstruct.LCR(LCRcount).nrows = nrows; outstruct.LCR(LCRcount).nparnames = nparnames; outstruct.LCR(LCRcount).parnames = {}; for ii=1:nparnames outstruct.LCR(LCRcount).parnames{ii} = fscanf(fid,"%s","C"); endfor ## Parse the matrix containing the values of parameters [outstruct.LCR(LCRcount).pvmatrix] = fscanf(fid,"%g",[npar,nrows])'; ## Parse the connectivity matrix [outstruct.LCR(LCRcount).vnmatrix] = fscanf(fid,"%g",[nextvar,nrows])'; ## Compute internal variables cycling over each ## element in the section for iel = 1:nrows [a,b,c] = feval(func,section,outstruct.LCR(LCRcount).pvmatrix(iel,:),\ outstruct.LCR(LCRcount).parnames,zeros(nextvar,1),[],0); ## FIXME: if all the element in the same section share the ## same number of internal variables, the for cycle can be ## substituted by only one call outstruct.LCR(LCRcount).nintvar(iel) = columns(a) - outstruct.LCR(LCRcount).nextvar; outstruct.LCR(LCRcount).osintvar(iel) = intvar; intvar += outstruct.LCR(LCRcount).nintvar(iel); endfor endfunctionocs/inst/prs/prs_spice.m0000755000076500000000000011101111706605057014553 0ustar carlowheel## Copyright (C) 2012 Marco Merlin ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## OCS is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with OCS; If not, see . ## ## author: Marco Merlin ## based on prs_iff which is (C) Carlo de Falco and Massimiliano Culpo ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{stuct}]} = prs_spice (@var{filename}) ## ## Circuit file parser that can interpret a subset of the spice file format. ## ## @code{prs_spice} currently supports the following set of "Element Cards" ## @itemize @minus ## @item Capacitors: ## @example ## Cname n+ n- cvalue ## @end example ## ## @item Diodes: ## @example ## Cname anode knode modelname ## @end example ## ## @item MOS: ## @example ## Mname gnode dnode snode bnode modelname ## @end example ## ## N.B.: one instance of a MOS element MUST be preceeded (everywhere in the file) by the declaration of the related model. ## For instance: ## @example ## .MODEL mynmos NMOS( k=1e-4 Vth=0.1 rd=1e6) ## M2 Vgate 0 Vdrain 0 mynmos ## @end example ## ## @item Resistors: ## @example ## Rname n+ n- rvalue ## @end example ## ## @item Voltage sources: ## @example ## Vname n+ n- ## @end example ## ## Transvalue specifies a transient voltage source ## @example ## SIN(VO VA FREQ TD THETA) ## @end example ## where: ## @itemize @bullet ## @item VO (offset) ## @item VA (amplitude) ## @item FREQ (frequency) ## @item TD (delay) ## @item THETA (damping factor) ## @end itemize ## ## @itemize @bullet ## @item 0 to TD: V0 ## @item TD to TSTOP: ## VO + VA*exp(-(time-TD)*THETA)*sine(twopi*FREQ*(time+TD)) ## @end itemize ## ## Currently the damping factor has no effect. ## ## Pulse ## @example ## PULSE(V1 V2 TD TR TF PW PER) ## @end example ## ## parameters meaning ## @itemize @bullet ## @item V1 (initial value) ## @item V2 (pulsed value) ## @item TD (delay time) ## @item TR (rise time) ## @item TF (fall time) ## @item PW (pulse width) ## @item PER (period) ## @end itemize ## ## Currently rise and fall time are not implemented yet. ## ## @item .MODEL cards ## Defines a model for semiconductor devices ## ## @example ## .MODEL MNAME TYPE(PNAME1=PVAL1 PNAME2=PVAL2 ... ) ## @end example ## ## TYPE can be: ## @itemize @bullet ## @item NMOS N-channel MOSFET model ## @item PMOS P-channel MOSFET model ## @item D diode model ## @end itemize ## ## The parameter "LEVEL" is currently assigned to the field "section" in the call ## of the element functions by the solver. ## Currently supported values for the parameter LEVEL for NMOS and PMOS are: ## @itemize @bullet ## @item simple ## @item lincap ## @end itemize ## (see documentation of function Mdiode). ## ## Currently supported values for the parameter LEVEL for D are: ## @itemize @bullet ## @item simple ## @end itemize ## (see documentation of functions Mnmosfet and Mpmosfet). ## ## @end itemize ## @seealso{prs_iff,Mdiode,Mnmosfet,Mpmosfet} ## @end deftypefn function outstruct = prs_spice (name) ## Check input if (nargin != 1 || !ischar (name)) error ("prs_spice: wrong input.") endif ## Initialization outstruct = struct ("LCR", [], "NLC", [], "totextvar", 0); global ndsvec; # Vector of circuit nodes global nodes_list; global intvar_list; global models_list; ndsvec = []; outstruct.totintvar = 0; # Number of internal variables count = struct ("NLC", struct ("n", 0, "list", {""}), "LCR", struct ("n", 0, "list", {""})); nodes_list = {"0"}; intvar_list = {}; models_list = struct ("mname", {""}, "melement", {""}, "msection", {""}); ## File parsing ## Open circuit file filename = [name ".spc"]; if (exist (filename) != 2) ## isempty (file_in_path (".", filename)) error (["prs_spice: .spc file not found:" filename]); endif fid = fopen (filename, "r"); if (fid>-1) line = ''; fullline = ''; lineCounter = 0; while (! feof (fid)) line = strtrim (line); %% exclude empty lines if length (line) %% exclude comments if (! strncmpi (line, '*', 1)) %% lines here aren't comments if (strncmpi (line, '+', 1)) %% this line has to be concatenated to previous one line (1) = ' '; fullline = [fullline line]; else %% these lines are not a concatenation %% line echo for debug %# disp (fullline); %% compute fullline here! %#[outstruct, intvar, count] = lineParse (upper (fullline), outstruct, count, intvar); %# NB: case-sensitive because of parameter names %#[outstruct, intvar, count] = lineParse (fullline, outstruct, intvar, count); [outstruct, count] = lineParse (fullline, outstruct, count); fullline = line; end %if (strncmpi (line, '+', 1)) end %if (~strncmpi (line, '*', 1)) end % if length (line) line = fgets (fid); lineCounter = lineCounter+1; end % while ~feof (fid) %% parse last line if length (fullline) ## NB: case-sensitive because of parameter names %#[outstruct, intvar, count] = lineParse (upper (fullline), outstruct, count, intvar); %#[outstruct, intvar, count] = lineParse (fullline, outstruct, intvar, count); [outstruct, count] = lineParse (fullline, outstruct, count); end fclose (fid); else error ('Input file not found!'); end ## Set the number of internal and external variables nnodes = length (unique (ndsvec)); maxidx = max (ndsvec); if (nnodes <= (maxidx+1)) ## If the valid file is a subcircuit it may happen ## that nnodes == maxidx, otherwise nnodes == (maxidx+1) outstruct.totextvar = max (ndsvec); else error ("prs_spice: hanging nodes in circuit %s", name); endif ## set node names as variable names for ii = 1:length (nodes_list) outstruct.namesn (ii) = ii-1; endfor outstruct.namess = horzcat (nodes_list, intvar_list); ##outstruct.namess ##outstruct.totintvar endfunction ## NLC block intvar count update function outstruct = NLCintvar (outstruct, NLCcount, name) global ndsvec; global intvar_list; ## set node names for NLC subcircuit ##for NLCcount = 1:count.NLC.n; ##NLCcount = count.NLC.n; ## set vnmatrix for NLC subcircuit ndsvec = [ndsvec ; outstruct.NLC(NLCcount).vnmatrix(:)]; ## Compute internal variables cycling over each ## element in the section ##for iel = 1:outstruct.NLC(NLCcount).nrows iel = outstruct.NLC(NLCcount).nrows; [a, b, c] = feval (outstruct.NLC(NLCcount).func, outstruct.NLC(NLCcount).section, outstruct.NLC(NLCcount).pvmatrix(iel, :), outstruct.NLC(NLCcount).parnames, zeros (outstruct.NLC(NLCcount).nextvar, 1), [], 0); ## FIXME: if all the element in the same section share the ## same number of internal variables, the for cycle can be ## substituted by only one call outstruct.NLC(NLCcount).nintvar(iel) = columns (a) - outstruct.NLC(NLCcount).nextvar; outstruct.NLC(NLCcount).osintvar(iel) = outstruct.totintvar; outstruct.totintvar += outstruct.NLC(NLCcount).nintvar(iel); if outstruct.NLC(NLCcount).nintvar(iel)>0 intvar_list{outstruct.totintvar} = ["I(" name ")"]; endif ##endfor ##endfor # NLCcount = 1:count.NLC.n; endfunction ## LCR block intvar count update function outstruct = LCRintvar (outstruct, LCRcount, name) global ndsvec; global intvar_list; ## set node names for LCR subcircuit ## for LCRcount = 1:count.LCR.n; ## LCRcount = count.LCR.n; ## set vnmatrix for LCR subcircuit ndsvec = [ndsvec ; outstruct.LCR(LCRcount).vnmatrix(:)]; ## Compute internal variables cycling over each ## element in the section ##for iel = 1:outstruct.LCR(LCRcount).nrows iel = outstruct.LCR(LCRcount).nrows; [a, b, c] = feval (outstruct.LCR(LCRcount).func, outstruct.LCR(LCRcount).section, outstruct.LCR(LCRcount).pvmatrix(iel, :), outstruct.LCR(LCRcount).parnames, zeros(outstruct.LCR(LCRcount).nextvar, 1), [], 0); ## FIXME: if all the element in the same section share the ## same number of internal variables, the for cycle can be ## substituted by only one call outstruct.LCR(LCRcount).nintvar(iel) = columns (a) - outstruct.LCR(LCRcount).nextvar; ##outstruct.LCR(LCRcount).osintvar(iel) = intvar; outstruct.LCR(LCRcount).osintvar(iel) = outstruct.totintvar; ##intvar += outstruct.LCR(LCRcount).nintvar(iel); outstruct.totintvar += outstruct.LCR(LCRcount).nintvar(iel); if outstruct.LCR(LCRcount).nintvar(iel)>0 intvar_list{outstruct.totintvar} = ["I(" name ")"]; endif ##endfor ## endfor # LCRcount = 1:count.LCR.n; endfunction ## Parses a single line function [outstruct, count] = lineParse (line, outstruct, count) if length (line) switch (line (1)) case 'B' case 'C' [outstruct, count] = prs_spice_C (line, outstruct, count); case 'D' [outstruct, count] = prs_spice_D (line, outstruct, count); case 'E' ##mspINP2E (line, lineCounter); case 'F' ##mspINP2F (line, lineCounter); case 'G' ##mspINP2G (line, lineCounter); case 'H' ##mspINP2H (line, lineCounter); case 'I' ##mspINP2I (line, lineCounter); case 'J' case 'K' ##mspINP2K (line, lineCounter); case 'L' ##mspINP2L (line, lineCounter); case 'M' ## FIXME: just for nMOS devices! [outstruct, count] = prs_spice_M (line, outstruct, count); ## case 'P' ## temporarily assigned to pMOS devices. ##[outstruct, count] = prs_spice_P (line, outstruct, count); case 'Q' case 'R' [outstruct, count] = prs_spice_R (line, outstruct, count); case 'S' case 'T' case 'U' case 'V' [outstruct, count] = prs_spice_V (line, outstruct, count); case 'W' case 'X' case 'Z' case '.' [outstruct, count] = prs_spice_dot (line, outstruct, count); otherwise warn = sprintf (['prs_spice: Unsupported circuit element in line: ' line ]); warning (warn); end % switch (line (1)) end %if length (line) endfunction ## adds an NLC element to outstruct function [outstruct, count] = addNLCelement (outstruct, count, element, section, nextvar, npar, nparnames, parnames, vnmatrix, pvmatrix) ## check whether the element type already exists in output structure ## the search key is (func, section) ##[tf, idx] = ismember ({element}, count.NLC.list); ##if !tf ## the element still does not exist ## update counters count.NLC.n++; count.NLC.list{count.NLC.n} = element; ## if the element doesn't exists, add it to the output structure outstruct.NLC(count.NLC.n).func = element; outstruct.NLC(count.NLC.n).section = section; outstruct.NLC(count.NLC.n).nextvar = nextvar; outstruct.NLC(count.NLC.n).npar = npar; outstruct.NLC(count.NLC.n).nrows = 1; outstruct.NLC(count.NLC.n).nparnames = nparnames; outstruct.NLC(count.NLC.n).parnames = parnames; outstruct.NLC(count.NLC.n).vnmatrix = vnmatrix; outstruct.NLC(count.NLC.n).pvmatrix = pvmatrix; ##else ## found = 0; ## for ii = 1:length (idx) ## if strcmp (outstruct.NLC(idx(ii)).section, section) ## found = 1; ## break; ## endif #!strcmp (outstruct.NLC(idx(ii)).section, section) ## endfor #ii = 1:length (idx) ## if !found ## the section does not exist ## the element still does not exist ## update counters ## count.NLC.n++; ## count.NLC.list{count.NLC.n} = element; ## if the element doesn't exists, add it to the output structure ## outstruct.NLC(count.NLC.n).func = element; ## outstruct.NLC(count.NLC.n).section = section; ## outstruct.NLC(count.NLC.n).nextvar = nextvar; ## outstruct.NLC(count.NLC.n).npar = npar; ## outstruct.NLC(count.NLC.n).nrows = 1; ## outstruct.NLC(count.NLC.n).nparnames = nparnames; ## outstruct.NLC(count.NLC.n).parnames = parnames; ## outstruct.NLC(count.NLC.n).vnmatrix = vnmatrix; ## outstruct.NLC(count.NLC.n).pvmatrix = pvmatrix; ## else ## the couple (element, section) already exists, so add a row in the structure ## add an element to the structure ## outstruct.NLC(idx(ii)).nrows++; ## update parameter value and connectivity matrix ## [outstruct.NLC(idx(ii)).vnmatrix] = [outstruct.NLC(idx(ii)).vnmatrix; vnmatrix]; ## [outstruct.NLC(idx(ii)).pvmatrix] = [outstruct.NLC(idx(ii)).pvmatrix; pvmatrix]; ## endif ##endif endfunction ## adds an LCR element to outstruct function [outstruct, count] = addLCRelement (outstruct, count, element, section, nextvar, npar, nparnames, parnames, vnmatrix, pvmatrix) ## check whether the element type already exists in output structure ## the search key is (func, section) [tf, idx] = ismember ({element}, count.LCR.list); if !tf ## the element still does not exist ## update counters count.LCR.n++; count.LCR.list{count.LCR.n} = element; ## if the element doesn't exists, add it to the output structure outstruct.LCR(count.LCR.n).func = element; outstruct.LCR(count.LCR.n).section = section; outstruct.LCR(count.LCR.n).nextvar = nextvar; outstruct.LCR(count.LCR.n).npar = npar; outstruct.LCR(count.LCR.n).nrows = 1; outstruct.LCR(count.LCR.n).nparnames = nparnames; outstruct.LCR(count.LCR.n).parnames = parnames; outstruct.LCR(count.LCR.n).vnmatrix = vnmatrix; outstruct.LCR(count.LCR.n).pvmatrix = pvmatrix; else found = 0; for ii = 1:length (idx) if strcmp (outstruct.LCR(idx(ii)).section, section) found = 1; break; endif #!strcmp (outstruct.LCR(idx(ii)).section, section) endfor #ii = 1:length (idx) if (! found) ## the section does not exist ## the element still does not exist ## update counters count.LCR.n++; count.LCR.list{count.LCR.n} = element; ## if the element doesn't exists, add it to the output structure outstruct.LCR(count.LCR.n).func = element; outstruct.LCR(count.LCR.n).section = section; outstruct.LCR(count.LCR.n).nextvar = nextvar; outstruct.LCR(count.LCR.n).npar = npar; outstruct.LCR(count.LCR.n).nrows = 1; outstruct.LCR(count.LCR.n).nparnames = nparnames; outstruct.LCR(count.LCR.n).parnames = parnames; outstruct.LCR(count.LCR.n).vnmatrix = vnmatrix; outstruct.LCR(count.LCR.n).pvmatrix = pvmatrix; else ## the couple (element, section) already exists, so add a row in the structure ## add an element to the structure outstruct.LCR(idx(ii)).nrows++; ## update parameter value and connectivity matrix [outstruct.LCR(idx(ii)).vnmatrix] = [outstruct.LCR(idx(ii)).vnmatrix; vnmatrix]; [outstruct.LCR(idx(ii)).pvmatrix] = [outstruct.LCR(idx(ii)).pvmatrix; pvmatrix]; endif endif endfunction ## converts a blank separated values string into a cell array function ca = str2ca (str) ca = regexpi (str, '[^ \s=]+', 'match'); endfunction ## replaces the tokens c_old with c_new in string inString function outString = strReplace (inString, c_old, c_new) outString = inString; l = length (c_new); for idx = 1:length (c_old) if (idx<=l) outString = strrep (outString, c_old{idx}, c_new{idx}); end end endfunction ## returns the numeric value of a string function num = literal2num (string) literals = {'MEG' 'MIL' 'A' 'F' 'P' 'N' 'U' 'M' 'K' 'G' 'T'}; numerics = {'e6' '*25.4e-6' 'e-18' 'e-15' 'e-12' 'e-9' 'e-6' 'e-3' 'e3' 'e9' 'e12'}; newstr = strReplace (upper (string), literals, numerics); num = str2num (newstr); end function syntaxError (line) warnstr = sprintf ("Syntax error in line: %s", line); error (warnstr); endfunction function [outstruct, count] = prs_spice_C (line, outstruct, count) element = "Mcapacitors"; ## check wheter the element type already exists in output structure [tf, idx] = ismember ({element}, count.NLC.list); if !tf ## update counters count.NLC.n++; count.NLC.list{count.NLC.n} = element; #idx=count.NLC.n; ## if the element doesn't exists, add it to the output structure outstruct.NLC(count.NLC.n).func = element; outstruct.NLC(count.NLC.n).section = "LIN"; outstruct.NLC(count.NLC.n).nextvar = 2; outstruct.NLC(count.NLC.n).npar = 1; outstruct.NLC(count.NLC.n).nrows = 0; outstruct.NLC(count.NLC.n).nparnames = 1; outstruct.NLC(count.NLC.n).parnames = {"C"}; outstruct.NLC(count.NLC.n).vnmatrix = []; outstruct.NLC(count.NLC.n).pvmatrix = []; endif ## add an element to the structure ##outstruct.NLC(idx).nrows++; outstruct.NLC(count.NLC.n).nrows++; ## convert input line string into cell array ca = str2ca (line); if length (ca)>3 ## update parameter value and connectivity matrix ##[outstruct.NLC(idx).vnmatrix] = [outstruct.NLC(idx).vnmatrix; add_nodes(ca(2:3))]; ##[outstruct.NLC(idx).pvmatrix] = [outstruct.NLC(idx).pvmatrix; literal2num(ca{4})]; [outstruct.NLC(count.NLC.n).vnmatrix] = [outstruct.NLC(count.NLC.n).vnmatrix; add_nodes(ca(2:3))]; [outstruct.NLC(count.NLC.n).pvmatrix] = [outstruct.NLC(count.NLC.n).pvmatrix; literal2num(ca{4})]; else syntaxError (line); endif ##outstruct = NLCintvar (outstruct, idx, ca{1}); outstruct = NLCintvar(outstruct, count.NLC.n, ca{1}); endfunction function [outstruct, count] = prs_spice_D (line, outstruct, count) element = "Mdiode"; ## check wheter the element type already exists in output structure ##[tf, idx] = ismember ({element}, count.NLC.list); ##if !tf ## update counters count.NLC.n++; count.NLC.list{count.NLC.n} = element; ##idx = count.NLC.n; ## if the element doesn't exists, add it to the output structure outstruct.NLC(count.NLC.n).func = element; outstruct.NLC(count.NLC.n).section = "simple"; outstruct.NLC(count.NLC.n).nextvar = 2; outstruct.NLC(count.NLC.n).npar = 0; outstruct.NLC(count.NLC.n).nrows = 1; outstruct.NLC(count.NLC.n).nparnames = 0; outstruct.NLC(count.NLC.n).parnames = {}; outstruct.NLC(count.NLC.n).vnmatrix = []; outstruct.NLC(count.NLC.n).pvmatrix = []; ##endif ## convert input line string into cell array ca = str2ca (line); ## update parameter value and connectivity matrix ##[outstruct.NLC(idx).vnmatrix] = [outstruct.NLC(idx).vnmatrix; add_nodes(ca(2:3))]; [outstruct.NLC(count.NLC.n).vnmatrix] = [outstruct.NLC(count.NLC.n).vnmatrix; add_nodes(ca(2:3))]; ## check if parameters are specified for prm_idx = 1:(length (ca)-3)/2 ## [tf, str_idx] = ismember (outstruct.NLC(count.NLC.n).parnames{prm_idx}, ca); ## TODO: can the loop be executed in a single operation? ## [tf, str_idx] = ismember (outstruct.NLC(count.NLC.n).parnames, ca); if length (ca) >= 1+prm_idx*2 ## find specified parameter name ##if tf outstruct.NLC(count.NLC.n).npar++; outstruct.NLC(count.NLC.n).nparnames++; outstruct.NLC(count.NLC.n).parnames{1, prm_idx} = ca{2*prm_idx+2}; outstruct.NLC(count.NLC.n).pvmatrix(1, prm_idx) = literal2num (ca{2*prm_idx+3}); ##else ## TODO: set to a default value undefined parameters, instead of rising an error? ## errstr = sprintf ("Undefined parameter %s in line: %s", outstruct.NLC(count.NLC.n).parnames{prm_idx}, line); ## error (errstr); ##endif else syntaxError (line); endif endfor outstruct = NLCintvar(outstruct, count.NLC.n, ca{1}); endfunction function [outstruct, count] = prs_spice_M (line, outstruct, count) global models_list; ##element = "Mnmosfet"; ## check wheter the element type already exists in output structure ##[tf, idx] = ismember ({element}, count.NLC.list); ##if !tf ## update counters count.NLC.n++; ##count.NLC.list{count.NLC.n} = element; ##idx = count.NLC.n; ## if the element doesn't exists, add it to the output structure ##outstruct.NLC(count.NLC.n).func = element; ##outstruct.NLC(count.NLC.n).section = "simple"; ## outstruct.NLC(count.NLC.n).section = "lincap"; outstruct.NLC(count.NLC.n).nextvar = 4; outstruct.NLC(count.NLC.n).npar = 0; outstruct.NLC(count.NLC.n).nrows = 1; outstruct.NLC(count.NLC.n).nparnames = 0; outstruct.NLC(count.NLC.n).parnames = {}; ##outstruct.NLC(count.NLC.n).vnmatrix = []; outstruct.NLC(count.NLC.n).pvmatrix = []; ##endif ## convert input line string into cell array ca = str2ca (line); ## update parameter value and connectivity matrix ##[outstruct.NLC(idx).vnmatrix] = [add_nodes(ca(2:5))]; [outstruct.NLC(count.NLC.n).vnmatrix] = [add_nodes(ca(2:5))]; [tf, idx] = ismember (ca{6}, models_list.mname); if (tf) outstruct.NLC(count.NLC.n).func = models_list.melement{idx}; outstruct.NLC(count.NLC.n).section = models_list.msection{idx}; ## check if parameters are specified for prm_idx = 1:(length (ca)-6)/2 if length (ca)>=4+prm_idx*2 outstruct.NLC(count.NLC.n).npar++; outstruct.NLC(count.NLC.n).nparnames++; outstruct.NLC(count.NLC.n).parnames{1, prm_idx} = ca{2*prm_idx+5}; outstruct.NLC(count.NLC.n).pvmatrix(1, prm_idx) = literal2num (ca{2*prm_idx+6}); else syntaxError (line); endif endfor ## add model parameters to list prm_idx = outstruct.NLC(count.NLC.n).npar; len = length (models_list.plist{idx}.pnames); for mpidx = 1:len outstruct.NLC(count.NLC.n).parnames{prm_idx+mpidx} = models_list.plist{idx}.pnames{mpidx}; outstruct.NLC(count.NLC.n).pvmatrix(1, prm_idx+mpidx) = models_list.plist{idx}.pvalues(mpidx); endfor outstruct.NLC(count.NLC.n).npar = outstruct.NLC(count.NLC.n).npar+len; outstruct.NLC(count.NLC.n).nparnanames = outstruct.NLC(count.NLC.n).nparnames+len; outstruct = NLCintvar(outstruct, count.NLC.n, ca{1}); else syntaxError (line); endif endfunction function [outstruct, count]= prs_spice_P (line, outstruct, count) element = "Mpmosfet"; ## check wheter the element type already exists in output structure ## update counters count.NLC.n++; count.NLC.list{count.NLC.n} = element; ## if the element doesn't exists, add it to the output structure outstruct.NLC(count.NLC.n).func = element; outstruct.NLC(count.NLC.n).section = "simple"; ## outstruct.NLC(count.NLC.n).section = "lincap"; outstruct.NLC(count.NLC.n).nextvar = 4; outstruct.NLC(count.NLC.n).npar = 0; outstruct.NLC(count.NLC.n).nrows = 1; outstruct.NLC(count.NLC.n).nparnames = 0; outstruct.NLC(count.NLC.n).parnames = {}; ##outstruct.NLC(count.NLC.n).vnmatrix = []; outstruct.NLC(count.NLC.n).pvmatrix = []; ## convert input line string into cell array ca = str2ca (line); ## update parameter value and connectivity matrix ##[outstruct.NLC(idx).vnmatrix] = [add_nodes(ca(2:5))]; [outstruct.NLC(count.NLC.n).vnmatrix] = [add_nodes(ca(2:5))]; ## check if parameters are specified for prm_idx = 1:(length (ca)-5)/2 ## [tf, str_idx] = ismember (outstruct.NLC(count.NLC.n).parnames{prm_idx}, ca); ## TODO: can the loop be executed in a single operation? ## [tf, str_idx] = ismember (outstruct.NLC(count.NLC.n).parnames, ca); if (length (ca) >= 3+prm_idx*2) ## find specified parameter name ##if tf outstruct.NLC(count.NLC.n).npar++; outstruct.NLC(count.NLC.n).nparnames++; outstruct.NLC(count.NLC.n).parnames{1, prm_idx} = ca{2*prm_idx+4}; outstruct.NLC(count.NLC.n).pvmatrix(1, prm_idx) = literal2num (ca{2*prm_idx+5}); ##else ## TODO: set to a default value undefined parameters, instead of rising an error? ## errstr=sprintf("Undefined parameter %s in line: %s", outstruct.NLC(count.NLC.n).parnames{prm_idx}, line); ## error(errstr); ##endif else syntaxError (line); endif endfor outstruct = NLCintvar(outstruct, count.NLC.n, ca{1}); endfunction function [outstruct, count]= prs_spice_R (line, outstruct, count) element = "Mresistors"; ## check wheter the element type already exists in output structure [tf, idx] = ismember ({element}, count.LCR.list); if !tf ## update counters count.LCR.n++; count.LCR.list{count.LCR.n} = element; ##idx = count.LCR.n; ## if the element doesn't exists, add it to the output structure outstruct.LCR(count.LCR.n).func = element; outstruct.LCR(count.LCR.n).section = "LIN"; outstruct.LCR(count.LCR.n).nextvar = 2; outstruct.LCR(count.LCR.n).npar = 1; outstruct.LCR(count.LCR.n).nrows = 0; outstruct.LCR(count.LCR.n).nparnames = 1; outstruct.LCR(count.LCR.n).parnames = {"R"}; outstruct.LCR(count.LCR.n).vnmatrix = []; outstruct.LCR(count.LCR.n).pvmatrix = []; endif ## add an element to the structure ##outstruct.LCR(idx).nrows++; outstruct.LCR(count.LCR.n).nrows++; ## convert input line string into cell array ca = str2ca (line); if (length (ca) > 3) ## update parameter value and connectivity matrix ##[outstruct.LCR(idx).vnmatrix] = [outstruct.LCR(idx).vnmatrix; add_nodes(ca(2:3))]; ##[outstruct.LCR(idx).pvmatrix] = [outstruct.LCR(idx).pvmatrix; literal2num(ca{4})]; [outstruct.LCR(count.LCR.n).vnmatrix] = [outstruct.LCR(count.LCR.n).vnmatrix; add_nodes(ca(2:3))]; [outstruct.LCR(count.LCR.n).pvmatrix] = [outstruct.LCR(count.LCR.n).pvmatrix; literal2num(ca{4})]; else syntaxError (line); endif outstruct = LCRintvar(outstruct, count.LCR.n, ca{1}); endfunction function [outstruct, count] = prs_spice_V (line, outstruct, count) ## Sine ## SIN(VO VA FREQ TD THETA) ## ## VO (offset) ## VA (amplitude) ## FREQ (frequency) ## TD (delay) ## THETA (damping factor) ## ## 0 to TD: V0 ## TD to TSTOP: VO + VA*exp(-(time-TD)*THETA)*sine(twopi*FREQ*(time+TD) ## check if it is a sinwave generator sine = regexp (line, '(?SIN)[\s]*\((?.+)\)', 'names'); ## Pulse ## PULSE(V1 V2 TD TR TF PW PER) ## ## parameters default values units ## V1 (initial value) Volts or Amps ## V2 (pulsed value) Volts or Amps ## TD (delay time) 0.0 seconds ## TR (rise time) TSTEP seconds ## TF (fall time) TSTEP seconds ## PW (pulse width) TSTOP seconds ## PER (period) TSTOP seconds ## check if it is a pulse generator pulse = regexp (line, '(?PULSE)[\s]*\((?.+)\)', 'names'); if (! isempty (sine.stim)) ## sinwave generator ca = str2ca (sine.prms); if (length (ca) == 5) vo = literal2num (ca{1}); va = literal2num (ca{2}); freq = literal2num (ca{3}); td = literal2num (ca{4}); theta = literal2num (ca{5}); pvmatrix = [va freq td vo]; element = "Mvoltagesources"; section = "sinwave"; nextvar = 2; npar = 4; nparnames = 4; parnames = {"Ampl", "f", "delay", "shift"}; ## convert input line string into cell array ca = str2ca (line); vnmatrix = add_nodes (ca(2:3)); [outstruct, count] = addNLCelement (outstruct, count, element, section, nextvar, npar, nparnames, parnames, vnmatrix, pvmatrix); outstruct = NLCintvar(outstruct, count.NLC.n, ca{1}); else #length(ca) == 5 syntaxError (line); endif #length (ca) == 5 elseif (! isempty (pulse.stim)) ca = str2ca (pulse.prms); if length (ca) == 7 low = literal2num (ca{1}); high = literal2num (ca{2}); delay = literal2num (ca{3}); ## TODO: add rise and fall times! ## tr = literal2num (ca{4}); ## tf = literal2num (ca{5}); thigh = literal2num (ca{6}); period = literal2num (ca{7}) tlow = period-thigh; pvmatrix = [low high tlow thigh delay]; element = "Mvoltagesources"; section = "squarewave"; nextvar = 2; npar = 5; nparnames = 5; parnames = {"low", "high", "tlow", "thigh", "delay"}; ## convert input line string into cell array ca = str2ca (line); vnmatrix = add_nodes (ca(2:3)); [outstruct, count] = addNLCelement (outstruct, count, element, section, nextvar, npar, nparnames, parnames, vnmatrix, pvmatrix); outstruct = NLCintvar(outstruct, count.NLC.n, ca{1}); else ##length (ca) == 7 syntaxError (line); endif ##length (ca) == 7 else ##~isempty (tran.stim) ## DC generator element = "Mvoltagesources"; section = "DC"; nextvar = 2; npar = 1; nparnames = 1; parnames = {"V"}; ## convert input line string into cell array ca = str2ca (line); vnmatrix = add_nodes (ca(2:3)); pvmatrix = literal2num (ca{4}); [outstruct, count] = addLCRelement (outstruct, count, element, section, nextvar, npar, nparnames, parnames, vnmatrix, pvmatrix); outstruct = LCRintvar(outstruct, count.LCR.n, ca{1}); endif #~isempty(tran.stim) endfunction function [outstruct, count] = prs_spice_dot (line, outstruct, count) ## .MODEL MNAME TYPE(PNAMEl = PVALl PNAME2 = PVAL2 ... ) ## TYPE can be: ## R resistor model ## C capacitor model ## URC Uniform Distributed RC model ## D diode model ## NPN NPN BIT model ## PNP PNP BJT model ## NJF N-channel JFET model ## PJF P-channel lFET model ## NMOS N-channel MOSFET model ## PMOS P-channel MOSFET model ## NMF N-channel MESFET model ## PMF P-channel MESFET model ## SW voltage controlled switch ## CSW current controlled switch global models_list; model = regexp (line, '.MODEL[\s]+(?[\S]+)[\s]+(?R|C|URC|D|NPN|PNP|NJF|PJF|NMOS|PMOS|NMF|PMF|SW|CSW)[\s]*\([\s]*(?.+)[\s]*\)', 'names'); if !isempty (model) switch (model.mtype) case 'R' case 'C' case 'URC' case 'D' element = "Mdiode"; case 'NPN' case 'PNP' case 'NJF' case 'PJF' case 'NMOS' element = "Mnmosfet"; case 'PMOS' element = "Mpmosfet"; case 'NMF' case 'PMF' case 'SW' case 'CSW' otherwise syntaxError (line); endswitch ## get model level (=section) level = regexp (model.prms, 'LEVEL=(?[\S]+)[\s]+(?.+)', 'names'); if isempty (level.level) section = "simple"; else section = level.level; model.prms = level.prms; endif midx = length (models_list.mname)+1; models_list.mname{midx} = model.mname; models_list.melement{midx} = element; models_list.msection{midx} = section; ## set model parameters ca = str2ca (model.prms); midx = length (models_list.mname); models_list.plist{midx} = struct ("pnames", {""}, "pvalues", []); for prm_idx = 1:length (ca)/2 ## save parameter name models_list.plist{midx}.pnames{prm_idx} = ca{2*prm_idx-1}; ## save parameter value models_list.plist{midx}.pvalues = [models_list.plist{midx}.pvalues literal2num(ca{2*prm_idx})]; endfor endif #!isempty (model) endfunction ## adds nodes to nodes_list and returns the indexes of the added nodes function indexes = add_nodes (nodes) global nodes_list; for ii = 1:length (nodes) [tf, idx] = ismember (nodes(ii), nodes_list); if tf indexes(ii) = idx-1; else indexes(ii) = length (nodes_list); nodes_list{length (nodes_list)+1} = nodes{ii}; endif endfor endfunction %!demo %! outstruct = prs_spice ("rlc"); %! vin = linspace (0, 10, 10); %! x = zeros (outstruct.totextvar+outstruct.totintvar, 1); %! %! for idx = 1:length (vin) %! outstruct.NLC(1).pvmatrix(1) = vin(idx); %! out = nls_stationary (outstruct, x, 1e-15, 100); %! vout(idx) = out(2); %! end %! %! plot (vin, vout); %! grid on; %!demo %! ## Circuit %! %! cir = menu ("Chose the circuit to analyze:", %! "AND (Simple algebraic MOS-FET model)", %! "AND (Simple MOS-FET model with parasitic capacitances)", %! "Diode clamper (Simple exponential diode model)", %! "CMOS-inverter circuit (Simple algebraic MOS-FET model)", %! "n-MOS analog amplifier (Simple algebraic MOS-FET model)", %! "Linear RC circuit", %! "Diode bridge rectifier", %! "RLC circuit"); %! %! switch cir %! case 1 %! outstruct = prs_spice ("and"); %! x = [.5 .5 .33 .66 .5 1 0 0 1 ]'; %! t = linspace (0, .5, 100); %! pltvars = {"Va", "Vb", "Va_and_b"}; %! dmp = .2; %! tol = 1e-15; %! maxit = 100; %! case 2 %! outstruct = prs_spice ("and2"); %! x = [.8;.8;0.00232;0.00465;.8; %! .8;0.00232;0.00465;0.00000; %! 0.0;0.0;0.0;0.00232;0.0; %! 0.0;0.0;0.0;1.0;0.0;-0.0; %! 0.0;1.0;0.00465;0.0;0.0; %! -0.0;1.0;0.00465;0.0; %! 0.0;0.0;1.0;1.0;0.0;0.0;0.0; %! 0.0;0.0;0.0]; %! t = linspace (.25e-6, .5e-6, 100); %! dmp = .1; %! pltvars = {"Va", "Vb", "Va_and_b"}; %! tol = 1e-15; %! maxit = 100; %! case 3 %! outstruct = prs_spice ("diode"); %! x = [0 0 0 0 0]'; %! t = linspace (0, 3e-10, 200); %! dmp = .1; %! pltvars = {"Vin", "Vout", "V2"}; %! tol = 1e-15; %! maxit = 100; %! case 4 %! outstruct = prs_spice ("inverter"); %! x = [.5 .5 1 0 0]'; %! t = linspace (0, 1, 100); %! dmp = .1; %! pltvars={"Vgate", "Vdrain"}; %! tol = 1e-15; %! maxit = 100; %! case 5 %! outstruct = prs_spice ("nmos"); %! x = [1 .03 1 0 0]'; %! t = linspace (0, 1, 50); %! dmp = .1; %! pltvars = {"Vgate", "Vdrain"}; %! tol = 1e-15; %! maxit = 100; %! case 6 %! outstruct = prs_spice ("rcs"); %! x = [0 0 0 0]'; %! t = linspace (0, 2e-5, 100); %! dmp = 1; %! pltvars = {"Vout"}; %! tol = 1e-15; %! maxit = 100; %! case 7 %! outstruct = prs_spice ("rect"); %! x = [0 0 0 0 ]'; %! t = linspace (0, 3e-10, 60); %! dmp = .1; %! pltvars = {"Vin", "Voutlow", "Vouthigh"}; %! tol = 1e-15; %! maxit = 100; %! case 8 %! outstruct = prs_spice ("rlc") %! #x = [0 0 0 0 0]'; %! #x = [0 0 0 ]'; %! #x = [0 0 0 0]'; %! x = [0 0 0 0 0 0 ]'; %! t = linspace (0, 2e-5, 200); %! dmp = 1; %! #pltvars = {"Vin", "Vout"}; %! pltvars = {"I(C3)"}; %! #pltvars = {"Vout"}; %! tol = 1e-15; %! maxit = 100; %! otherwise %! error ("unknown circuit"); %! endswitch %! %! clc; %! slv = menu("Chose the solver to use:", %! "BWEULER", # 1 %! "DASPK", # 2 %! "THETA", # 3 %! "ODERS", # 4 %! "ODESX", # 5 %! "ODE2R", # 6 %! "ODE5R" # 7 %! ); %! %! out = zeros (rows (x), columns (t)); %! %! switch slv %! case 1 %! out = tst_backward_euler (outstruct, x, t, tol, maxit, pltvars); %! # out = TSTbweuler (outstruct, x, t, tol, maxit, pltvars); %! case 2 %! out = tst_daspk (outstruct, x, t, tol, maxit, pltvars); %! # out = TSTdaspk (outstruct, x, t, tol, maxit, pltvars); %! case 3 %! out = tst_theta_method (outstruct, x, t, tol, maxit, .5, pltvars, [0 0]); %! # out = TSTthetamethod (outstruct, x, t, tol, maxit, .5, pltvars, [0 0]); %! case 4 %! out = tst_odepkg (outstruct, x, t, tol, maxit, pltvars, "oders", [0, 1]); %! # out = TSTodepkg (outstruct, x, t, tol, maxit, pltvars, "oders", [0, 1]); %! case 5 %! out = tst_odepkg (outstruct, x, t, tol, maxit, pltvars, "odesx", [0, 1]); %! # out = TSTodepkg (outstruct, x, t, tol, maxit, pltvars, "odesx", [0, 1]); %! case 6 %! out = tst_odepkg (outstruct, x, t, tol, maxit, pltvars, "ode2r", [0, 1]); %! # out = TSTodepkg (outstruct, x, t, tol, maxit, pltvars, "ode2r", [0, 1]); %! case 7 %! out = tst_odepkg (outstruct, x, t, tol, maxit, pltvars, "ode5r", [0, 1]) %! # out = TSTodepkg (outstruct, x, t, tol, maxit, pltvars, "ode5r", [0, 1]) %! otherwise %! error ("unknown solver"); %! endswitch %! %! #utl_plot_by_name (t, out, outstruct, pltvars); %! utl_plot_by_name (t, out, outstruct, pltvars); %! axis ("tight"); ocs/inst/sbn/0000755000076500000000000000000011706606202012357 5ustar carlowheelocs/inst/sbn/Mcapacitors.m0000644000076500000000000001112611334211056014777 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=} Mcapacitors(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing models for capacitors. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "LIN" (Linear Capacitor) ## @itemize @minus ## @item C -> capacitance value ## @end itemize ## @item @var{string} = "MULTICAP" (Multipole Capacitor) ## @itemize @minus ## @item C -> capacitance values ## @end itemize ## @item @var{string} = "PDE_NMOS" (Drift-Diffusion PDE NMOS capacitor) ## @itemize @minus ## @item tbulk -> bulk thickness ## @item tox -> oxide thickness ## @item Nnodes -> number of nodes of 1D grid ## @item Na -> bulk doping ## @item toll -> absolute tolerance ## @item maxit -> max iterations number ## @item Area -> device area ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c] = Mcapacitors(string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) intvar = 0; endif switch string ##LCR part case "LIN" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor a = [0 0 1; 0 0 -1; 0 0 0]; b = [0 0 0;0 0 0;-C C 1]; c = [0 0 0]'; break case "MULTICAP" n = length(extvar); C = reshape(parameters,n,n); a = [zeros(n) eye(n); zeros(n) zeros(n)]; b = [zeros(n) zeros(n); -C eye(n)]; c = [zeros(2*n,1)]'; break ##NLC part case "PDE_NMOS" constants tbulk = 1.5e-6; tox = 90e-9; len = tbulk + tox; Nnodes = 300; Na=1e21; toll = 1e-10; maxit = 1000; Area = 1e-12; for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor Vg = extvar(1) - extvar(2); q = intvar(1); [Q,C]=Mnmoscap(tbulk,tox,Area,Vg,Na,Nnodes,toll,maxit); a = [0 0 1; 0 0 -1; 0 0 0]; b = [0 0 0;0 0 0;C -C -1]; c = [0 0 Q-q]'; break otherwise error (["unknown section:" string]) endswitch endfunction ## Non-linear 1D MOS structure. ## FIXME: requires SECS1D!!! function [Q,C]=Mnmoscap(tbulk,tox,Area,Vg,Na,Nnodes,toll,maxit); constants Nelements = Nnodes - 1; len = tox+tbulk; x = linspace(0,len,Nnodes)'; sinodes = find(x<=tbulk); Nsinodes = length(sinodes); NelementsSi = Nsinodes-1; D = - Na* ones(Nsinodes,1); pp = Na ; p = pp* ones(Nsinodes,1); n = (ni^2)./p; Fn = 0*n; Fp = 0*n; V = -Phims + Vg * ones(Nnodes,1); V(sinodes) = Fn + Vth*log(n/ni); ## Scaling xs = len; ns = norm(D,inf); Din = D/ns; Vs = Vth; xin = x/xs; nin = n/ns; pin = p/ns; Vin = V/Vs; Fnin = (Fn - Vs * log(ni/ns))/Vs; Fpin = (Fp + Vs * log(ni/ns))/Vs; l2 = (Vs*esio2)/(q*ns*xs^2)* ones(Nelements,1); l2(1:NelementsSi) = (Vs*esi)/(q*ns*xs^2); ## Solution of Nonlinear Poisson equation [V,nout,pout,res,niter] = DDGnlpoisson (xin,sinodes,Vin,nin,... pin,Fnin,Fpin,Din,l2,... toll,maxit,0); L = Ucomplap(xin,Nnodes,[],Nelements,l2); C22 = L(end,end); C12 = L(2:end-1,end); C11 = L(2:end-1,2:end-1); drdv = zeros(Nnodes,1); drdv(sinodes) = nout + pout; coeff = zeros(Nelements,1); coeff(1:NelementsSi) = 1; M = Ucompmass(xin,Nnodes,[],[],drdv,coeff); C = C22 - C12'*((C11+M(2:end-1,2:end-1))\C12); Q =(C12'*V(2:end-1)+C22*V(end)); ## Descaling C = Area*C*(q*ns*xs/Vs); Q = Area*Q*(q*ns*xs); endfunctionocs/inst/sbn/Mcurrentsources.m0000644000076500000000000000664511334211056015747 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco, Culpo Massimiliano ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## author culpo@math.uni-wuppertal.de ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=}Mcurrentsources(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing models for current sources. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "DC" (Static indipendent current source) ## @itemize @minus ## @item I -> Current source value ## @end itemize ## @item @var{string} = "VCCS" (Voltage controlled current source) ## @itemize @minus ## @item K -> Control parameter ## @end itemize ## @item @var{string} = "sinwave" (Sinusoidal indipendent current ## source) ## @itemize @minus ## @item shift -> mean value of sinusoidal input ## @item Ampl -> amplitude of sinusoidal wave ## @item f -> frequency of sinusoidal wave ## @item delay -> delay of sinusoidal wave ## @end itemize ## @item @var{string} = "VCPS" (Voltage controlled power source) ## @itemize @minus ## @item K -> Control parameter ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c] = Mcurrentsources (string,parameters,parameternames,extvar,intvar,t) switch string ## LCR part case "DC" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor a = zeros(2); b = a; c = [I -I]'; break case "VCCS" ## Voltage controlled current source K = 1; for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor a = zeros(4); b = [0 0 K -K;\ 0 0 -K K;\ 0 0 0 0;\ 0 0 0 0]; c = zeros(4,1); ## NLC part case "sinwave" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor I = shift+Ampl * sin(2*pi*(t+delay)*f ); a = zeros(2); b = a; c = [I -I]'; break case "VCPS" ## Voltage controlled power source K = 1; for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor dv = extvar(3) - extvar(4); I = K*(dv^2); dIdv = 2*K*dv; a = zeros(4); b = [0 0 dIdv -dIdv;\ 0 0 -dIdv dIdv;\ 0 0 0 0;\ 0 0 0 0]; c = [I -I 0 0]; otherwise error (["unknown section:" string]) endswitch endfunction ocs/inst/sbn/Mdiode.m0000644000076500000000000000600411334211056013732 0ustar carlowheel## Copyright (C) 2006,2007,2008 Massimiliano Culpo, Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: culpo@math.uni-wuppertal.de, Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=}Mdiode(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing models for diodes. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @itemize @minus ## @item @var{string} = "simple" (Usual exponential diode model) ## @itemize @minus ## @item Is -> reverse current ## @item Vth -> thermal voltage ## @item Rpar -> parasitic resistance ## @end itemize ## @item @var{string} = "PDEsymmetric" (Drift-Diffusion PDE model) ## @itemize @minus ## @item len -> diode length ## @item Nnodes -> number of nodes of 1D grid ## @item Dope -> doping (abrupt and symmetric) ## @item toll -> absolute tolerance ## @item maxit -> max iterations number ## @item Area -> device area ## @end itemize ## @end itemize ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c] = Mdiode (string,parameters,parameternames,extvar,intvar,t) switch string case "simple" Is = 1e-14; Vth = 2.5e-2; Rpar = 1e12; for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor vp = extvar(1); vm = extvar(2); I = Is*(exp((vp - vm)/Vth) -1 ) + (vp - vm)/Rpar; geq = Is*exp((vp - vm)/Vth)/Vth + 1/Rpar; a = zeros(2); b = [geq -geq; -geq geq]; c = [I ; -I] ; break case "PDEsymmetric" len = 1e-6; Nnodes = 100; Dope=1e23; toll = 1e-5; maxit = 100; ptoll = 1e-10; pmaxit = 100; Area = 1e-10; for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor vp = extvar(1); vm = extvar(2); [I,g] = Mpdesympnjunct (len,Dope,vp-vm,Area,Nnodes,toll,maxit,ptoll,pmaxit); a = zeros(2); b = [g -g; -g g]; c = [I ; -I] ; break otherwise error(["unknown section:" string]) endswitch endfunction ocs/inst/sbn/Minductors.m0000644000076500000000000000376611334211056014674 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=}Minductors(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing models for inductors. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "LIN" (Linear inductor model) ## @itemize @minus ## @item L -> inductance value ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c] = Minductors (string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) intvar = [0 0]; endif switch string case "LIN" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor phi = intvar(1); jl = intvar(2); a = [0 0 0 0; 0 0 0 0; 0 0 1 0; 0 0 0 0]; b = [0 0 0 1; 0 0 0 -1; -1 1 0 0; 0 0 1 -L]; c = [0 0 0 0]'; otherwise error (["unknown section:" string]) endswitch endfunction ocs/inst/sbn/Mnmosfet.m0000644000076500000000000001001011617232116014315 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=}Mnmosfet(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing standard models for n-mosfets. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "simple" (Standard model for MOSFET) ## @itemize @minus ## @item rd -> parasitic resistance between drain and source ## @item k -> k parameter for usual mosfet model ## @item Vth -> threshold voltage ## @end itemize ## @item @var{string} = "lincap" (Adds RC parasitics) ## @itemize @minus ## @item rd -> parasitic resistance between drain and source ## @item k -> k parameter for usual mosfet model ## @item Vth -> threshold voltage ## @item Rs -> parasitic source resistance ## @item Rd -> parasitic drain resistance ## @item Cs -> gate-source capacitance ## @item Cd -> gate-drain capacitance ## @item Cb -> gate-bulk capacitance ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c]=Mnmosfet(string,parameters,parameternames,extvar,intvar,t) switch string case "simple" rd = 1e6; k = 1e-5; Vth = .5; for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]) endfor vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); vgs = vg-vs; vds = vd-vs; if (vgs < Vth) gm = 0; gd = 1/rd; id = vds*gd; elseif (((vgs-Vth) >= (vds)) && (vds>=0)) id = k*((vgs-Vth)*vds-(vds^2)/2)+vds/rd; gm = k*vds; gd = k*(vgs-Vth-vds)+1/rd; elseif (((vgs-Vth) >= (vds)) && (vds<0)) gm = 0; gd = 1/rd; id = vds*gd; else # (i.e. if 0 <= vgs-vth <= vds) id = (k/(2))*(vgs-Vth)^2+vds/rd; gm = (2*k/(2))*(vgs-Vth); gd = 1/rd; endif a = zeros(4); b = [0 0 0 0; -gm (gm+gd) -gd 0; gm -(gm+gd) gd 0; 0 0 0 0]; c = [0 -id id 0]'; break; case "lincap" ## Default parameter values if isempty(intvar) intvar = zeros(5,1); endif Rs = 1e2; Rd = 1e2; Cs = 1e-15; Cd = 1e-15; Cb = 1e-14; rd = inf; k = 1e-3; Vth = .1; ## parameters given in input for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]) endfor persistent tmpstruct if isempty(tmpstruct) mtdnmos = file_in_path(path,"Mtdnmos.cir"); mtdnmos(end-3:end)=[]; tmpstruct = prs_iff(mtdnmos); endif tmpstruct.NLC.pvmatrix = [k Vth rd]; tmpstruct.LCR(1).pvmatrix = [Rs; Rd]; tmpstruct.LCR(2).pvmatrix = [Cs; Cd; Cb]; [A0,B,C] = asm_initialize_system(tmpstruct,[extvar;intvar]); [A1,Jac,res] = asm_build_system(tmpstruct,[extvar;intvar],t); a = A0+A1; b = B+Jac; c = res + B*[extvar;intvar] + C; break; otherwise error(["unknown option:" string]); endswitch endfunction ocs/inst/sbn/Mpdesympnjunct.m0000644000076500000000000000623011334211056015552 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{j},@var{g}]=}Mpdesympnjunct@ ## (@var{len}, @var{Dope}, @var{va}, @ ## @var{Area}, @var{Nnodes}, @var{toll}, @var{maxit}, @var{ptoll}, @var{pmaxit}) ## ## INTERNAL FUNCTION: ## ## NOT SUPPOSED TO BE CALLED DIRECTLY BY USERS ## @end deftypefn function [j,g] = Mpdesympnjunct (len,Dope,va,Area,Nnodes,toll,maxit,ptoll,pmaxit) constants x = linspace(0,len,Nnodes)'; xm = mean(x); Nd=Dope; Na=Dope; nn = (Nd + sqrt(Nd^2+4*ni^2))/2; pp = (Na + sqrt(Na^2+4*ni^2))/2; xn = xm+len/10; xp = xm-len/10; D = Nd * (x>xm) - Na * (x<=xm); ## Scaling coefficients xs = len; ns = norm(D,inf); Vs = Vth; us = un; Js = (Area*us*Vs*q*ns/xs); xin = x/xs; gs = Js/Vs; n = nn * (x>=xn) + (ni^2)/pp * (xxp) + pp * (x<=xp); Fn = va*(x<=xm); Fp = Fn; V = (Fn - Vth * log(p/ni)); ## Scaling idata.D = D/ns; idata.un = un/us; idata.up = up/us; idata.tn = inf; idata.tp = inf; idata.l2 = (Vs*esi)/(q*ns*xs^2); idata.nis = ni/ns; idata.n = n/ns; idata.p = p/ns; idata.V = V/Vs; idata.Fn = (Fn - Vs * log(ni/ns))/Vs; idata.Fp = (Fp + Vs * log(ni/ns))/Vs; ## Solution of DD system ## Algorithm parameters sinodes = [1:length(x)]; [idata,it,res] = DDGgummelmap (xin,idata,toll,maxit/2,ptoll,pmaxit,0); [odata,it,res] = DDNnewtonmap (xin,idata,toll,maxit/2,0); DV = diff(odata.V); h = xin(2)-xin(1); Bp = Ubernoulli(DV,1); Bm = Ubernoulli(DV,0); Jn = -odata.un * (odata.n(2:end).*Bp-odata.n(1:end-1).*Bm)/h; Jp = odata.up * (odata.p(2:end).*Bm-odata.p(1:end-1).*Bp)/h; coeff = idata.un.*Umediaarmonica(odata.n); L =- Ucomplap (xin,Nnodes,[],[],coeff); Jn1 = L*odata.Fn; fprintf(1,"jn1=%g\n",Jn1(1)) fprintf(1,"jn=%g\n",Jn(1)) C11 = L(1,1); C1I = L(1,2:end-1); CII = L(2:end-1,2:end-1); Gn = C11 - C1I*(CII\C1I'); Gn = Gn - coeff(1)*(odata.Fn(2)-odata.Fn(1))/h coeff = idata.up.*Umediaarmonica(odata.p); L =- Ucomplap (xin,Nnodes,[],[],coeff); Jp1 = L*odata.Fp; fprintf(1,"jp1=%g\n",Jp1(1)) fprintf(1,"jp=%g\n",Jp(1)) C11 = L(1,1); C1I = L(1,2:end-1); CII = L(2:end-1,2:end-1); Gp = C11 - C1I*(CII\C1I'); Gp = Gp - coeff(1)*(odata.Fp(2)-odata.Fp(1))/h ## Descaling j= -(Jp(1)+Jn(1))*Js g= gs*(Gn+Gp) endfunctionocs/inst/sbn/Mpmosfet.m0000644000076500000000000000763311617232116014340 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=} Mpmosfet(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing standard models for p-mosfets. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "simple" (Standard model for MOSFET) ## @itemize @minus ## @item rd -> parasitic resistance between drain and source ## @item k -> k parameter for usual mosfet model ## @item Vth -> threshold voltage ## @end itemize ## @item @var{string} = "lincap" (Adds RC parasitics) ## @itemize @minus ## @item rd -> parasitic resistance between drain and source ## @item k -> k parameter for usual mosfet model ## @item Vth -> threshold voltage ## @item Rs -> parasitic source resistance ## @item Rd -> parasitic drain resistance ## @item Cs -> gate-source capacitance ## @item Cd -> gate-drain capacitance ## @item Cb -> gate-bulk capacitance ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c]= Mpmosfet (string,parameters,parameternames,extvar,intvar,t) switch string case "simple" rd = 1e6; for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]); endfor vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); vgs = vg-vs; vds = vd-vs; if (vgs > Vth) gm = 0; gd = 1/rd; id = vds*gd; elseif (((vgs-Vth) <= (vds)) && (vds<=0)) id = k*((vgs-Vth)*vds-(vds^2)/2)+vds/rd; gm = k*vds; gd = k*(vgs-Vth-vds)+1/rd; elseif (((vgs-Vth) <= (vds)) && (vds>0)) gm = 0; gd = 1/rd; id = vds*gd; else id = k*(vgs-Vth)^2/2+vds/rd; gm = k*(vgs-Vth); gd = 1/rd; endif a = zeros(4); b = [0 0 0 0; -gm (gm+gd) -gd 0; gm -(gm+gd) gd 0; 0 0 0 0 ]; c =[0 -id id 0]'; break; case "lincap" ## Default parameter values if isempty(intvar) intvar = zeros(5,1); endif Rs = 1e2; Rd = 1e2; Cs = 1e-15; Cd = 1e-15; Cb = 1e-12; rd = inf; k = -1e-3; Vth = -.1; ## parameters given in input for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]) endfor mtdpmos = file_in_path(path,"Mtdpmos.cir"); mtdpmos(end-3:end)=[]; tmpstruct = prs_iff(mtdpmos); tmpstruct.NLC.pvmatrix = [k Vth rd]; tmpstruct.LCR(1).pvmatrix = [Rs; Rd]; tmpstruct.LCR(2).pvmatrix = [Cs; Cd; Cb]; [A0,B,C] = asm_initialize_system(tmpstruct,[extvar;intvar]); [A1,Jac,res] = asm_build_system(tmpstruct,[extvar;intvar],t); a = A0+A1; b = B+Jac; c = res + B*[extvar;intvar] + C; break; otherwise error(["unknown option:" string]); endswitch endfunction ocs/inst/sbn/Mresistors.m0000644000076500000000000000720011334211056014702 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco, Culpo Massimiliano ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## author: culpo@math.uni-wuppertal.de ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=}Mresistors(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing models for resistors. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "LIN" (Linear resistor) ## @itemize @minus ## @item R -> resistance value ## @end itemize ## @item @var{string} = "THERMAL" (Linear resistor with termal pin) ## @itemize @minus ## @item R0 -> reference resistance value at temperature @code{TNOM} ## @item TC1 -> coefficient for first order Taylor expansion ## @item TC2 -> coefficient for second order Taylor expansion ## @item TNOM -> reference temperature ## @end itemize ## @item @var{string} = "THERMAL1D" (1D Thermal resistor) ## @itemize @minus ## @item L -> length of 1D domain ## @item N -> number of discretized elements ## @item cv -> PDE coefficient for dynamic part ## @item k -> PDE coefficient for diffusion part ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c] =Mresistors(string,parameters,parameternames,extvar,intvar,t) switch string ## LCR part case "LIN" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor vp = extvar(1); vm = extvar(2); a = zeros(2); b = [1 -1 ;-1 1]/R; c = -[0; 0]; break ##NLCpart case "THERMAL" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor v1 = extvar(1); v2 = extvar(2); T = extvar(3); RT = R0*(1 + TC1*(T-TNOM) + TC2*(T - TNOM)^2); dRdT = R0*(TC1 + 2*TC2*(T-TNOM)); i1 = (v1-v2)/RT; i2 = (v2-v1)/RT; P = -(v1-v2)^2/RT; a = zeros(3); b = [ 1/RT -1/RT (v2-v1)*dRdT/RT^2;... -1/RT 1/RT (v1-v2)*dRdT/RT^2;... -2*(v1-v2)/RT -2*(v2-v1)/RT (v1-v2)^2*dRdT/RT^2]; c = [i1 i2 P]'; break; case "THERMAL1D" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor h = L/N; A = (cv*S*h)*speye(N+1); B = spdiags([ -ones(N+1,1) 2*ones(N+1,1) -ones(N+1,1)],-1:1,N+1,N+1); B(1 ,1) = 1; B(N+1 ,N+1) = 1; ext=[1 N+1]; int=[2:N]; a = [A(ext,ext), A(ext,int); A(int,ext), A(int,int)]; b = k*(S/h)*[B(ext,ext), B(ext,int); B(int,ext), B(int,int)]; c = zeros(N+1,1); break; otherwise error (["unknown section:" string]) endswitch endfunction ocs/inst/sbn/Mshichmanhodgesmosfet.m0000644000076500000000000001670711617232116017067 0ustar carlowheel## Copyright (C) 2006-2009 Carlo de Falco, Massimiliano Culpo ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco , culpo@math.uni-wuppertal.de ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=} Mshichmanhodgesmosfet(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing Schichman-Hodges MOSFETs model. ## ## @var{string} is used to select among models. Possible models are: ## ## @enumerate ## @item @var{string} = "NMOS" (Schichman-Hodges n-MOSFET) ## @item @var{string} = "PMOS" (Schichman-Hodges p-MOSFET) ## @end enumerate ## ## Parameters for all the above models are: ## @itemize ## @item rd -> parasitic resistance between drain and source ## @item W -> MOSFET width ## @item L -> channel length ## @item mu0 -> reference value for mobility ## @item Vth -> threshold voltage ## @item Cox -> oxide capacitance ## @item Cgs -> gate-source capacitance ## @item Cgd -> gate-drain capacitance ## @item Cgb -> gate-bulk capacitance ## @item Csb -> source-bulk capacitance ## @item Cdb -> drain-bulk capacitance ## @item Tshift -> shift for reference temperature on MOSFETs (default 0) ## @end itemize ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c]= Mshichmanhodgesmosfet (string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) ## If intvar is empty, then we are initializing the system ## and there is no need of a matrix evaluation a = sparse(10,10); b = []; c = []; else ## If intvar is NOT empty, then we are evaluating the ## element stamp switch string case "NMOS" rd = 1e6; W = 1; L = 1; mu0 = 1e-5; Vth = .5; Cox = 1e-9; Cgb = Cox; Cgs=Cgd=Csb=Cdb=.1*Cox; Tshift = 0; for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]) endfor [gm,gd,ids,didT,P,dPdT,dPdvgs,dPdvds] = \ nmos(extvar,mu0,Cox,W,L,Vth,rd,Tshift); vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); T = max(extvar(5),0); if isempty(intvar) intvar = zeros(5,1); endif Qgb = intvar(1); Qgs = intvar(2); Qgd = intvar(3); Qsb = intvar(4); Qdb = intvar(5); a11 = a21 = a22 = zeros(5,5); a12 = [ 1 1 1 0 0; \ 0 -1 0 1 0; \ 0 0 -1 0 1; \ -1 0 0 -1 -1; \ 0 0 0 0 0]; a = [a11 a12; a21 a22]; b11 = [0 0 0 0 0; \ -gm (gm+gd) -gd 0 -didT; \ gm -(gm+gd) gd 0 didT; \ 0 0 0 0 0; \ dPdvgs -(dPdvgs+dPdvds) dPdvds 0 dPdT]; b12 = zeros(5,5); b21 = [Cgb 0 0 -Cgb 0; \ Cgs -Cgs 0 0 0; \ Cgd 0 -Cgd 0 0; \ 0 Csb 0 -Csb 0; \ 0 0 Cdb -Cdb 0]; b22 = -eye(5); b = [b11 b12; b21 b22]; c1 = [0; -ids; ids; 0; P]; c2 = [Cgb*(vg - vb) - Qgb;\ Cgs*(vg - vs) - Qgs;\ Cgd*(vg - vd) - Qgd;\ Csb*(vs - vb) - Qsb;\ Cdb*(vd - vb) - Qdb]; c = [c1;c2]; break; case "PMOS" rd = 1e6; W = 1; L = 1; mu0 = 1e-5; Vth = -.5; Cox = 1e-9; Cgb=Cox; Cgs=Cgd=Csb=Cdb=.1*Cox; Tshift = 0; for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]) endfor [gm,gd,ids,didT,P,dPdT,dPdvgs,dPdvds] = \ pmos(extvar,mu0,Cox,W,L,Vth,rd,Tshift); vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); T = extvar(5); if isempty(intvar) intvar = zeros(5,1); endif Qgb = intvar(1); Qgs = intvar(2); Qgd = intvar(3); Qsb = intvar(4); Qdb = intvar(5); a11 = a21 = a22 = zeros(5,5); a12 = [ 1 1 1 0 0; \ 0 -1 0 1 0; \ 0 0 -1 0 1; \ -1 0 0 -1 -1; \ 0 0 0 0 0]; a = [a11 a12; a21 a22]; b11 = [0 0 0 0 0; \ -gm (gm+gd) -gd 0 -didT; \ gm -(gm+gd) gd 0 didT; \ 0 0 0 0 0; \ dPdvgs -(dPdvgs+dPdvds) dPdvds 0 dPdT]; b12 = zeros(5,5); b21 = [Cgb 0 0 -Cgb 0; \ Cgs -Cgs 0 0 0; \ Cgd 0 -Cgd 0 0; \ 0 Csb 0 -Csb 0; \ 0 0 Cdb -Cdb 0]; b22 = -eye(5); b = [b11 b12; b21 b22]; c1 = [0; -ids; ids; 0; P]; c2 = [Cgb*(vg - vb) - Qgb;\ Cgs*(vg - vs) - Qgs;\ Cgd*(vg - vd) - Qgd;\ Csb*(vs - vb) - Qsb;\ Cdb*(vd - vb) - Qdb]; c = [c1;c2]; break; otherwise error(["unknown option:" string]); endswitch endif endfunction function [gm,gd,ids,didT,P,dPdT,dPdvgs,dPdvds] = nmos(extvar,mu0,Cox,W,L,Vth,rd,Tshift) ##Computes values for nmos case vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); T = max(extvar(5),0); k = mu0*Cox*((T + Tshift)/300)^(-3/2)*W/L; dkdT = mu0*Cox*W*(-3/2)*((T + Tshift)/300)^(-5/2)*(1/300)/L; vgs = vg-vs; vds = vd-vs; if (vgs < Vth) gm = 0; gd = 1/rd; ids = vds*gd; didT= 0; elseif (((vgs-Vth) >= (vds)) && (vds >= 0)) ids = k*((vgs-Vth)*vds-(vds^2)/2)+vds/rd; gm = k*vds; gd = k*(vgs-Vth-vds) + 1/rd; didT= dkdT*((vgs-Vth)*vds-(vds^2)/2); elseif (((vgs-Vth) >= (vds)) && (vds < 0)) gm = 0; gd = 1/rd; ids = vds*gd; didT= 0; else # (i.e. if 0 <= vgs-vth <= vds) ids = (k/2)*(vgs-Vth)^2+vds/rd; gm = k*(vgs-Vth); gd = 1/rd; didT= (dkdT/(2))*(vgs-Vth)^2; endif P = -ids * vds; dPdT = -didT* vds; dPdvgs = -(gm*vds); dPdvds = -(gd*vds + ids); endfunction function [gm,gd,ids,didT,P,dPdT,dPdvgs,dPdvds] = pmos(extvar,mu0,Cox,W,L,Vth,rd,Tshift) ##Computes values for pmos case vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); T = extvar(5); k = - mu0 * Cox * ((T + Tshift)/300)^(-3/2) *W/L; dkdT = - mu0 * Cox * W *(-3/2)*((T + Tshift)/300)^(-5/2)*(1/300)/L; vgs = vg-vs; vds = vd-vs; if (vgs > Vth) gm = 0; gd = 1/rd; ids = vds*gd; didT= 0; elseif (((vgs-Vth) <= (vds)) && (vds <= 0)) ids = k*((vgs-Vth)*vds-(vds^2)/2)+vds/rd; gm = k*vds; gd = k*(vgs-Vth-vds)+1/rd; didT= dkdT*((vgs-Vth)*vds-(vds^2)/2); elseif (((vgs-Vth) <= (vds)) && (vds > 0)) gm = 0; gd = 1/rd; ids = vds*gd; didT= 0; else ids = (k/2)*(vgs-Vth)^2+vds/rd; gm = k*(vgs-Vth); gd = 1/rd; didT= (dkdT/(2))*(vgs-Vth)^2; endif P = -ids * vds; dPdT = -didT* vds; dPdvgs = -(gm*vds); dPdvds = -(gd*vds + ids); endfunctionocs/inst/sbn/Mtdnmos.cir0000644000076500000000000000041111334211056014467 0ustar carlowheel% 0.1b1 % A Simple MOSFET model % including charge stores % N-Mosfet Mnmosfet simple 4 3 1 3 k Vth rd 1 1 1e30 1 5 6 4 END % Resistors Mresistors LIN 2 1 2 1 R 1 1 2 5 3 6 % Capacitors Mcapacitors LIN 2 1 3 1 C 1 1 1 1 5 1 6 1 4 END ocs/inst/sbn/Mtdnmos.nms0000644000076500000000000000006611334211056014515 0ustar carlowheel% 0.1b1 1 Vg 2 Vs 3 Vd 4 Vb 5 Vsi 6 Vdi 7 Qs 8 Qd 9 Qbocs/inst/sbn/Mtdpmos.cir0000644000076500000000000000041111334211056014471 0ustar carlowheel% 0.1b1 % A Simple MOSFET model % including charge stores % N-Mosfet Mpmosfet simple 4 3 1 3 k Vth rd 1 1 1e30 1 5 6 4 END % Resistors Mresistors LIN 2 1 2 1 R 1 1 2 5 3 6 % Capacitors Mcapacitors LIN 2 1 3 1 C 1 1 1 1 5 1 6 1 4 END ocs/inst/sbn/Mtdpmos.nms0000644000076500000000000000006611334211056014517 0ustar carlowheel% 0.1b1 1 Vg 2 Vs 3 Vd 4 Vb 5 Vsi 6 Vdi 7 Qs 8 Qd 9 Qbocs/inst/sbn/Mvoltagesources.m0000644000076500000000000001145211334211056015716 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=} Mvoltagesources(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing models for voltage sources. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "DC" (Static indipendent voltage source) ## @itemize @minus ## @item V -> Current source value ## @end itemize ## @item @var{string} = "sinwave" (Sinusoidal indipendent voltage ## source) ## @itemize @minus ## @item shift -> mean value of sinusoidal input ## @item Ampl -> amplitude of sinusoidal wave ## @item f -> frequency of sinusoidal wave ## @item delay -> delay of sinusoidal wave ## @end itemize ## @item @var{string} = "pwl" (Piecewise linear voltage source) ## @itemize @minus ## @item takes as parameter times and values. For example @code{0 1 4 6} ## means at time instant 0 value 1, at time instant 4 value 6, etc. ## @end itemize ## @item @var{string} = "squarewave" (Square wave) ## @itemize @minus ## @item low -> low-state value ## @item high -> high-state value ## @item tlow -> duration of low-state ## @item thigh -> duration of high-state ## @item delay -> delay of square wave ## @item start -> starting voltage value ## @end itemize ## @item @var{string} = "step" (Voltage step) ## @itemize @minus ## @item low -> low-state value ## @item high -> high-state value ## @item tstep -> time instant of step transition ## @end itemize ## @item @var{string} = "VCVS" (Voltage controlled voltage source) ## @itemize @minus ## @item K -> Control parameter ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c] = Mvoltagesources (string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) intvar = 0; endif switch string ##LCR part case "DC" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor j = intvar(1); a = zeros(3); b = [0 0 1;0 0 -1;1 -1 0]; c = [0 0 -V]; break ## NLC part case "sinwave" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor DV = shift+Ampl * sin(2*pi*(t+delay)*f ); j = intvar(1); a = zeros(3); b = [0 0 1;0 0 -1;1 -1 0]; c = [0 0 -DV]' + b * [extvar;intvar]; break case "pwl" times = parameters(1:2:end-1); values= parameters(2:2:end); DV = interp1(times,values,t,"linear","extrap"); j = intvar(1); a = zeros(3); b = [0 0 1;0 0 -1;1 -1 0]; c = [0 0 -DV]' + b * [extvar;intvar]; break case "squarewave" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor if t. ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} {[@var{out},@var{niter}] =} @ ## tst_backward_euler(@var{cirstruct},@var{x},@var{t},@var{tol},@ ## @var{maxit},@var{pltvars},@var{verbosity},@var{dae_fun}) ## ## Perform a transient simulation of the system described by ## @var{cirstruct} over the time interval @var{t} using the backward ## Euler algorithm. ## ## The initial value for the state vector is computed by solving a ## steady state problem at @var{t}(1), with starting guess @var{x}. ## ## @var{tol} and @var{maxit} are parameters passed to ## @code{nls_newton_raphson}. ## ## The output @var{out} will contain the value of the state vector at ## each point of @var{t}. ## ## The optional parameter @var{verbosity} controls the amount of ## output produced: ## ## @itemize @minus ## @item if verbosity(1) != 0, information on the progress ## of the algorithm are output at runtime ## @item if verbosity(2) != 0, the plot of the variables whose names ## are listed in @var{pltvars} is ## produced after the computation ## @end itemize ## ## For special purposes one may need to pass modified jacobian and ## residual functions. This can be done via the cell array of function ## handles @var{dae_fun}. ## ## Such functions should have the same input and output ## parameter list as the default sub-functions ## TSTBWEFUNJAC0,TSTBWEFUNRES0, TSTBWEFUNJAC,TSTBWEFUNRES. ## ## The optional output @var{niter} returns the number of Newton iterations ## needed to reach convergence. ## ## @seealso{tst_daspk,tst_theta_method,tst_odepkg,nls_newton_raphson} ## ## @end deftypefn function [out, varargout] = tst_backward_euler (outstruct, x, t, tol, maxit, pltvars, verbosity, dae_fun) ## Check input ## FIXME: add input check! if ((nargin < 6) || (nargin > 8)) error ("tst_backward_euler: wrong number of input parameters."); endif if ~exist ("verbosity") verbosity = [0,0]; elseif (length (verbosity) < 2) verbosity(2) = 0; endif out = zeros (rows (x), columns (t)); out(:,1) = x; if nargout > 1 niter = zeros (length(t),1); endif if (verbosity(1)) fprintf (1, "Initial value.\n"); endif [A0, B, C] = asm_initialize_system (outstruct, x); if (nargin > 8) JAC = @(x) dae_fun{1} (outstruct,x,t(1),B); RES = @(x) dae_fun{2} (outstruct,x,t(1),B,C); [out(:,1), ii, resnrm] = nls_newton_raphson (x, RES, JAC, tol, maxit, verbosity(1)); else [out(:,1),ii] = nls_stationary (outstruct, x, tol, maxit); endif if (nargout > 1) niter(1) = ii; endif for it = 2:length (t) if (verbosity(1)) fprintf (1,"Timestep #%d.\n",it); endif if nargin > 8 JAC = @(x) dae_fun{3} (outstruct, x, t(it-1), t(it), A0, B); RES = @(x) dae_fun{4} (outstruct, x, out(:,it-1), t(it-1), t(it), A0, B, C); else JAC = @(x,A1,Jac,res) TSTBWEFUNJAC1(outstruct, x, t(it-1), t(it), A0, B, A1, Jac, res); RES = @(x,A1,Jac,res) TSTBWEFUNRES1(outstruct, x, out(:,it-1), t(it-1), t(it), A0, B, C, A1, Jac, res); UPDT = @(x) TSTBWEFUNUP1 (outstruct, x, t(it)); endif [out(:,it),ii,resnrm] = nls_newton_raphson (out(:,it-1), RES, JAC, tol, maxit, verbosity(1), UPDT); if nargout > 1 niter(it) = ii; endif if (verbosity(2)) utl_plot_by_name (t(1:it), out(:,1:it), outstruct, pltvars); drawnow (); endif ## Stop at runtime ## FIXME: maintain this part? if exist("~/.stop_ocs","file") printf("stopping at timestep %d\n",it); unix("rm ~/.stop_ocs"); break end endfor if nargout > 1 varargout{1} = niter; endif endfunction ## Jacobian for transient problem function lhs = TSTBWEFUNJAC1 (outstruct, x, t0, t1, A0, B, A1, Jac, res) DT = t1-t0; if (nargin < 9) [A1, Jac, res] = asm_build_system (outstruct, x, t1); endif lhs = ((A0+A1)/DT + B + Jac); endfunction ## Residual for transient problem function rhs = TSTBWEFUNRES1 (outstruct, x, xold, t0, t1, A0, B, C, A1, Jac, res) DT = t1-t0; if ( nargin < 11 ) [A1, Jac, res] = asm_build_system (outstruct, x, t1); endif rhs = (res + C + B*x + (A0+A1)*(x-xold)/DT); endfunction ## Update for transient problem function update = TSTBWEFUNUP1 (outstruct, x, t1) [A1, Jac, res] = asm_build_system (outstruct, x, t1); update = {A1, Jac, res}; endfunctionocs/inst/tst/tst_daspk.m0000644000076500000000000001034111523470456014567 0ustar carlowheel## Copyright (C) 2006,2007,2008,2011 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} {[@var{out}] =} tst_daspk @ ## (@var{cirstruct},@var{x},@var{t},@var{tol},@var{maxit},@ ## @var{pltvars},@var{verbosity},@var{daskopts},@var{dae_fun}); ## ## Perform a transient simulation of the system described by ## @var{cirstruct} over the time interval @var{t} using @code{daspk}. ## ## The initial value for the state vector is computed by solving a ## steady state problem at @var{t}(1), with starting guess @var{x}. ## ## @var{tol} and @var{maxit} are parameters passed to ## @code{nls_newton_raphson}. ## ## The output @var{out} will contain the value of the state vector ## at each point of @var{t}. ## ## Extra options for @code{daspk} can be passed as name/value pairs in ## the cellarray @var{daskopts}. ## ## The optional parameter @var{verbosity} controls the amount of ## output produced: ## ## @itemize @minus ## @item if verbosity(1) != 0, information on the progress ## of the algorithm are output at runtime ## @item if verbosity(2) != 0, the plot of the variables whose names ## are listed in @var{pltvars} is ## produced after the computation ## @end itemize ## ## For special purposes one may need to pass modified jacobian and ## residual functions. This can be done via the cell array of function ## handles @var{dae_fun}. ## ## Such functions should have the same input and output ## parameter list as the default sub-functions ## TSTBWEFUNJAC0,TSTBWEFUNRES0, TSTBWEFUNJAC,TSTBWEFUNRES. ## ## @seealso{tst_backward_euler,tst_odepkg,tst_theta_method,nls_newton_raphson,daspk} ## ## @end deftypefn function [out] = tst_daspk (outstruct, x, t, tol, maxit, pltvars, verbosity, daspkopts, dae_fun) ## FIXME: add input check! if ((nargin < 6) || (nargin > 9)) error ("tst_daspk: wrong number of input parameters."); endif if (! exist ("verbosity")) verbosity = [0, 0]; elseif (length (verbosity) < 2) verbosity(2) = 0; endif if (verbosity(1)) fprintf (1, "initial value:\n"); endif daspk_options ("print initial condition info",1); daspk_options ("maximum order",2); daspk_options ("initial step size",t(2)-t(1)); daspk_options ("relative tolerance",1e-3); if (nargin > 8) for ii = 1:2:length (daspkopts) daspk_options (daspkopts{ii}, daspkopts{ii+1}); endfor endif [A0, B, C] = asm_initialize_system (outstruct, x); if (nargin > 9) JAC = @(x) dae_fun{1} (outstruct, x, t(1), B); RES = @(x) dae_fun{2} (outstruct, x, t(1), B, C); [x, ii, resnrm] = nls_newton_raphson (x, RES, JAC, tol, maxit, verbosity); else [out(:,1), ii] = nls_stationary (outstruct, x, tol, maxit); endif if (nargin > 9) JAC = @(x) dae_fun{3} (outstruct, x, t(1), B); RES = @(x) dae_fun{4} (outstruct, x, t(1), B, C); else JAC = @(x,xdot,t,c) TSTDASPKFUNJAC (outstruct, x, xdot, A0, B, t, c); RES = @(x,xdot,t) TSTDASPKFUNRES (outstruct, x, xdot, A0, B, C, t); endif [out, xdot, istate, msg] = daspk ({RES,JAC}, out(:,1), zeros (size (x)), t); out = out.'; if (verbosity(2)) utl_plot_by_name (t, out, outstruct, pltvars) endif endfunction ## Jacobian for transient problem function lhs = TSTDASPKFUNJAC (outstruct, x, xdot, A0, B, t, c) [A1, Jac, res] = asm_build_system (outstruct, x, t); lhs = (c*(A0+A1) + B + Jac); endfunction ## Residual for transient problem function rhs = TSTDASPKFUNRES (outstruct, x, xdot, A0, B, C, t) [A1, Jac, res] = asm_build_system (outstruct, x, t); rhs = (A0+A1)*xdot + B*x + C + res; endfunctionocs/inst/tst/tst_odepkg.m0000644000076500000000000001222111334211056014722 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} {[@var{out}, [@var{tout}]] =} tst_odepkg @ ## (@var{cirstruct},@var{x},@var{t},@var{tol},@var{maxit},@ ## @var{pltvars},@var{solver},@var{odestruct},@var{verbosity}); ## ## Perform a transient simulation of the system described by ## @var{cirstruct} over the time interval @var{t} using the @code{odepkg} DAE ## solver specified in @var{solver}. ## ## Pssible values for @var{solver} are @code{ode2r}, @code{ode5r}, ## @code{oders} or @code{odesx}. ## ## The initial value for the state vector is computed by solving a ## steady state problem at @var{t}(1), with starting guess @var{x}. ## ## @var{tol} and @var{maxit} are parameters passed to @code{nls_newton_raphson}. ## ## If one output is requested @var{out} will contain the value of the state vector ## at each point of @var{t}. ## ## If two outputs are requested @var{out} will contain the value of the state vector ## at each point of @var{tout}. ## ## Extra options for options for the solver can be passed to the solver ## via @var{odestruct}. ## ## The optional parameter @var{verbosity} controls the amount of ## output produced: ## ## @itemize @minus ## @item if verbosity(1) != 0, information on the progress ## of the algorithm are output at runtime ## @item if verbosity(2) != 0, the plot of the variables whose names ## are listed in @var{pltvars} is ## produced after the computation ## @end itemize ## ## @seealso{tst_backward_euler,tst_theta_method,tst_daspk,nls_newton_raphson,odepkg,odeset,@ ## ode2r,ode5r,oders,odesx} ## ## @end deftypefn function [out, tout] = tst_odepkg (outstruct,x,t,tol,maxit,\ pltvars,solver,verbosity,odestruct) ## Check input ## FIXME: add input check! if ((nargin < 7) || (nargin > 9)) error("tst_odepkg:wrong number of input parameters"); endif if ~exist("verbosity") verbosity = [0,0]; elseif length(verbosity)<2 verbosity(2) =0; endif if(verbosity(1)) fprintf(1,"initial value:\n"); endif if ~exist("odestruct") odestruct = odeset(); endif [A0,B,C] = asm_initialize_system(outstruct,x); [out(:,1),ii] = nls_stationary(outstruct,x,tol,maxit); JAC = @(t, x) TSTODEPKGFUNJAC(outstruct, x, A0, B, t); RES = @(t, x) TSTODEPKGFUNRES(outstruct, x, A0, B, C, t); MASS= @(t, x) TSTODEPKGFUNMASS(outstruct, x, A0, t); odestruct = odeset(odestruct,"Jacobian", JAC); odestruct = odeset(odestruct,"Mass",MASS(0,x)); odestruct = odeset(odestruct,"RelTol", 1e-6,"AbsTol",1e6*eps, "MaxStep", max(diff(t)),"InitialStep",(diff(t))(1)); if verbosity(2) odestruct = odeset(odestruct, "OutputFcn", @(t, y, flag) plotfun(t, y, flag, outstruct, pltvars) ); endif [tout, out] = feval( solver, RES, t([1 end]), x, odestruct); if (nargout < 2) out = interp1(tout, out, t).'; endif endfunction function [varargout] = plotfun (vt, vy, vflag, outstruct, pltvars) ## this function is a modified version of odeplot distributed ## with odepkg (c) Thomas Treichl %# No input argument check is done for a higher processing speed persistent vfigure; persistent vtold; persistent vyold; persistent vcounter; if (strcmp (vflag, "init")) %# Nothing to return, vt is either the time slot [tstart tstop] %# or [t0, t1, ..., tn], vy is the inital value vector 'vinit' vfigure = figure; vtold = vt(1,1); vyold = vy(:,1); vcounter = 1; elseif (isempty (vflag)) %# Return something in varargout{1}, either false for 'not stopping %# the integration' or true for 'stopping the integration' vcounter = vcounter + 1; figure (vfigure); vtold(vcounter,1) = vt(1,1); vyold(:,vcounter) = vy(:,1); utl_plot_by_name(vtold, vyold, outstruct, pltvars); drawnow; varargout{1} = false; elseif (strcmp (vflag, "done")) %# Cleanup has to be done, clear the persistent variables because %# we don't need them anymore clear ("vfigure","vtold","vyold","vcounter"); endif endfunction ## Jacobian for transient problems function lhs = TSTODEPKGFUNJAC(outstruct,x,A0,B,t) [A1,Jac,res] = asm_build_system(outstruct,x,t); lhs = ( B + Jac); endfunction function lhs = TSTODEPKGFUNMASS(outstruct,x,A0,t) [A1,Jac,res] = asm_build_system(outstruct,x,t); lhs = -(A0+A1); endfunction ## Residual for transient problems function rhs = TSTODEPKGFUNRES(outstruct,x,A0,B,C,t) [A1,Jac,res] = asm_build_system(outstruct,x,t); rhs = B*x + C + res; endfunctionocs/inst/tst/tst_theta_method.m0000644000076500000000000001062211334211056016121 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} {[@var{out},@var{niter}] =} tst_theta_method @ ## (@var{cirstruct},@var{x},@var{t},@var{tol},@ ## @var{maxit},@var{theta},@var{pltvars},@ ## @var{verbosity}); ## ## Perform a transient simulation of the system described by ## @var{cirstruct} over the time interval @var{t} using the ## theta-method with parameter @var{theta}. ## ## The initial value for the state vector is computed by solving a ## steady state problem at @var{t}(1), with starting guess @var{x}. ## ## @var{tol} and @var{maxit} are parameters passed to ## @code{nls_newton_raphson}. ## ## The output @var{out} will contain the value of the state vector at ## each point of @var{t}. ## ## The optional parameter @var{verbosity} controls the amount of ## output produced: ## ## @itemize @minus ## @item if verbosity(1) != 0, information on the progress ## of the algorithm are output at runtime ## @item if verbosity(2) != 0, the plot of the variables whose names ## are listed in @var{pltvars} is ## produced after the computation ## @end itemize ## ## The optional output @var{niter} returns the number of Newton iterations ## needed to reach convergence. ## ## @seealso{tst_backward_euler,tst_daspk,tst_odepkg,nls_newton_raphson} ## ## @end deftypefn function [out, varargout] = tst_theta_method(outstruct,x,t,tol,maxit,\ theta,pltvars,verbosity) ## Check input ## FIXME: add input check! if ((nargin < 7) || (nargin > 8)) error("tst_theta_method: wrong number of input parameters."); endif if ~exist("verbosity") verbosity = [0,0]; elseif length(verbosity)<2 verbosity(2) = 0; endif out = zeros(rows(x),columns(t)); out(:,1) = x; if nargout > 1 niter = zeros(length(t),1); endif if (verbosity(1)) fprintf(1,"Initial value.\n"); endif [A0,B,C] = asm_initialize_system(outstruct,x); [out(:,1),ii] = nls_stationary(outstruct,x,tol,maxit); if nargout > 1 niter(1) = ii; endif for it=2:length(t) if(verbosity) fprintf(1,"Timestep #%d.\n",it); endif [A1old,Jacold,resold] = asm_build_system(outstruct, out(:,it-1), t(it-1)); JAC = @(x,A1,Jac,res) TSTTHETAFUNJAC1(outstruct, x, t(it-1), t(it), A0, B, theta, A1, Jac, res); RES = @(x,A1,Jac,res) TSTTHETAFUNRES1(outstruct, x, out(:,it-1), t(it-1), t(it), A0, B, C, resold, theta, A1, Jac, res); UPDT = @(x) TSTTHETAFUNUP1 (outstruct, x, t(it)); [out(:,it),ii,resnrm] = nls_newton_raphson(out(:,it-1),RES,JAC,\ tol, maxit,verbosity(1),\ UPDT); if nargout > 1 niter(it) = ii; endif if (verbosity(2)) utl_plot_by_name(t(1:it),out(:,1:it),outstruct,pltvars); pause(.1); endif if exist("~/.stop_ocs","file") break end endfor if nargout > 1 varargout{1} = niter; endif endfunction ## Jacobian for transient problem function lhs = TSTTHETAFUNJAC1(outstruct, x, t0, t1, A0, B, theta, A1, Jac, res) DT = t1-t0; if ( nargin < 10 ) [A1,Jac,res] = asm_build_system(outstruct,x,t1); endif lhs = ( (A0+A1)/DT + theta*(B + Jac) ); endfunction ## Residual for transient problem function rhs = TSTTHETAFUNRES1(outstruct, x, xold, t0, t1, A0, B, C, resold, theta, A1, Jac, res) DT = t1-t0; if ( nargin < 13 ) [A1,Jac,res] = asm_build_system(outstruct,x,t1); endif rhs = ( (A1+A0)*(x-xold)/DT + theta * (res + C + B*x) + (1-theta) * (resold + C + B*xold) ); endfunction ## Update for transient problem function update = TSTTHETAFUNUP1(outstruct,x,t1) [A1,Jac,res] = asm_build_system(outstruct,x,t1); update = {A1,Jac,res}; endfunctionocs/inst/utl/0000755000076500000000000000000011706606202012401 5ustar carlowheelocs/inst/utl/utl_plot_by_name.m0000644000076500000000000000351011533543616016121 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## @deftypefn{Function File} {} utl_plot_by_name(@var{t},@var{out}, @ ## @var{outstruct},@var{namelist}) ## ## Select by name some elements of the state vector of the system described ## by @var{outstruct} and plot their dynamics over the time interval ## @var{t}. ## ## @var{namelist} should contain the list of names of the variables ## to plot. ## @var{out} should be the output of a transient simulation over the ## time interval @var{t} ## ## @seealso{tst_backward_euler,tst_daspk,tst_theta_method,tst_odepkg,prs_iff} ## ## @end deftypefn function utl_plot_by_name (t, out, outstruct, namelist) if (nargin != 4) error ("utl_plot_by_name: wrong number of input parameters.") endif nn = length (outstruct.namesn); leg = {}; ileg = 0; for ip = 1:nn for in = 1:length (namelist) if (strcmp (namelist{in},outstruct.namess{ip})) plot (t, out(outstruct.namesn(ip), :), sprintf("%d", mod (in+1, 6) + 1)); leg{++ileg} = outstruct.namess{ip}; hold on endif endfor endfor legend (leg{:}); hold off endfunctionocs/inst/utl/utl_sbn_server.m0000644000076500000000000000437511334211056015620 0ustar carlowheel## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## @deftypefn{Function File} {} utl_sbn_server(@var{port}) ## Listen for socket connections on port @var{port}, read a command @ ## and return the corresponding output to the socket. ## @end deftypefn function utl_sbn_server (portnum) QUITMESSAGE = "quit UTLsbnserver"; CONFIRMMESSAGE = "confirmed"; ## CREATE THE SOCKET AND WAIT FOR CONNECTIONS s = socket(AF_INET, SOCK_STREAM, 0); if s < 0 error("cannot create socket\n"); end if bind(s, portnum) < 0 error("bind failed\n"); end if listen(s, 1) < 0 error("listen failed\n"); end ##MAIN LOOP while 1 ##ACCEPT CONNECTIONS c = accept(s); if c < 0 error("connection error") end ## READ COMMANDS FROM THE SOCKET msg = readstring (c) ##IF CLIENT SENT SHUTDOWN MESSAGE EXIT if strcmp (msg,QUITMESSAGE) printf("client requested server shutdown, goodbye!\n"); disconnect(c); disconnect(s); break end ##EXECUTE COMMANDS FROM THE CLIENT [A,B,C] = eval(msg); ##SEND OUTPUT TO THE CLIENT str = [ sprintf("%17g ",A) "\n" sprintf("%17g ",B)... "\n" sprintf("%17g ",C) "\n"] send(c,str); ##END CONNECTION disconnect(c); end disconnect(s); endfunction function msg = readstring (c) BUFFER_SIZE = 255; msg = ''; read = BUFFER_SIZE; while read >= BUFFER_SIZE newmsg = char(recv(c, BUFFER_SIZE)); read = length(newmsg) msg = [ msg newmsg]; end endfunction ocs/PKG_ADD0000644000076500000000000000106511617232116011636 0ustar carlowheeldirlist = {"utl", "asm", "tst", "nls", "prs", "sbn"}; dirname = fileparts (canonicalize_file_name (mfilename ("fullpath"))); if (! exist (fullfile (dirname, "inst"), "dir")) ## Run this if the package is installed for ii=1:length (dirlist) addpath ( [ dirname "/../" dirlist{ii}],"-end") endfor else ## Run this if we are testing the package without installation for ii=1:length(dirlist) addpath ([ dirname "/inst/" dirlist{ii}]) addpath ([ dirname "/src/"]) endfor endif warning('off', 'Octave:fopen-file-in-path'); clear dirlist dirname ocs/PKG_DEL0000644000076500000000000000073311617232116011653 0ustar carlowheeldirlist = {"utl", "asm", "tst", "nls", "prs", "sbn"}; dirname = fileparts (canonicalize_file_name (mfilename ("fullpath"))); for ii=1:length (dirlist) if (! exist (fullfile (dirname, "inst"), "dir")) ## Run this if the package is installed rmpath ( [ dirname "/../" dirlist{ii}]) else ## Run this if we are testing the package without installation rmpath ([ dirname "/inst/" dirlist{ii}]) rmpath ([ dirname "/src/"]) end end clear dirlist dirname ocs/README0000644000076500000000000000175411601145313011502 0ustar carlowheel OCS - A Circuit Simulator for Octave ------------------------------------------------------------------- Copyright (C) 2006 Carlo de Falco This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see the file LICENSE); if not, write to the Free Software Foundation, Inc. 51 Franklin Street - Fifth Floor Boston MA 02110-1301 USA For more information, you may also contact me by email at carlo.defalco@gmail.com I would also appreciate it if you drop me a line just to say that you are you using the program ocs/src/0000755000076500000000000000000011706606201011406 5ustar carlowheelocs/src/Makefile0000644000076500000000000000020011334212227013034 0ustar carlowheelOCTFILES:=Mshichmanhodgesmosfet.oct all: $(OCTFILES) %.oct: %.cc mkoctfile $< clean: -rm -f *.o core octave-core *.oct *~ ocs/src/Mshichmanhodgesmosfet.cc0000644000076500000000000003523711334212227016244 0ustar carlowheel/* Copyright (C) 2009 Massimiliano Culpo This file is part of: OCS - A Circuit Simulator for Octave OCS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see the file LICENSE); if not, see . author: Massimiliano Culpo */ #include #include #include #include #include using namespace std; /* Print parameters */ void print_parameters(double rd, double W, double L, double mu0, double Vth, double Cox, double Cgs, double Cgd, double Cgb, double Csb, double Cdb, double Tshift) { octave_stdout << "PARAMETER TABLE: Simplified Shichman-Hodges MOS-FET\n\n"; octave_stdout << "Name\t\tValue\n"; octave_stdout << "rd\t\t" << rd << "\n" ; octave_stdout << "W\t\t" << W << "\n" ; octave_stdout << "L\t\t" << L << "\n" ; octave_stdout << "mu0\t\t" << mu0 << "\n" ; octave_stdout << "Vth\t\t" << Vth << "\n" ; octave_stdout << "Cox\t\t" << Cox << "\n" ; octave_stdout << "Cgs\t\t" << Cgs << "\n" ; octave_stdout << "Cgd\t\t" << Cgd << "\n" ; octave_stdout << "Cgb\t\t" << Cgb << "\n" ; octave_stdout << "Csb\t\t" << Csb << "\n" ; octave_stdout << "Cdb\t\t" << Cdb << "\n" ; octave_stdout << "Tshift\t\t" << Tshift << "\n" ; octave_stdout << "\n\n"; } /* Print computed values */ void print_values(double gm, double gd, double ids, double didT, double P, double dPdT, double dPdvgs, double dPdvds) { octave_stdout << "COMPUTED VALUES TABLE: Simplified Shichman-Hodges MOS-FET\n\n"; octave_stdout << "Name\t\tValue\n"; octave_stdout << "gm\t\t" << gm << "\n" ; octave_stdout << "gd\t\t" << gd << "\n" ; octave_stdout << "ids\t\t" << ids << "\n" ; octave_stdout << "didT\t\t" << didT << "\n" ; octave_stdout << "P\t\t" << P << "\n" ; octave_stdout << "dPdT\t\t" << dPdT << "\n" ; octave_stdout << "dPdvgs\t\t" << dPdvgs << "\n" ; octave_stdout << "dPdvds\t\t" << dPdvds << "\n" ; octave_stdout << "\n\n"; } /* Set the parameters of the simplified Shichman-Hodges MOS-FET */ void set_parameters(ColumnVector parameters, string_vector parameternames, double *rd, double* W, double* L, double* mu0, double* Vth, double* Cox, double* Cgs, double* Cgd, double* Cgb, double* Csb, double* Cdb, double* Tshift) { octave_idx_type nnames = parameternames.length(); octave_idx_type niter = 0; //FIXME: it should be better to use Octave_map for parameters while (niter < nnames) { if (parameternames[niter] == "rd") *rd = parameters(niter); else if (parameternames[niter] == "W") *W = parameters(niter); else if (parameternames[niter] == "L") *L = parameters(niter); else if (parameternames[niter] == "mu0") *mu0 = parameters(niter); else if (parameternames[niter] == "Vth") *Vth = parameters(niter); else if (parameternames[niter] == "Cox") *Cox = parameters(niter); else if (parameternames[niter] == "Cgs") *Cgs = parameters(niter); else if (parameternames[niter] == "Cgd") *Cgd = parameters(niter); else if (parameternames[niter] == "Cgb") *Cgb = parameters(niter); else if (parameternames[niter] == "Csb") *Csb = parameters(niter); else if (parameternames[niter] == "Cdb") *Cdb = parameters(niter); else if (parameternames[niter] == "Tshift") *Tshift = parameters(niter); else warning ((string("Mshichmanhodgesmosfet: unknown parameter").append (parameternames[niter])).c_str ()); niter++; } } /* Compute values for n-mos model*/ void nmos(ColumnVector extvar, double mu0, double Cox, double W, double L, double Vth, double rd, double Tshift, double *gm, double *gd, double *ids, double *didT, double *P, double *dPdT, double *dPdvgs, double *dPdvds) { double vg = extvar(0); // V-gate double vs = extvar(1); // V-source double vd = extvar(2); // V-drain double vb = extvar(3); // V-bulk double T = extvar(4); // Temperature double k = mu0*Cox*pow((T + Tshift)/300.0,-3.0/2.0)*W/L; double dkdT = mu0*Cox*W*(-3.0/2)*pow((T + Tshift)/300.0,-5.0/2.0 )*(1.0/300.0)/L; double vgs = vg - vs; double vds = vd - vs; if (vgs < Vth) { *gm = 0; *gd = 1/rd; *ids = vds*(*gd); *didT = 0; } else if ( ( (vgs-Vth)>= vds ) && (vds>=0)) { *ids = k*((vgs-Vth)*vds - pow(vds,2)/2 ) + vds/rd; *gm = k*vds; *gd = k*(vgs-Vth-vds) + (1/rd); *didT = dkdT*((vgs-Vth)*vds-(pow(vds,2))/2); } else if (((vgs-Vth)>=(vds))&&(vds<0)) { *gm = 0; *gd = 1/rd; *ids = vds*(*gd); *didT= 0; } else // (i.e. if 0 <= vgs-vth <= vds) { *ids = (k/2)*pow((vgs-Vth),2) + vds/rd; *gm = k*(vgs-Vth); *gd = 1/rd; *didT= (dkdT/(2))*pow((vgs-Vth),2); } *P = -(*ids)*vds; *dPdT = -(*didT)*vds; *dPdvgs = -(*gm)*vds; *dPdvds = -((*gd)*vds + (*ids)); } /* Compute values for p-mos model*/ void pmos(ColumnVector extvar, double mu0, double Cox, double W, double L, double Vth, double rd, double Tshift, double *gm, double *gd, double *ids, double *didT, double *P, double *dPdT, double *dPdvgs, double *dPdvds) { double vg = extvar(0); // V-gate double vs = extvar(1); // V-source double vd = extvar(2); // V-drain double vb = extvar(3); // V-bulk double T = extvar(4); // Temperature double k = - mu0*Cox*pow((T + Tshift)/300.0,-3.0/2.0)*W/L; double dkdT = - mu0*Cox*W*(-3.0/2.0)*pow((T + Tshift)/300.0,-5.0/2.0 )*(1.0/300.0)/L; double vgs = vg - vs; double vds = vd - vs; if (vgs > Vth) { *gm = 0; *gd = 1/rd; *ids = vds*(*gd); *didT = 0; } else if ( ( (vgs-Vth)<= vds ) && (vds<=0)) { *ids = k*((vgs-Vth)*vds - pow(vds,2)/2 ) + vds/rd; *gm = k*vds; *gd = k*(vgs-Vth-vds) + (1/rd); *didT = dkdT*((vgs-Vth)*vds-(pow(vds,2))/2); } else if (((vgs-Vth)<=(vds))&&(vds>0)) { *gm = 0; *gd = 1/rd; *ids = vds*(*gd); *didT= 0; } else // (i.e. if 0 <= vgs-vth <= vds) { *ids = (k/2)*pow((vgs-Vth),2) + vds/rd; *gm = k*(vgs-Vth); *gd = 1/rd; *didT= (dkdT/(2))*pow((vgs-Vth),2); } *P = -(*ids)*vds; *dPdT = -(*didT)*vds; *dPdvgs = -(*gm)*vds; *dPdvds = -((*gd)*vds + (*ids)); } DEFUN_DLD(Mshichmanhodgesmosfet,args,nargout, "-*- texinfo -*-\n\ \n\ @deftypefn{Function File} @\n\ {[@var{a},@var{b},@var{c}]=} Mshichmanhodgesmosfet@\n\ (@var{string}, @var{parameters}, @var{parameternames}, @\n\ @var{extvar},@var{intvar},@var{t})\n\ \n\ SBN file implementing Schichman-Hodges MOSFETs model.\n\ \n\ @var{string} is used to select among models. Possible models are:\n\ \n\ @enumerate\n\ @item @var{string} = NMOS (Simplified Shichman-Hodges n-MOSFET)\n\ @item @var{string} = PMOS (Simplified Shichman-Hodges p-MOSFET)\n\ @end enumerate\n\ \n\ Parameters for all the above models are:\n\ @itemize\n\ @item rd -> parasitic resistance between drain and source\n\ @item W -> MOSFET width\n\ @item L -> channel length\n\ @item mu0 -> reference value for mobility\n\ @item Vth -> threshold voltage\n\ @item Cox -> oxide capacitance\n\ @item Cgs -> gate-source capacitance\n\ @item Cgd -> gate-drain capacitance\n\ @item Cgb -> gate-bulk capacitance\n\ @item Csb -> source-bulk capacitance\n\ @item Cdb -> drain-bulk capacitance\n\ @item Tshift -> shift for reference temperature on MOSFETs\n\ @end itemize\n\ See the @cite{IFF file format specifications} for details about\n\ the output structures.\n\ \n\ @seealso{prs_iff,asm_initialize_system,asm_build_system}\n\ \n\ @end deftypefn\n \ ") { octave_value_list retval; // Contain returned values octave_idx_type nargin = args.length(); /* Input parameters */ string eltype; ColumnVector parameters; string_vector parameternames; ColumnVector extvar; ColumnVector intvar(5,0.0); double t; /* Model parameters */ double rd; double W,L; double mu0,Vth,Cox; double Cgs,Cgd,Cgb,Csb,Cdb; double Tshift; /* Model variables */ double vg; // V-gate double vs; // V-source double vd; // V-drain double vb; // V-bulk double T ; // Temperature double Qgb;// Charges double Qgs; double Qgd; double Qsb; double Qdb; double gm; // Conductances et similia double gd; double ids; double didT; double P; double dPdT; double dPdvgs; double dPdvds; /* Output values */ Matrix a(10,10,0.0), b(10,10,0.0); ColumnVector c(10,0.0); /* Check and retrieve input */ if (nargin != 6) error("Mshichmanhodgesmosfet: wrong number of input parameters.\n"); else { /* Retrieve input parameters */ // Type of MOS-FET if (args(0).is_string()) eltype = args(0).string_value(); else error("Mshichmanhodgesmosfet: argument #1 is expected to be a string.\n"); // Parameters and parameter names if (args(1).length() == args(2).length()) { parameters = args(1).column_vector_value(); parameternames = args(2).all_strings(); } else error("Mshichmanhodgesmosfet: parameters and parameternames are expected to have the same length.\n"); // External pins if (args(3).length() == 5) extvar = args(3).column_vector_value(); else error("Mshichmanhodgesmosfet: five external values expected.\n"); // Internal variables if (args(4).is_empty()) {} else if (args(4).length() == 5) intvar = args(4).column_vector_value(); else error("Mshichmanhodgesmosfet: five internal values expected.\n"); // Time point if (args(5).is_real_scalar()) t = args(5).double_value(); else error("Mshichmanhodgesmosfet: double type value expected as time instant.\n"); } if (!error_state) { //FIXME: create enum of cases and use switch? if (eltype == "NMOS") { //FIXME: change parameters to a single map or Octave_map /* Default n-MOS parameters*/ rd = 1e6; W = 1; L = 1; mu0 = 1e-5; Vth = .5; Cox = 1e-9; Cgb = Cox; Cgs = .1*Cox; Cgd = .1*Cox; Csb = .1*Cox; Cdb = .1*Cox; Tshift = 0; /* Overwrite parameters */ set_parameters(parameters, parameternames, &rd, &W, &L, &mu0, &Vth, &Cox, &Cgs, &Cgd, &Cgb, &Csb, &Cdb, &Tshift); //FIXME: debug //print_parameters(rd, W, L, mu0, Vth, Cox, Cgs, Cgd, Cgb, Csb, Cdb, Tshift); /* Compute model conductance and capacitance */ nmos(extvar,mu0,Cox,W,L,Vth,rd,Tshift,&gm,&gd,&ids,&didT,&P,&dPdT,&dPdvgs,&dPdvds); //FIXME: debug //print_values(gm, gd, ids, didT, P, dPdT, dPdvgs, dPdvds); /* Assemble output values*/ vg = extvar(0); // V-gate vs = extvar(1); // V-source vd = extvar(2); // V-drain vb = extvar(3); // V-bulk T = extvar(4); // Temperature Qgb = intvar(0); Qgs = intvar(1); Qgd = intvar(2); Qsb = intvar(3); Qdb = intvar(4); //FIXME: probably a better way to initialize Matrix exist! /* Dynamic matrix (constant) */ a(0,5) = 1; a(0,6) = 1; a(0,7) = 1; a(1,6) = -1; a(1,8) = 1; a(2,7) = -1; a(2,9) = 1; a(3,5) = -1; a(3,8) = -1; a(3,9) = -1; /* Algebraic part (non-linear) */ b(1,0) = -gm; b(1,1) = (gm+gd); b(1,2) = -gd; b(1,4) = -didT; b(2,0) = gm; b(2,1) = -(gm+gd); b(2,2) = gd; b(2,4) = didT; b(4,0) = dPdvgs; b(4,1) = -(dPdvgs+dPdvds); b(4,2) = dPdvds; b(4,4) = dPdT; b(5,0) = Cgb; b(5,3) = -Cgb; b(6,0) = Cgs; b(6,1) = -Cgs; b(7,0) = Cgd; b(7,2) = -Cgd; b(8,1) = Csb; b(8,3) = -Csb; b(9,2) = Cdb; b(9,3) = -Cdb; b(5,5) = -1; b(6,6) = -1; b(7,7) = -1; b(8,8) = -1; b(9,9) = -1; /* Residual */ c(0) = 0; c(1) = -ids; c(2) = ids; c(4) = P; c(5) = Cgb*(vg - vb) - Qgb; c(6) = Cgs*(vg - vs) - Qgs; c(7) = Cgd*(vg - vd) - Qgd; c(8) = Csb*(vs - vb) - Qsb; c(9) = Cdb*(vd - vb) - Qdb; /* Return values */ retval(0) = octave_value(a); retval(1) = octave_value(b); retval(2) = octave_value(c); } else if (eltype == "PMOS") { /* Default p-MOS parameters*/ rd = 1e6; W = 1; L = 1; mu0 = 1e-5; Vth = -.5; Cox = 1e-9; Cgb = Cox; Cgs = .1*Cox; Cgd = .1*Cox; Csb = .1*Cox; Cdb = .1*Cox; Tshift = 0; /* Overwrite parameters */ set_parameters(parameters, parameternames, &rd, &W, &L, &mu0, &Vth, &Cox, &Cgs, &Cgd, &Cgb, &Csb, &Cdb, &Tshift); /* Compute model conductance and capacitance */ pmos(extvar,mu0,Cox,W,L,Vth,rd,Tshift,&gm,&gd,&ids,&didT,&P,&dPdT,&dPdvgs,&dPdvds); /* Assemble output values*/ vg = extvar(0); // V-gate vs = extvar(1); // V-source vd = extvar(2); // V-drain vb = extvar(3); // V-bulk T = extvar(4); // Temperature Qgb = intvar(0); Qgs = intvar(1); Qgd = intvar(2); Qsb = intvar(3); Qdb = intvar(4); /* Dynamic matrix (constant) */ a(0,5) = 1; a(0,6) = 1; a(0,7) = 1; a(1,6) = -1; a(1,8) = 1; a(2,7) = -1; a(2,9) = 1; a(3,5) = -1; a(3,8) = -1; a(3,9) = -1; /* Algebraic part (non-linear) */ b(1,0) = -gm; b(1,1) = (gm+gd); b(1,2) = -gd; b(1,4) = -didT; b(2,0) = gm; b(2,1) = -(gm+gd); b(2,2) = gd; b(2,4) = didT; b(4,0) = dPdvgs; b(4,1) = -(dPdvgs+dPdvds); b(4,2) = dPdvds; b(4,4) = dPdT; b(5,0) = Cgb; b(5,3) = -Cgb; b(6,0) = Cgs; b(6,1) = -Cgs; b(7,0) = Cgd; b(7,2) = -Cgd; b(8,1) = Csb; b(8,3) = -Csb; b(9,2) = Cdb; b(9,3) = -Cdb; b(5,5) = -1; b(6,6) = -1; b(7,7) = -1; b(8,8) = -1; b(9,9) = -1; /* Residual */ c(0) = 0; c(1) = -ids; c(2) = ids; c(4) = P; c(5) = Cgb*(vg - vb) - Qgb; c(6) = Cgs*(vg - vs) - Qgs; c(7) = Cgd*(vg - vd) - Qgd; c(8) = Csb*(vs - vb) - Qsb; c(9) = Cdb*(vd - vb) - Qdb; /* Return values */ retval(0) = octave_value(a); retval(1) = octave_value(b); retval(2) = octave_value(c); } else error("Mshichmanhodgesmosfet: unknown element type.\n"); return retval; } }