BSD 3 development
[unix-history] / usr / src / cmd / spice / errchks.f
subroutine errchk
implicit double precision (a-h,o-z)
c
c
c this routine drives the pre-processing and general error-checking
c of input performed by spice.
c
common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
common /miscel/ atime,aprog(3),adate,atitle(10),defl,defw,defad,
1 defas,rstats(50),iwidth,lwidth,nopage
common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
common /cje/ maxtim,itime,icost
common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
2 itemno,nosolv,ipostp,iscrch
common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok,
1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox
common /dc/ tcstar(2),tcstop(2),tcincr(2),icvflg,itcelm(2),kssop,
1 kinel,kidin,kovar,kidout
common /ac/ fstart,fstop,fincr,skw2,refprl,spw2,jacflg,idfreq,
1 inoise,nosprt,nosout,nosin,idist,idprt
common /tran/ tstep,tstop,tstart,delmax,tdmax,forfre,jtrflg
common /outinf/ xincr,string(15),xstart,yvar(8),itab(8),itype(8),
1 ilogy(8),npoint,numout,kntr,numdgt
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c
dimension titlop(4)
dimension nnods(50),aname(2)
data aname / 4htrap, 4hgear /
data titlop / 8hoption s, 8hummary , 8h , 8h /
data ndefin / 2h.u /
data nnods / 2, 2, 2, 0, 2, 2, 2, 2, 2, 2,
1 2, 4, 3, 4, 0, 0, 4, 0, 1, 0,
2 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4 2, 2, 2, 0, 0, 0, 0, 0, 0, 0 /
data aelmt,amodel,aoutpt /7helement,5hmodel,6houtput/
data alsdc,alstr,alsac / 2hdc, 4htran, 2hac /
c
c
call second(t1)
do 60 id=1,50
loc=locate(id)
10 if (loc.eq.0) go to 60
if (nodplc(loc+2).ne.ndefin) go to 50
nogo=1
locv=nodplc(loc+1)
if (id.ge.21) go to 20
anam=aelmt
go to 40
20 if (id.ge.31) go to 30
anam=amodel
go to 40
30 anam=aoutpt
40 write (6,41) anam,value(locv)
41 format('0*error*: ',2a8,' has been referenced but not defined'/)
50 loc=nodplc(loc)
go to 10
60 continue
if (nogo.ne.0) go to 2000
c
c construct ordered list of user specified nodes
c
call getm4(junode,1)
nodplc(junode+1)=0
nunods=1
do 180 id=1,50
if (nnods(id).eq.0) go to 180
loc=locate(id)
110 if (loc.eq.0) go to 180
if (id.le.4) go to 120
if (id.le.8) go to 150
if (id.eq.19) go to 165
if (id.le.40) go to 120
if (id.le.43) go to 170
120 jstop=loc+nnods(id)-1
do 130 j=loc,jstop
call putnod(nodplc(j+2))
130 continue
go to 170
150 call putnod(nodplc(loc+2))
call putnod(nodplc(loc+3))
if (id.ge.7) go to 170
locp=nodplc(loc+id+1)
nssnod=2*nodplc(loc+4)
155 do 160 j=1,nssnod
call putnod(nodplc(locp+j))
160 continue
go to 170
165 locp=nodplc(loc+2)
call sizmem(nodplc(loc+2),nssnod)
go to 155
170 loc=nodplc(loc)
go to 110
180 continue
if (nogo.ne.0) go to 2000
ncnods=nunods
c
c assign program nodes
c
200 do 280 id=1,50
if (nnods(id).eq.0) go to 280
loc=locate(id)
210 if (loc.eq.0) go to 280
if (id.le.4) go to 220
if (id.le.8) go to 250
if (id.eq.19) go to 265
if (id.le.40) go to 220
if (id.le.43) go to 240
220 jstop=loc+nnods(id)-1
do 230 j=loc,jstop
call getnod(nodplc(j+2))
230 continue
go to 270
240 if (nodplc(loc+5).eq.0) go to 220
go to 270
250 call getnod(nodplc(loc+2))
call getnod(nodplc(loc+3))
if (id.ge.7) go to 270
locp=nodplc(loc+id+1)
nssnod=2*nodplc(loc+4)
255 do 260 j=1,nssnod
call getnod(nodplc(locp+j))
260 continue
go to 270
265 locp=nodplc(loc+2)
call sizmem(nodplc(loc+2),nssnod)
go to 255
270 loc=nodplc(loc)
go to 210
280 continue
c
c check and set .nodeset nodes to their internal values
c
call sizmem(nsnod,nic)
if(nic.eq.0) go to 300
do 290 i=1,nic
call getnod(nodplc(nsnod+i))
290 continue
c
c check and set .ic nodes to their internal values
c
300 call sizmem(icnod,nic)
if(nic.eq.0) go to 320
do 310 i=1,nic
call getnod(nodplc(icnod+i))
310 continue
320 if (nogo.ne.0) go to 2000
c
c expand subcircuit calls
c
call subckt
if (nogo.ne.0) go to 2000
if (ncnods.ge.2) go to 400
write (6,321)
321 format('0*error*: circuit has no nodes'/)
nogo=1
go to 2000
400 numnod=ncnods
c
c link unsatisfied references
c
call lnkref
if (nogo.ne.0) go to 2000
c
c generate subcircuit element names
c
if (jelcnt(19).eq.0) go to 530
do 520 id=1,24
loc=locate(id)
510 if (loc.eq.0) go to 520
call subnam(loc)
loc=nodplc(loc)
go to 510
520 continue
c
c translate node initial conditions to device initial conditions
c (capacitance, diode, bjt, and mosfet only
c
530 call sizmem(icnod,nic)
if(nic.eq.0) go to 600
call getm8(lvnim1,numnod)
call zero8(value(lvnim1+1),numnod)
do 535 i=1,nic
node=nodplc(icnod+i)
535 value(lvnim1+node)=value(icval+i)
loc=locate(2)
540 if(loc.eq.0) go to 550
locv=nodplc(loc+1)
if(value(locv+2).ne.0.0d0) go to 545
node1=nodplc(loc+2)
node2=nodplc(loc+3)
value(locv+2)=value(lvnim1+node1)-value(lvnim1+node2)
545 loc=nodplc(loc)
go to 540
550 loc=locate(11)
555 if(loc.eq.0) go to 565
locv=nodplc(loc+1)
if(value(locv+2).ne.0.0d0) go to 560
node1=nodplc(loc+2)
node2=nodplc(loc+3)
value(locv+2)=value(lvnim1+node1)-value(lvnim1+node2)
560 loc=nodplc(loc)
go to 555
565 loc=locate(12)
570 if(loc.eq.0) go to 580
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
node3=nodplc(loc+4)
if(value(locv+2).eq.0.0d0) value(locv+2)=value(lvnim1+node2)-
1 value(lvnim1+node3)
if(value(locv+3).eq.0.0d0) value(locv+3)=value(lvnim1+node1)-
1 value(lvnim1+node3)
loc=nodplc(loc)
go to 570
580 loc=locate(13)
585 if(loc.eq.0) go to 590
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
node3=nodplc(loc+4)
if(value(locv+2).eq.0.0d0) value(locv+2)=value(lvnim1+node1)-
1 value(lvnim1+node3)
if(value(locv+3).eq.0.0d0) value(locv+3)=value(lvnim1+node2)-
1 value(lvnim1+node3)
loc=nodplc(loc)
go to 585
590 loc=locate(14)
595 if(loc.eq.0) go to 598
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
node3=nodplc(loc+4)
node4=nodplc(loc+5)
if(value(locv+5).eq.0.0d0) value(locv+5)=value(lvnim1+node1)-
1 value(lvnim1+node3)
if(value(locv+6).eq.0.0d0) value(locv+6)=value(lvnim1+node2)-
1 value(lvnim1+node3)
if(value(locv+7).eq.0.0d0) value(locv+7)=value(lvnim1+node4)-
1 value(lvnim1+node3)
loc=nodplc(loc)
go to 595
598 call clrmem(lvnim1)
c
c process sources
c
600 if (jtrflg.eq.0) go to 700
do 690 id=9,10
loc=locate(id)
610 if (loc.eq.0) go to 690
locv=nodplc(loc+1)
locp=nodplc(loc+5)
jtype=nodplc(loc+4)+1
go to (680,620,630,640,650,675), jtype
620 value(locp+3)=dmax1(value(locp+3),0.0d0)
if (value(locp+4).le.0.0d0) value(locp+4)=tstep
if (value(locp+5).le.0.0d0) value(locp+5)=tstep
if (value(locp+6).le.0.0d0) value(locp+6)=tstop
if (value(locp+7).le.0.0d0) value(locp+7)=tstop
temp=value(locp+4)+value(locp+5)+value(locp+6)
value(locp+7)=dmax1(value(locp+7),temp)
value(locv+1)=value(locp+1)
go to 680
630 if (value(locp+3).le.0.0d0) value(locp+3)=1.0d0/tstop
value(locp+4)=dmax1(value(locp+4),0.0d0)
value(locv+1)=value(locp+1)
go to 680
640 value(locp+3)=dmax1(value(locp+3),0.0d0)
if (value(locp+4).le.0.0d0) value(locp+4)=tstep
if (value(locp+5).le.value(locp+3))
1 value(locp+5)=value(locp+3)+tstep
if (value(locp+6).le.0.0d0) value(locp+6)=tstep
value(locv+1)=value(locp+1)
go to 680
650 value(locp+1)=dmin1(dmax1(value(locp+1),0.0d0),tstop)
iknt=1
call sizmem(nodplc(loc+5),nump)
660 temp=value(locp+iknt)
if (value(locp+iknt+2).eq.0.0d0) go to 670
if (value(locp+iknt+2).ge.tstop) go to 670
value(locp+iknt+2)=dmax1(value(locp+iknt+2),temp)
if(temp.ne.value(locp+iknt+2)) go to 665
write(6,661) value(locv)
661 format('0*error*: element ',a8,' piecewise linear source table no
1t increasing in time')
nogo=1
665 iknt=iknt+2
if (iknt.lt.nump) go to 660
670 value(locp+iknt+2)=tstop
value(locv+1)=value(locp+2)
call relmem(nodplc(loc+5),nump-iknt-3)
go to 680
675 if (value(locp+3).le.0.0d0) value(locp+3)=1.0d0/tstop
if (value(locp+5).le.0.0d0) value(locp+5)=1.0d0/tstop
value(locv+1)=value(locp+1)
680 loc=nodplc(loc)
go to 610
690 continue
c
c use default values for mos device geometries if not specified
c
700 loc=locate(14)
710 if(loc.eq.0) go to 720
locv=nodplc(loc+1)
if(value(locv+1).le.0.0d0) value(locv+1)=defl
if(value(locv+2).le.0.0d0) value(locv+2)=defw
if(value(locv+3).le.0.0d0) value(locv+3)=defad
if(value(locv+4).le.0.0d0) value(locv+4)=defas
loc=nodplc(loc)
go to 710
c
c print listing of elements, process device models,
c and check topology
c
720 if (iprntl.eq.0) go to 730
call elprnt
730 call topchk
call modchk
if (nogo.ne.0) go to 2000
c
c invert resistance values
c
800 loc=locate(1)
810 if (loc.eq.0) go to 900
locv=nodplc(loc+1)
value(locv+1)=1.0d0/value(locv+2)
loc=nodplc(loc)
go to 810
c
c process mutual inductors
c
900 loc=locate(4)
910 if (loc.eq.0) go to 940
locv=nodplc(loc+1)
nl1=nodplc(loc+2)
call sizmem(nodplc(nl1+10),nparam)
if (nparam.ne.1) go to 920
ispot1=nodplc(nl1+1)
jspot=nodplc(nl1+10)
value(ispot1+1)=value(jspot+1)
if (value(ispot1+1).lt.0.0d0) go to 920
nl2=nodplc(loc+3)
call sizmem(nodplc(nl2+10),nparam)
if (nparam.ne.1) go to 920
ispot2=nodplc(nl2+1)
jspot=nodplc(nl2+10)
value(ispot2+1)=value(jspot+1)
if (value(ispot2+1).lt.0.0d0) go to 920
value(locv+1)=value(locv+1)*dsqrt(value(ispot1+1)*value(ispot2+1))
go to 930
920 write (6,921) value(locv)
921 format('0*error*: inductors coupled by ',a8,' are negative or non
1linear'/)
nogo=1
930 loc=nodplc(loc)
go to 910
940 if (nogo.ne.0) go to 2000
c
c limit delmax to minimum delay over 2 if transmission lines in circuit
c
if (jtrflg.eq.0) go to 1200
tdmax=0.0d0
loc=locate(17)
1010 if (loc.eq.0) go to 1200
locv=nodplc(loc+1)
delmax=dmin1(delmax,value(locv+2)/2.0d0)
tdmax=dmax1(tdmax,value(locv+2))
loc=nodplc(loc)
go to 1010
c
c process source parameters
c
1200 numbkp=0
if (jtrflg.eq.0) go to 1205
tol=1.0d-2*delmax
numbkp=2
call getm8(lsbkpt,numbkp)
value(lsbkpt+1)=0.0d0
value(lsbkpt+2)=tstop
1205 do 1290 id=9,10
loc=locate(id)
1210 if (loc.eq.0) go to 1290
locv=nodplc(loc+1)
locp=nodplc(loc+5)
temp=value(locv+3)/rad
value(locv+3)=value(locv+2)*dsin(temp)
value(locv+2)=value(locv+2)*dcos(temp)
if (jtrflg.eq.0) go to 1280
jtype=nodplc(loc+4)+1
go to (1280,1220,1230,1235,1240,1260), jtype
1220 value(locp+4)=value(locp+4)+value(locp+3)
temp=value(locp+5)
value(locp+5)=value(locp+4)+value(locp+6)
value(locp+6)=value(locp+5)+temp
time=0.0d0
1225 call extmem(lsbkpt,4)
value(lsbkpt+numbkp+1)=value(locp+3)+time
value(lsbkpt+numbkp+2)=value(locp+4)+time
value(lsbkpt+numbkp+3)=value(locp+5)+time
value(lsbkpt+numbkp+4)=value(locp+6)+time
numbkp=numbkp+4
time=time+value(locp+7)
if (time.ge.tstop) go to 1280
go to 1225
1230 value(locp+3)=value(locp+3)*twopi
call extmem(lsbkpt,1)
1231 value(lsbkpt+numbkp+1)=value(locp+4)
numbkp=numbkp+1
go to 1280
1235 call extmem(lsbkpt,2)
value(lsbkpt+numbkp+1)=value(locp+3)
value(lsbkpt+numbkp+2)=value(locp+5)
numbkp=numbkp+2
go to 1280
1240 iknt=1
call sizmem(nodplc(loc+5),nump)
1250 call extmem(lsbkpt,1)
value(lsbkpt+numbkp+1)=value(locp+iknt)
numbkp=numbkp+1
iknt=iknt+2
if (iknt.le.nump) go to 1250
go to 1280
1260 value(locp+3)=value(locp+3)*twopi
value(locp+5)=value(locp+5)*twopi
1280 loc=nodplc(loc)
go to 1210
1290 continue
1300 if (jtrflg.eq.0) go to 1600
call extmem(lsbkpt,1)
value(lsbkpt+numbkp+1)=tstop
numbkp=numbkp+1
call shlsrt(value(lsbkpt+1),numbkp)
nbkpt=1
do 1310 i=2,numbkp
if ((value(lsbkpt+i)-value(lsbkpt+nbkpt)).lt.tol) go to 1310
nbkpt=nbkpt+1
value(lsbkpt+nbkpt)=value(lsbkpt+i)
if (value(lsbkpt+nbkpt).ge.tstop) go to 1320
1310 continue
1320 call relmem(lsbkpt,numbkp-nbkpt)
numbkp=nbkpt
value(lsbkpt+numbkp)=dmax1(value(lsbkpt+numbkp),tstop)
c
c print option summary
c
1600 if (iprnto.eq.0) go to 1700
call title(0,lwidth,1,titlop)
write (6,1601) gmin,reltol,abstol,vntol,lvlcod,itl1,itl2
1601 format('0dc analysis -',/,
1 '0 gmin = ',1pd10.3,/,
2 ' reltol = ', d10.3,/,
3 ' abstol = ', d10.3,/,
4 ' vntol = ', d10.3,/,
5 ' lvlcod = ', i6,/,
6 ' itl1 = ', i6,/,
7 ' itl2 = ', i6,/)
write (6,1611) aname(method),maxord,chgtol,trtol,lvltim,xmu,
1 itl3,itl4,itl5
1611 format('0transient analysis -',/,
1 '0 method = ',a8,/,
2 ' maxord = ', i6,/,
3 ' chgtol = ',1pd10.3,/,
4 ' trtol = ', d10.3,/,
5 ' lvltim = ', i6,/,
6 ' mu = ',0pf10.3,/,
7 ' itl3 = ', i6,/,
8 ' itl4 = ', i6,/,
9 ' itl5 = ', i6,/)
write (6,1621) limpts,limtim,maxtim,numdgt,value(itemps+1),
1 defl,defw,defad,defas
1621 format('0miscellaneous -',/,
1 '0 limpts = ', i6,/,
2 ' limtim = ', i6,/,
3 ' cptime = ', i6,/,
4 ' numdgt = ', i6,/,
5 ' tnom = ',0pf10.3,/,
6 ' defl = ',1pe10.3,/,
7 ' defw = ',e10.3,/,
8 ' defad = ',e10.3,/,
9 ' defas = ',e10.3)
c
c miscellaneous error checking
c
1700 if (icvflg.eq.0) go to 1720
if (icvflg.le.limpts) go to 1710
icvflg=0
write (6,1701) limpts,alsdc
1701 format('0warning: more than ',i5,' points for ',a4,' analysis,',/
11x,'analysis omitted. this limit may be overridden using the ',/
21x,'limpts parameter on the .option card'/)
go to 1720
1710 if ((jelcnt(31)+jelcnt(36)).gt.0) go to 1720
if(ipostp.ne.0) go to 1720
icvflg=0
write (6,1711) alsdc
1711 format('0warning: no ',a4,' outputs specified .',
1 '.. analysis omitted'/)
1720 if (jtrflg.eq.0) go to 1740
if (method.eq.1) maxord=2
if ((method.eq.2).and.(maxord.ge.3)) lvltim=2
if (jtrflg.le.limpts) go to 1730
jtrflg=0
write (6,1701) limpts,alstr
go to 1740
1730 if ((jelcnt(32)+jelcnt(37)+nfour).gt.0) go to 1735
if(ipostp.ne.0) go to 1735
jtrflg=0
write (6,1711) alstr
go to 1740
1735 if (nfour.eq.0) go to 1740
forprd=1.0d0/forfre
if ((tstop-forprd).ge.(tstart-1.0d-12)) go to 1740
nfour=0
call clrmem(ifour)
write (6,1736)
1736 format('0warning: fourier analysis fundamental frequency is incom
1patible with'/11x'transient analysis print interval ... fourier an
2alysis omitted'/)
1740 if (jacflg.eq.0) go to 1800
if (jacflg.le.limpts) go to 1750
jacflg=0
write (6,1701) limpts,alsac
go to 1800
1750 if ((jelcnt(33)+jelcnt(34)+jelcnt(35)+jelcnt(38)+jelcnt(39)
1 +jelcnt(40)+idist+inoise).gt.0) go to 1800
if(ipostp.ne.0) go to 1800
jacflg=0
write (6,1711) alsac
c
c sequence through the output lists
c
1800 do 1820 id=41,45
if (id.le.43) numout=1
loc=locate(id)
1810 if (loc.eq.0) go to 1820
numout=numout+1
nodplc(loc+4)=numout
loc=nodplc(loc)
go to 1810
1820 continue
c
c increase number of .prints if too many outputs for output line-width
c
ifwdth=max0(numdgt-1,0)+9
noprln=min0(8,(lwidth-12)/ifwdth)
do 1860 id=31,35
loc=locate(id)
1830 if(loc.eq.0) go to 1860
noprex=nodplc(loc+3)-noprln
if(noprex.le.0) go to 1850
nodplc(loc+3)=noprln
call find(dfloat(jelcnt(id)),id,locnew,1)
nodplc(locnew+2)=nodplc(loc+2)
nodplc(locnew+3)=noprex
call copy4(nodplc(loc+2*noprln+4),nodplc(locnew+4),2*noprex)
1850 loc=nodplc(loc)
go to 1830
1860 continue
c
c exit
c
2000 call second(t2)
rstats(1)=rstats(1)+t2-t1
return
end
subroutine shlsrt(a,n)
implicit double precision (a-h,o-z)
c
c this routine sorts the array a using a shell sort algorithm.
c
dimension a(n)
integer h
c
c
c... compute best starting step size
h=1
10 h=3*h+1
if (h.lt.n) go to 10
c... back off two times
h=(h-1)/3
h=(h-1)/3
h=max0(h,1)
c
c shell sort
c
20 j=h+1
go to 60
30 i=j-h
c... ak = record key; ar = record
ak=a(j)
ar=ak
40 if (ak.ge.a(i)) go to 50
a(i+h)=a(i)
i=i-h
if (i.ge.1) go to 40
50 a(i+h)=ar
j=j+1
60 if (j.le.n) go to 30
h=(h-1)/3
if (h.ne.0) go to 20
return
end
subroutine putnod(node)
implicit double precision (a-h,o-z)
c
c this routine adds 'node' to the list of user input nodes in table
c junode.
c
common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c
jknt=0
10 jknt=jknt+1
if (jknt.gt.nunods) go to 20
if (node-nodplc(junode+jknt)) 20,100,10
20 k=nunods+1
call extmem(junode,1)
if (k.le.jknt) go to 30
call copy4(nodplc(junode+jknt),nodplc(junode+jknt+1),k-jknt)
k=jknt
30 nodplc(junode+k)=node
nunods=nunods+1
c
c finished
c
100 return
end
subroutine getnod(node)
implicit double precision (a-h,o-z)
c
c this routine converts from the user node number to the internal
c (compact) node number.
c
common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c
if (nogo.ne.0) go to 100
jknt=0
10 jknt=jknt+1
if (jknt.gt.nunods) go to 20
if (nodplc(junode+jknt).ne.node) go to 10
node=jknt
go to 100
c
c unknown node -- must be implied by .print and/or .plot
c
20 if (node.eq.0) go to 30
write (6,21) node
21 format('0warning: attempt to reference undefined node ',i5,
1 ' -- node reset to 0'/)
30 node=1
c
c finished
c
100 return
end
subroutine subckt
implicit double precision (a-h,o-z)
c
c this routine drives the expansion of subcircuit calls.
c
common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c
c... avoid 'call by value' problems, make inodi, inodx arrays
c... in routines which receive them as parameters !!!
locx=locate(19)
10 if (locx.eq.0) go to 300
locs=nodplc(locx+3)
asnam=value(iunsat+locs)
call fndnam(asnam,locx-1,locx+3,20)
if (nogo.ne.0) go to 300
locs=nodplc(locx+3)
c
c check for recursion
c
isbptr=nodplc(locx-1)
20 if (isbptr.eq.0) go to 30
if (locs.eq.nodplc(isbptr+3)) go to 260
isbptr=nodplc(isbptr-1)
go to 20
c
c
30 call sizmem(nodplc(locx+2),nxnod)
call sizmem(nodplc(locs+2),nssnod)
if (nxnod.ne.nssnod) go to 250
call getm4(inodx,nssnod)
call getm4(inodi,nssnod)
itemp=nodplc(locs+2)
call copy4(nodplc(itemp+1),nodplc(inodx+1),nssnod)
itemp=nodplc(locx+2)
call copy4(nodplc(itemp+1),nodplc(inodi+1),nxnod)
c
c add elements of subcircuit to nominal circuit
c
loc=nodplc(locs+3)
100 if (loc.eq.0) go to 200
id=nodplc(loc-1)
if (id.eq.20) go to 110
call find(dfloat(jelcnt(id)),id,loce,1)
nodplc(loce-1)=locx
call addelt(loce,loc,id,inodx,inodi,nxnod)
110 loc=nodplc(loc)
go to 100
c
c
200 call clrmem(inodx)
call clrmem(inodi)
locx=nodplc(locx)
go to 10
c
c errors
c
250 locv=nodplc(locx+1)
axnam=value(locv)
locv=nodplc(locs+1)
asnam=value(locv)
write (6,251) axnam,asnam
251 format('0*error*: ',a8,' has different number of nodes than ',a8/
1)
nogo=1
go to 300
260 locsv=nodplc(locs+1)
asnam=value(locsv)
write (6,261) asnam
261 format('0*error*: subcircuit ',a8,' is defined recursively'/)
nogo=1
c
c finished
c
300 return
end
subroutine fndnam(anam,jsbptr,ispot,id)
implicit double precision (a-h,o-z)
c
c this routine searches for an element with id 'id' by tracing back
c up the subcircuit definition list. if the element is not found, the
c nominal element list is searched.
c
common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
integer xxor
c
c
isbptr=nodplc(jsbptr)
10 if (isbptr.eq.0) go to 50
isub=nodplc(isbptr+3)
loc=nodplc(isub+3)
20 if (loc.eq.0) go to 40
if (id.ne.nodplc(loc-1)) go to 30
locv=nodplc(loc+1)
if (xxor(anam,value(locv)).ne.0) go to 30
if (id.ne.20) go to 50
go to 65
30 loc=nodplc(loc)
go to 20
40 isbptr=nodplc(isbptr-1)
go to 10
c
50 loc=locate(id)
60 if (loc.eq.0) go to 90
if (nodplc(loc-1).ne.isbptr) go to 70
locv=nodplc(loc+1)
if (xxor(anam,value(locv)).ne.0) go to 70
65 nodplc(ispot)=loc
go to 100
70 loc=nodplc(loc)
go to 60
90 write (6,91) anam
91 format('0*error*: unable to find ',a8/)
nogo=1
100 return
end
subroutine newnod(nodold,nodnew,inodx,inodi,nnodi)
implicit double precision (a-h,o-z)
c
c this routine makes a new node number for an element which is about
c to be added to the circuit as a result of a subcircuit call.
c
common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c... inodx, inodi are arrays (see subckt)
dimension inodx(1),inodi(1)
c
if (nodold.ne.0) go to 5
nodnew=1
go to 20
5 do 10 i=1,nnodi
jnodx=inodx(1)
if (nodold.ne.nodplc(jnodx+i)) go to 10
jnodi=inodi(1)
nodnew=nodplc(jnodi+i)
go to 20
10 continue
c
call extmem(inodx(1),1)
call extmem(inodi(1),1)
call extmem(junode,1)
nnodi=nnodi+1
ncnods=ncnods+1
jnodx=inodx(1)
nodplc(jnodx+nnodi)=nodold
jnodi=inodi(1)
nodplc(jnodi+nnodi)=ncnods
nodplc(junode+ncnods)=nodplc(junode+ncnods-1)+1
nodnew=ncnods
20 return
end
subroutine addelt(loce,loc,id,inodx,inodi,nnodi)
implicit double precision (a-h,o-z)
c
c this routine adds an element to the nominal circuit definition
c lists.
c
common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c... inodx(1), inodi(1) are arrays (see subckt)
dimension inodx(1),inodi(1)
c
dimension lnod(50),lval(50),nnods(50)
data lnod / 9,13,15, 7,14,15,14,15,12, 7,
1 17,37,26,34, 7, 7,34, 0, 5, 5,
2 4, 4, 4, 4, 0, 0, 0, 0, 0, 0,
3 21,21,21,21,21,21,21,21,21,21,
4 8, 8, 8, 8, 8, 0, 0, 0, 0, 0 /
data lval / 5, 4, 4, 2, 1, 1, 1, 1, 4, 4,
1 3, 4, 4,13, 1, 1, 9, 0, 1, 1,
2 19,55,17,41, 0, 0, 0, 0, 0, 0,
3 1, 1, 1, 1, 1,17,17,17,17,17,
4 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 /
data nnods / 2, 2, 2, 0, 2, 2, 2, 2, 2, 2,
1 2, 4, 3, 4, 4, 4, 4, 0, 1, 0,
2 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4 2, 2, 2, 0, 0, 0, 0, 0, 0, 0 /
c
c copy integer part
c
nword=lnod(id)-3
if (nword.le.0) go to 10
call copy4(nodplc(loc+2),nodplc(loce+2),nword)
c
c set nodes
c
10 if (id.ge.21) go to 100
if (nnods(id).eq.0) go to 100
if (id.le.4) go to 20
if (id.le.8) go to 40
if (id.eq.19) go to 70
20 jstop=nnods(id)
do 30 j=1,jstop
call newnod(nodplc(loc+j+1),nodplc(loce+j+1),inodx(1),
1 inodi(1),nnodi)
30 continue
go to 100
40 call newnod(nodplc(loc+2),nodplc(loce+2),inodx(1),inodi(1),nnodi)
call newnod(nodplc(loc+3),nodplc(loce+3),inodx(1),inodi(1),nnodi)
if (id.ge.7) go to 100
nlocp=loc+id+1
nssnod=2*nodplc(loc+4)
call getm4(nodplc(loce+id+1),nssnod)
nlocpe=loce+id+1
50 do 60 j=1,nssnod
locp=nodplc(nlocp)
nodold=nodplc(locp+j)
call newnod(nodold,nodnew,inodx(1),inodi(1),nnodi)
locpe=nodplc(nlocpe)
nodplc(locpe+j)=nodnew
60 continue
go to 100
70 nlocp=loc+2
call sizmem(nodplc(loc+2),nssnod)
call getm4(nodplc(loce+2),nssnod)
nlocpe=loce+2
go to 50
c
c copy real part
c
100 if (nogo.ne.0) go to 300
locv=nodplc(loc+1)
locve=nodplc(loce+1)
call copy8(value(locv),value(locve),lval(id))
c
c treat non-node tables specially
c
200 if (id.ge.11) go to 300
go to (300,210,220,300,230,240,230,240,260,260), id
210 call cpytb8(loc+7,loce+7)
go to 300
220 call cpytb8(loc+10,loce+10)
go to 300
230 itab=5
go to 250
240 itab=6
250 if (id.le.6) go to 255
call cpytb4(loc+itab+1,loce+itab+1)
255 call cpytb4(loc+itab+2,loce+itab+2)
call cpytb8(loc+itab+3,loce+itab+3)
call cpytb8(loc+itab+4,loce+itab+4)
call cpytb4(loc+itab+5,loce+itab+5)
call cpytb8(loc+itab+6,loce+itab+6)
go to 300
260 call cpytb8(loc+5,loce+5)
c
c
300 return
end
subroutine cpytb4(itabo,itabn)
implicit double precision (a-h,o-z)
c
c this routine copies a table. its use is made necessary by the
c fact that only one pointer is allowed per table.
c
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c
call sizmem(nodplc(itabo),isize)
call getm4(nodplc(itabn),isize)
loco=nodplc(itabo)
locn=nodplc(itabn)
call copy4(nodplc(loco+1),nodplc(locn+1),isize)
return
end
subroutine cpytb8(itabo,itabn)
implicit double precision (a-h,o-z)
c
c this routine copies a table. its use is made necessary by the
c fact that only one pointer is allowed per table.
c
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c
call sizmem(nodplc(itabo),isize)
call getm8(nodplc(itabn),isize)
loco=nodplc(itabo)
locn=nodplc(itabn)
call copy8(value(loco+1),value(locn+1),isize)
return
end
subroutine lnkref
implicit double precision (a-h,o-z)
c
c this routine resolves all unsatisfied name references.
c
common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c mutual inductors
c
loc=locate(4)
100 if (loc.eq.0) go to 200
iref=nodplc(loc+2)
call fndnam(value(iunsat+iref),loc-1,loc+2,3)
iref=nodplc(loc+3)
call fndnam(value(iunsat+iref),loc-1,loc+3,3)
loc=nodplc(loc)
go to 100
c
c current-controlled current source
c
200 loc=locate(7)
210 if (loc.eq.0) go to 300
nump=nodplc(loc+4)
locp=nodplc(loc+6)
do 220 i=1,nump
iref=nodplc(locp+i)
call fndnam(value(iunsat+iref),loc-1,locp+i,9)
220 continue
loc=nodplc(loc)
go to 210
c
c current-controlled voltage sources
c
300 loc=locate(8)
310 if (loc.eq.0) go to 400
nump=nodplc(loc+4)
locp=nodplc(loc+7)
do 320 i=1,nump
iref=nodplc(locp+i)
call fndnam(value(iunsat+iref),loc-1,locp+i,9)
320 continue
loc=nodplc(loc)
go to 310
c
c diodes
c
400 loc=locate(11)
410 if (loc.eq.0) go to 500
iref=nodplc(loc+5)
call fndnam(value(iunsat+iref),loc-1,loc+5,21)
loc=nodplc(loc)
go to 410
c
c bjts
c
500 loc=locate(12)
510 if (loc.eq.0) go to 600
iref=nodplc(loc+8)
call fndnam(value(iunsat+iref),loc-1,loc+8,22)
loc=nodplc(loc)
go to 510
c
c jfets
c
600 loc=locate(13)
610 if (loc.eq.0) go to 700
iref=nodplc(loc+7)
call fndnam(value(iunsat+iref),loc-1,loc+7,23)
loc=nodplc(loc)
go to 610
c
c mosfets
c
700 loc=locate(14)
710 if (loc.eq.0) go to 1000
iref=nodplc(loc+8)
call fndnam(value(iunsat+iref),loc-1,loc+8,24)
loc=nodplc(loc)
go to 710
c
c finished
c
1000 call clrmem(iunsat)
return
end
subroutine subnam(loce)
implicit double precision (a-h,o-z)
c
c this routine constructs the names of elements added as a result of
c subcircuit expansion. the full element names are of the form
c name.xn. --- xd.xc.xb.xa
c where 'name' is the nominal element name, and the 'x'*s denote the
c sequence of subcircuit calls (from top or circuit level down through
c nested subcircuit calls) which caused the particular element to be
c added. at present, spice restricts all element names to be 8 charac-
c ters or less. therefore, the name used consists of the leftmost 8
c characters of the full element name, with the rightmost character
c replaced by an asterisk ('*') if the full element name is longer than
c 8 characters.
c
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c
data ablank, aper, astk / 1h , 1h., 1h* /
c
c construct subcircuit element name
c
if (nodplc(loce-1).eq.0) go to 100
locve=nodplc(loce+1)
loc=loce
nchar=0
sname=ablank
achar=ablank
10 locv=nodplc(loc+1)
elname=value(locv)
do 20 ichar=1,8
call move(achar,1,elname,ichar,1)
if (achar.eq.ablank) go to 30
if (nchar.eq.8) go to 40
nchar=nchar+1
call move(sname,nchar,achar,1,1)
20 continue
30 loc=nodplc(loc-1)
if (loc.eq.0) go to 60
if (nchar.eq.8) go to 40
nchar=nchar+1
call move(sname,nchar,aper,1,1)
go to 10
c
c name is longer than 8 characters: flag with asterisk
c
40 call move(sname,8,astk,1,1)
60 value(locve)=sname
c
c finished
c
100 return
end
subroutine elprnt
implicit double precision (a-h,o-z)
c
c this routine prints a circuit element summary.
c
common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
common /miscel/ atime,aprog(3),adate,atitle(10),defl,defw,defad,
1 defas,rstats(50),iwidth,lwidth,nopage
common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
common /tran/ tstep,tstop,tstart,delmax,tdmax,forfre,jtrflg
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c
dimension itab(25),astyp(6)
dimension eltitl(4)
data eltitl / 8hcircuit , 8helement , 8hsummary , 8h /
data astyp / 1h , 5hpulse, 3hsin, 3hexp, 3hpwl, 4hsffm /
data ablnk,aoff /1h ,3hoff/
c
c print listing of elements
c
call title(0,lwidth,1,eltitl)
c
c print resistors
c
if (jelcnt(1).eq.0) go to 50
ititle=0
21 format(//'0**** resistors'/'0 name nodes value
1 tc1 tc2'//)
loc=locate(1)
30 if (loc.eq.0) go to 50
if (ititle.eq.0) write (6,21)
ititle=1
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
write (6,31) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),value(locv+2),value(locv+3),value(locv+4)
31 format(6x,a8,2i5,1p3d11.2)
40 loc=nodplc(loc)
go to 30
c
c print capacitors and inductors
c
50 if ((jelcnt(2)+jelcnt(3)).eq.0) go to 80
ititle=0
51 format(//'0**** capacitors and inductors'/'0 name nodes
1 in cond value'//)
do 70 id=2,3
loc=locate(id)
60 if (loc.eq.0) go to 70
if (ititle.eq.0) write (6,51)
ititle=1
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
ltab=7
if (id.eq.3) ltab=10
call sizmem(nodplc(loc+ltab),nparam)
if (nparam.ge.2) go to 62
ispot=nodplc(loc+ltab)+1
write (6,31) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),value(locv+2),value(ispot)
go to 65
62 write (6,63) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),value(locv+2)
63 format(6x,a8,2i5,1pd11.2,' variable')
65 loc=nodplc(loc)
go to 60
70 continue
c
c print mutual inductors
c
80 if (jelcnt(4).eq.0) go to 100
ititle=0
81 format(//'0**** mutual inductors'/'0 name coupled induc
1tors value'//)
loc=locate(4)
90 if (loc.eq.0) go to 110
if (ititle.eq.0) write (6,81)
ititle=1
locv=nodplc(loc+1)
nl1=nodplc(loc+2)
nl1=nodplc(nl1+1)
nl2=nodplc(loc+3)
nl2=nodplc(nl2+1)
write (6,91) value(locv),value(nl1),value(nl2),value(locv+1)
91 format(6x,a8,4x,a8,2x,a8,1pd10.2)
95 loc=nodplc(loc)
go to 90
c
c print nonlinear voltage controlled sources
c
100 if (jelcnt(5).eq.0) go to 120
ititle=0
101 format(//'0**** voltage-controlled current sources'/'0 name
1 + - dimension function')
loc=locate(5)
110 if (loc.eq.0) go to 120
if (ititle.eq.0) write (6,101)
ititle=1
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
write (6,111) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),nodplc(loc+4)
111 format(6x,a8,2i5,i8,9x,'poly')
115 loc=nodplc(loc)
go to 110
c
c nonlinear voltage controlled voltage sources
c
120 if (jelcnt(6).eq.0) go to 140
ititle=0
121 format(//'0**** voltage-controlled voltage sources'/'0 name
1 + - dimension function')
loc=locate(6)
130 if (loc.eq.0) go to 140
if (ititle.eq.0) write (6,121)
ititle=1
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
write (6,111) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),nodplc(loc+4)
135 loc=nodplc(loc)
go to 130
c
c nonlinear current controlled current sources
c
140 if (jelcnt(7).eq.0) go to 160
ititle=0
141 format(//'0**** current-controlled current sources'/'0 name
1 + - dimension function')
loc=locate(7)
150 if (loc.eq.0) go to 160
if (ititle.eq.0) write (6,141)
ititle=1
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
write (6,111) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),nodplc(loc+4)
155 loc=nodplc(loc)
go to 150
c
c nonlinear current controlled voltage sources
c
160 if (jelcnt(8).eq.0) go to 170
ititle=0
161 format(//'0**** current-controlled voltage sources'/'0 name
1 + - dimension function')
loc=locate(8)
165 if (loc.eq.0) go to 170
if (ititle.eq.0) write (6,161)
ititle=1
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
write (6,111) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),nodplc(loc+4)
167 loc=nodplc(loc)
go to 165
c
c print independent sources
c
170 if ((jelcnt(9)+jelcnt(10)).eq.0) go to 250
ititle=0
171 format(//'0**** independent sources'/'0 name nodes dc
1 value ac value ac phase transient'//)
do 245 id=9,10
loc=locate(id)
180 if (loc.eq.0) go to 245
if (ititle.eq.0) write (6,171)
ititle=1
locv=nodplc(loc+1)
locp=nodplc(loc+5)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
itype=nodplc(loc+4)+1
anam=astyp(itype)
write (6,181) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),value(locv+1),value(locv+2),
2 value(locv+3),anam
181 format(6x,a8,2i5,1p3d11.2,2x,a8)
if (jtrflg.eq.0) go to 240
jstart=locp+1
go to (240,190,200,210,220,230), itype
190 jstop=locp+7
write (6,191) (value(j),j=jstart,jstop)
191 format(1h0,42x,'initial value',1pd11.2,/,
1 43x,'pulsed value.', d11.2,/,
2 43x,'delay time...', d11.2,/,
3 43x,'risetime.....', d11.2,/,
4 43x,'falltime.....', d11.2,/,
5 43x,'width........', d11.2,/,
6 43x,'period.......', d11.2,/)
go to 240
200 jstop=locp+5
write (6,201) (value(j),j=jstart,jstop)
201 format(1h0,42x,'offset.......',1pd11.2,/,
1 43x,'amplitude....', d11.2,/,
2 43x,'frequency....', d11.2,/,
3 43x,'delay........', d11.2,/,
4 43x,'theta........', d11.2,/)
go to 240
210 jstop=locp+6
write (6,211) (value(j),j=jstart,jstop)
211 format(1h0,42x,'initial value',1pd11.2,/,
1 43x,'pulsed value.', d11.2,/,
2 43x,'rise delay...', d11.2,/,
3 43x,'rise tau.....', d11.2,/,
4 43x,'fall delay...', d11.2,/,
5 43x,'fall tau.....', d11.2,/)
go to 240
220 call sizmem(nodplc(loc+5),jstop)
jstop=locp+jstop
write (6,221) (value(j),j=jstart,jstop)
221 format(1h0,49x,'time value'//,(46x,1p2d11.2))
write (6,226)
226 format(1x)
go to 240
230 jstop=locp+5
write (6,231) (value(j),j=jstart,jstop)
231 format(1h0,42x,'offset.......',1pd11.2,/,
1 43x,'amplitude....', d11.2,/,
2 43x,'carrier freq.', d11.2,/,
3 43x,'modn index...', d11.2,/,
4 43x,'signal freq..', d11.2,/)
240 loc=nodplc(loc)
go to 180
245 continue
c
c print transmission lines
c
250 if (jelcnt(17).eq.0) go to 260
ititle=0
251 format(//'0**** transmission lines'/'0 name nodes
1 z0 td'//)
loc=locate(17)
253 if (loc.eq.0) go to 260
if (ititle.eq.0) write (6,251)
ititle=1
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
node3=nodplc(loc+4)
node4=nodplc(loc+5)
write (6,256) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),nodplc(junode+node3),
2 nodplc(junode+node4),value(locv+1),value(locv+2)
256 format(6x,a8,4i5,1p2d11.2)
258 loc=nodplc(loc)
go to 253
c
c print diodes
c
260 if (jelcnt(11).eq.0) go to 290
ititle=0
261 format(//'0**** diodes'/'0 name + - model are
1a'//)
loc=locate(11)
270 if (loc.eq.0) go to 290
if (ititle.eq.0) write (6,261)
ititle=1
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
locm=nodplc(loc+5)
locm=nodplc(locm+1)
aic=ablnk
if (nodplc(loc+6).eq.1) aic=aoff
write (6,271) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),value(locm),value(locv+1),aic
271 format(6x,a8,2i5,2x,a8,f8.3,2x,a8)
280 loc=nodplc(loc)
go to 270
c
c print transistors
c
290 if (jelcnt(12).eq.0) go to 320
ititle=0
291 format(//'0**** bipolar junction transistors'/'0 name c
1 b e s model area'//)
loc=locate(12)
300 if (loc.eq.0) go to 320
if (ititle.eq.0) write (6,291)
ititle=1
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
node3=nodplc(loc+4)
node4=nodplc(loc+5)
locm=nodplc(loc+8)
locm=nodplc(locm+1)
aic=ablnk
if (nodplc(loc+9).eq.1) aic=aoff
write (6,301) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),nodplc(junode+node3),nodplc(junode+node4),
2 value(locm),value(locv+1),aic
301 format(6x,a8,4i5,2x,a8,f8.3,2x,a8)
310 loc=nodplc(loc)
go to 300
c
c print jfets
c
320 if (jelcnt(13).eq.0) go to 350
ititle=0
321 format(//'0**** jfets'/'0 name d g s model
1 area'//)
loc=locate(13)
330 if (loc.eq.0) go to 350
if (ititle.eq.0) write (6,321)
ititle=1
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
node3=nodplc(loc+4)
locm=nodplc(loc+7)
locm=nodplc(locm+1)
aic=ablnk
if (nodplc(loc+8).eq.1) aic=aoff
write (6,331) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),nodplc(junode+node3),
2 value(locm),value(locv+1),aic
331 format(6x,a8,3i5,2x,a8,f8.3,2x,a8)
340 loc=nodplc(loc)
go to 330
c
c print mosfets
c
350 if (jelcnt(14).eq.0) go to 400
ititle=0
351 format(//'0**** mosfets',/,'0name d g s b model l
1 w ad as rd rs',//)
loc=locate(14)
360 if (loc.eq.0) go to 400
if (ititle.eq.0) write (6,351)
ititle=1
locv=nodplc(loc+1)
node1=nodplc(loc+2)
node2=nodplc(loc+3)
node3=nodplc(loc+4)
node4=nodplc(loc+5)
locm=nodplc(loc+8)
locm=nodplc(locm+1)
rd=value(locv+11)
if(rd.eq.0.0d0) rd=value(locm+6)
rs=value(locv+12)
if(rs.eq.0.0d0) rs=value(locm+7)
aic=ablnk
if (nodplc(loc+9).eq.1) aic=aoff
write (6,361) value(locv),nodplc(junode+node1),
1 nodplc(junode+node2),nodplc(junode+node3),
2 nodplc(junode+node4),value(locm),value(locv+1),value(locv+2),
3 value(locv+3),value(locv+4),rd,rs
361 format(1x,a8,4i4,1x,a8,1pd7.1,5d8.1)
if(aic.ne.ablnk) write(6,362)
362 format(1x,'above device specified to be *off* to aid dc solution',
1 /)
370 loc=nodplc(loc)
go to 360
c
c subcircuit calls
c
400 if (jelcnt(19).eq.0) go to 500
ititle=0
401 format(//'0**** subcircuit calls'/'0 name subcircuit ext
1ernal nodes'//)
loc=locate(19)
410 if (loc.eq.0) go to 500
if (ititle.eq.0) write (6,401)
ititle=1
locv=nodplc(loc+1)
locn=nodplc(loc+2)
call sizmem(nodplc(loc+2),nnodx)
locs=nodplc(loc+3)
locsv=nodplc(locs+1)
jstart=1
ndprln=(lwidth-28)/5
412 jstop=min0(nnodx,jstart+ndprln-1)
do 414 j=jstart,jstop
node=nodplc(locn+j)
itab(j-jstart+1)=nodplc(junode+node)
414 continue
if (jstart.eq.1)
1 write (6,416) value(locv),value(locsv),(itab(j),j=1,jstop)
416 format(6x,a8,2x,a8,4x,20i5)
if (jstart.ne.1)
1 write (6,418) (itab(j-jstart+1),j=jstart,jstop)
418 format(28x,20i5)
jstart=jstop+1
if (jstart.le.nnodx) go to 412
if (nnodx.le.ndprln) go to 420
write (6,226)
420 loc=nodplc(loc)
go to 410
c
c finished
c
500 return
end
subroutine modchk
implicit double precision (a-h,o-z)
c
c this routine performs one-time processing of device model para-
c meters and prints out a device model summary. it also reserves the
c additional nodes required by nonzero device extrinsic resistances.
c
common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
common /miscel/ atime,aprog(3),adate,atitle(10),defl,defw,defad,
1 defas,rstats(50),iwidth,lwidth,nopage
common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
2 itemno,nosolv,ipostp,iscrch
common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok,
1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c
dimension itab(50),atable(10)
dimension ifun(4)
dimension antype(4),aptype(4)
dimension ipar(6),ampar(120),defval(120),ifmt(120)
dimension titled(4),titleb(4),titlej(4),titlem(4)
data titled / 8hdiode mo, 8hdel para, 8hmeters , 8h /
data titleb / 8hbjt mode, 8hl parame, 8hters , 8h /
data titlej / 8hjfet mod, 8hel param, 8heters , 8h /
data titlem / 8hmosfet m, 8hodel par, 8hameters , 8h /
data ifun / 0, 0, 1, 1 /
data antype /1h ,3hnpn,3hnjf,4hnmos/
data aptype /1h ,3hpnp,3hpjf,4hpmos/
data agaas /5hga-as/
data ipar / 0, 14, 60, 72, 106, 119 /
data hndrd,hndrd2 /1.0d+02,1.0d+04/
data ampar /
1 6his ,6hrs ,6hn ,6htt ,6hcjo ,6hpb ,6hm ,
2 6heg ,6hpt ,6hkf ,6haf ,6hfc ,6hbv ,6hibv ,
1 6hjs ,6hbf ,6hnf ,6hvbf ,6hjbf ,6hjle ,6hnle ,
2 6hbr ,6hnr ,6hvbr ,6hjbr ,6hjlc ,6hnlc ,6h0 ,
3 6h0 ,6hrb ,6hjrb ,6hrbm ,6hre ,6hrc ,6hcje ,
4 6hvje ,6hmje ,6htf ,6hxtf ,6hvtf ,6hjtf ,6hptf ,
5 6hcjc ,6hvjc ,6hmjc ,6hcdis ,6htr ,6h0 ,6h0 ,
6 6h0 ,6h0 ,6hcjs ,6hvjs ,6hmjs ,6htb ,6heg ,
7 6hpt ,6hkf ,6haf ,6hfc ,
1 6hvto ,6hbeta ,6hlambda,6hrd ,6hrs ,6hcgs ,6hcgd ,
2 6hpb ,6his ,6hkf ,6haf ,6hfc ,
1 6hvto ,6hkp ,6hgamma ,6hphi ,6hlambda,6hrd ,6hrs ,
2 6hcgs ,6hcgd ,6hcgb ,6hcbd ,6hcbs ,6htox ,6hpb ,
3 6hjs ,6hnsub ,6hnss ,6hnfs ,6hxj ,6hld ,6hngate ,
4 6htps ,6huo ,6hucrit ,6huexp ,6hutra ,6hkf ,6haf ,
5 6hfc ,6hwd ,6hecrit ,6hetra ,6hvnorm ,6hdesat ,
1 6hvp ,6hvbr ,6hvbi ,6hvfwd ,6hnd ,6hkdso ,6hkdv ,
2 6hcdso ,6hczg ,6hgnoise,6hnexp ,6hkf ,6haf ,0.0d0 /
data defval /
1 1.0d-14, 0.0d0, 1.0d0, 2*0.0d0, 1.0d0, 0.5d0, 1.11d0,
2 3.0d0, 0.0d0, 1.0d0, 0.5d0, 0.0d0, 1.0d-3,
1 1.0d-16, 100.0d0, 1.0d0, 3*0.0d0, 1.5d0, 2*1.0d0, 3*0.0d0,
2 2.0d0, 0.0d0, 1.0d0, 0.0d0, 0.0d0, 4*0.0d0, 0.75d0,
3 0.33d0, 2*0.0d0, 2*0.0d0, 2*0.0d0, 0.75d0, 0.33d0, 1.0d0,
4 2*0.0d0, 2*0.0d0, 2*0.0d0, 0.75d0, 0.0d0, 0.0d0, 1.11d0,
5 3.0d0, 0.0d0, 1.0d0, 0.5d0,
1 -2.0d0, 1.0d-4, 5*0.0d0, 1.0d0,1.0d-14, 0.0d0, 1.0d0,
2 0.5d0,
1 3*0.0d0, 0.0d0, 8*0.0d0, 1.0d-7, 0.8d0, 1.0d-4,6*0.0d0,
2 1.0d0,700.0d0, 1.0d+4, 3*0.0d0, 1.0d0, 0.5d0, 0.0d0,
3 3*0.0d0,1.5d+9,
1 -2.1d0, 0.0d0, 0.8d0, 0.6d0, 1.0d17, 5.8d0 ,0.01d0,
2 2.0d-10, 0.0d0, 0.0d0, 1.0d0, 0.0d0, 1.0d0, 0.0d0 /
data ifmt /
1 2,1,1,2,2,1,1,1,1,2,1,1,2,2,
1 2,1,1,2,2,2,1,1,1,2,2,2,1,0,0,1,2,1,1,1,2,1,1,2,2,2,2,1,2,1,
a 1,1,2,0,0,0,0,2,1,1,2,1,1,2,2,2,
3 1,2,1,1,1,2,2,1,2,2,1,1,
4 1,2,1,1,2,1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,1,2,1,1,2,1,1,2,
a 2,2,2,2,
5 1,1,1,1,2,2,2,2,2,2,1,2,1,0/
c
c
tnom=value(itemps+1)+ctok
xkt=boltz*tnom
vt=xkt/charge
egfet=1.16d0-(7.02d-04*tnom**2/(tnom+1108.0d0))
arg=-egfet/2.0d0/boltz/tnom+1.1151d0/boltz/2.0d0/(27.0d0+ctok)
xni=1.45d10*(tnom/(27.0d0+ctok))**1.5d0*dexp(charge*arg)
nummod=jelcnt(21)+jelcnt(22)+jelcnt(23)+jelcnt(24)
if (nummod.eq.0) go to 1000
c
c assign default values
c
kntlim=lwidth/11
do 390 id=1,4
if (jelcnt(id+20).eq.0) go to 390
iflag=ifun(id)
loc=locate(id+20)
10 if (loc.eq.0) go to 20
locv=nodplc(loc+1)
id1=id
c... special case of gaas
if(id.eq.4.and.nodplc(loc+2).eq.0) id1=5
locm=ipar(id1)
nopar=ipar(id1+1)-locm
do 18 i=1,nopar
itab(i)=ifmt(locm+i)
if (value(locv+i).eq.0.0d0) go to 16
if (iflag.eq.0) go to 14
if (i.eq.1) go to 18
if(i.eq.2.and.id1.eq.5) go to 18
14 if (value(locv+i).gt.0.0d0) go to 18
c.. let pt be negative for bjts (for now anyway!)
if(i.eq.43.and.id.eq.2) go to 18
c... nss, ld, wd, utra and tps for mosfet can be negative
if((i.eq.22.or.i.eq.17.or.i.eq.20.or.i.eq.30.or.i.eq.26)
1 .and.id.eq.4) go to 18
c... vbr for ga-as fets must be negative
16 value(locv+i)=defval(locm+i)
18 continue
loc=nodplc(loc)
go to 10
c
c limit model values
c
20 go to (30,40,50,60), id
c... diodes
30 loc=locate(21)
32 if (loc.eq.0) go to 100
locv=nodplc(loc+1)
value(locv+7)=dmin1(value(locv+7),0.9d0)
value(locv+8)=dmax1(value(locv+8),0.1d0)
value(locv+11)=dmax1(value(locv+11),0.1d0)
value(locv+12)=dmin1(value(locv+12),0.95d0)
loc=nodplc(loc)
go to 32
c... bipolar transistors
40 loc=locate(22)
42 if (loc.eq.0) go to 100
locv=nodplc(loc+1)
value(locv+23)=dmin1(value(locv+23),0.9d0)
if(value(locv+24).eq.0.0d0) value(locv+28)=0.0d0
value(locv+31)=dmin1(value(locv+31),0.9d0)
value(locv+32)=dmin1(value(locv+32),1.0d0)
value(locv+40)=dmin1(value(locv+40),0.9d0)
value(locv+42)=dmax1(value(locv+42),0.1d0)
value(locv+45)=dmax1(value(locv+45),0.1d0)
value(locv+46)=dmin1(value(locv+46),0.9999d0)
loc=nodplc(loc)
if(value(locv+18).eq.0.0d0) value(locv+18)=value(locv+16)
if(value(locv+16).ge.value(locv+18)) go to 42
write(6,44) value(locv)
44 format('0warning: minimum base resistance (rbm) is less than '
1 ,'total (rb) for model ',a8,/10x' rbm set equal to rb',/)
value(locv+18)=value(locv+16)
go to 42
c... jfets
50 loc=locate(23)
52 if (loc.eq.0) go to 100
locv=nodplc(loc+1)
value(locv+11)=dmax1(value(locv+11),0.1d0)
value(locv+12)=dmin1(value(locv+12),0.95d0)
loc=nodplc(loc)
go to 52
c... mosfets
60 loc=locate(24)
64 if (loc.eq.0) go to 100
locv=nodplc(loc+1)
if(nodplc(loc+2).eq.0) go to 70
c
c special preprocessing for mosfet models
c
type=nodplc(loc+2)
cox=epsox/value(locv+13)/hndrd
c... if kp not given, calculate it from cox and uo
if(value(locv+2).eq.0.0d0)
1 value(locv+2)=value(locv+23)*cox
value(locv+35)=0.0d0
c... nsub nonzero => calculate gamma, vto, phi unless specified
if (value(locv+16).le.0.0d0) go to 68
xnsub=value(locv+16)
if (xnsub.le.xni) go to 66
if (value(locv+4).le.0.0d0) value(locv+4)=2.0d0*vt*dlog(xnsub/xni)
if (value(locv+3).le.0.0d0)
1 value(locv+3)=dsqrt(2.0d0*epssil*charge*xnsub)/cox
fermis=type*0.5d0*value(locv+4)
wkfng=3.2d0
c... polysilicon gate ... calculate appropriate work function
if (value(locv+21).le.0.0d0) go to 65
fermig=type*value(locv+22)*vt*dlog(value(locv+21)/xni)
wkfng=3.25d0+0.5d0*egfet-fermig
65 wkfngs=wkfng-(3.25d0+0.5d0*egfet+fermis)
if(value(locv+1).eq.0.0d0)
1 value(locv+1)= wkfngs-value(locv+17)*charge/cox+
2 type*(value(locv+4)+value(locv+3)*dsqrt(value(locv+4)))
value(locv+35)=dsqrt((epssil+epssil)/(charge*xnsub))
go to 68
66 value(locv+16)=0.0d0
write (6,67) value(locv)
67 format('0*error*: nsub < ni in mosfet model ',a8,/)
nogo=1
c... set phi to default if still zero
68 if(value(locv+4).eq.0.0d0) value(locv+4)=0.6d0
value(locv+4)=dmax1(value(locv+4),0.1d0)
value(locv+28)=dmax1(value(locv+28),0.1d0)
value(locv+29)=dmin1(value(locv+29),0.95d0)
loc=nodplc(loc)
go to 64
c... ga-as fets
70 value(locv+1)=-dabs(value(locv+1))
if(value(locv+2).ne.0.0d0) value(locv+2)=-dabs(value(locv+2))
value(locv+2)=dmax1(value(locv+2),-200.0d0)
if(value(locv+9).eq.0.0d0)
1 value(locv+9)=2.49d-12*dsqrt(value(locv+5)/value(locv+3))
loc=nodplc(loc)
go to 64
c
c print model parameters
c
100 if (iprntm.eq.0) go to 390
locs=locate(id+20)
110 kntr=0
loc=locs
go to (120,130,140,150),id
120 call title(0,lwidth,1,titled)
go to 200
130 call title(0,lwidth,1,titleb)
go to 200
140 call title(0,lwidth,1,titlej)
go to 200
150 call title(0,lwidth,1,titlem)
200 if (loc.eq.0) go to 210
if (kntr.lt.kntlim) go to 220
210 locn=loc
go to 240
220 kntr=kntr+1
locv=nodplc(loc+1)
atable(kntr)=value(locv)
230 loc=nodplc(loc)
go to 200
240 write (6,241) (atable(k),k=1,kntr)
241 format(//11x,12(2x,a8))
if (id.eq.1) go to 300
kntr=0
loc=locs
250 if (loc.eq.0) go to 260
if (kntr.ge.kntlim) go to 260
kntr=kntr+1
atable(kntr)=antype(id)
if (nodplc(loc+2).eq.-1) atable(kntr)=aptype(id)
c... special type for ga-as (do not mix ga-as and mos!)
if(id.eq.4.and.nodplc(loc+2).eq.0) atable(kntr)=agaas
loc=nodplc(loc)
go to 250
260 write (6,261) (atable(k),k=1,kntr)
261 format('0type',4x,12(4x,a6))
300 do 340 i=1,nopar
if (itab(i).eq.0) go to 340
kntr=0
loc=locs
310 if (loc.eq.0) go to 320
if (kntr.ge.kntlim) go to 320
locv=nodplc(loc+1)
kntr=kntr+1
atable(kntr)=value(locv+i)
loc=nodplc(loc)
go to 310
320 if (itab(i).eq.2) go to 330
write (6,321) ampar(locm+i),(atable(k),k=1,kntr)
321 format(1h ,a8,12f10.3)
go to 340
330 write (6,331) ampar(locm+i),(atable(k),k=1,kntr)
331 format(1h ,a8,1p12d10.2)
340 continue
if (locn.eq.0) go to 390
locs=locn
go to 110
390 continue
c
c process model parameters
c
c diodes
c
400 loc=locate(21)
410 if (loc.eq.0) go to 420
locv=nodplc(loc+1)
if (value(locv+2).ne.0.0d0) value(locv+2)=1.0d0/value(locv+2)
pb=value(locv+6)
xm=value(locv+7)
fc=value(locv+12)
value(locv+12)=fc*pb
xfc=dlog(1.0d0-fc)
value(locv+15)=pb*(1.0d0-dexp((1.0d0-xm)*xfc))/(1.0d0-xm)
value(locv+16)=dexp((1.0d0+xm)*xfc)
value(locv+17)=1.0d0-fc*(1.0d0+xm)
csat=value(locv+1)
vte=value(locv+3)*vt
value(locv+18)=vte*dlog(vte/(root2*csat))
bv=value(locv+13)
if(bv.eq.0.0d0) go to 418
cbv=value(locv+14)
if(cbv.ge.csat*bv/vt) go to 412
cbv=csat*bv/vt
write(6,411) value(locv),cbv
411 format('0warning: in diode model ',a8,' ibv increased to ',
1 1pd10.3,/10x,'to resolve incompatibility with specified is',/)
xbv=bv
go to 416
412 tol=reltol*cbv
xbv=bv-vt*dlog(1.0d0+cbv/csat)
iter=0
413 xbv=bv-vt*dlog(cbv/csat+1.0d0-xbv/vt)
xcbv=csat*(dexp((bv-xbv)/vt)-1.0d0+xbv/vt)
if (dabs(xcbv-cbv).le.tol) go to 416
iter=iter+1
if (iter.lt.25) go to 413
write (6,415) xbv,xcbv
415 format('0warning: unable to match forward and reverse diode regio
1ns',/,11x,'bv = ',1pd10.3,' and ibv = ',d10.3,/)
416 value(locv+13)=xbv
418 loc=nodplc(loc)
go to 410
c
c bipolar transistor models
c
420 loc=locate(22)
430 if (loc.eq.0) go to 440
locv=nodplc(loc+1)
if(value(locv+4).ne.0.0d0) value(locv+4)=1.0d0/value(locv+4)
if(value(locv+5).ne.0.0d0) value(locv+5)=1.0d0/value(locv+5)
if(value(locv+10).ne.0.0d0) value(locv+10)=1.0d0/value(locv+10)
if(value(locv+11).ne.0.0d0) value(locv+11)=1.0d0/value(locv+11)
if(value(locv+19).ne.0.0d0) value(locv+19)=1.0d0/value(locv+19)
if(value(locv+20).ne.0.0d0) value(locv+20)=1.0d0/value(locv+20)
if(value(locv+26).ne.0.0d0) value(locv+26)=1.0d0/value(locv+26)
1 /1.44d0
value(locv+28)=value(locv+28)/rad*value(locv+24)
if(value(locv+35).ne.0.0d0) value(locv+35)=1.0d0/value(locv+35)
1 /1.44d0
pe=value(locv+22)
xme=value(locv+23)
pc=value(locv+30)
xmc=value(locv+31)
fc=value(locv+46)
value(locv+46)=fc*pe
xfc=dlog(1.0d0-fc)
value(locv+47)=pe*(1.0d0-dexp((1.0d0-xme)*xfc))/(1.0d0-xme)
value(locv+48)=dexp((1.0d0+xme)*xfc)
value(locv+49)=1.0d0-fc*(1.0d0+xme)
value(locv+50)=fc*pc
value(locv+51)=pc*(1.0d0-dexp((1.0d0-xmc)*xfc))/(1.0d0-xmc)
value(locv+52)=dexp((1.0d0+xmc)*xfc)
value(locv+53)=1.0d0-fc*(1.0d0+xmc)
csat=value(locv+1)
value(locv+54)=vt*dlog(vt/(root2*csat))
loc=nodplc(loc)
go to 430
c
c jfet models
c
440 loc=locate(23)
450 if (loc.eq.0) go to 460
locv=nodplc(loc+1)
if (value(locv+4).ne.0.0d0) value(locv+4)=1.0d0/value(locv+4)
if (value(locv+5).ne.0.0d0) value(locv+5)=1.0d0/value(locv+5)
pb=value(locv+8)
xm=0.5d0
fc=value(locv+12)
value(locv+12)=fc*pb
xfc=dlog(1.0d0-fc)
value(locv+13)=pb*(1.0d0-dexp((1.0d0-xm)*xfc))/(1.0d0-xm)
value(locv+14)=dexp((1.0d0+xm)*xfc)
value(locv+15)=1.0d0-fc*(1.0d0+xm)
csat=value(locv+9)
value(locv+16)=vt*dlog(vt/(root2*csat))
loc=nodplc(loc)
go to 450
c
c mosfet models
c
460 loc=locate(24)
470 if (loc.eq.0) go to 600
locv=nodplc(loc+1)
if(nodplc(loc+2).eq.0) go to 490
type=nodplc(loc+2)
c... check validiy of lambda
if(value(locv+5).lt.5.0d-6) go to 472
write(6,471) value(locv)
471 format('0warning: value for lambda unrealisticly large for model'
1 ,1x,a8,/'0this parameter has been re-defined. see latest users '
2 ,'guide.')
472 value(locv+5)=value(locv+5)*hndrd
value(locv+8)=value(locv+8)/hndrd
value(locv+9)=value(locv+9)/hndrd
value(locv+10)=value(locv+10)/hndrd
value(locv+11)=value(locv+11)/hndrd2
value(locv+12)=value(locv+12)/hndrd2
value(locv+13)=value(locv+13)*hndrd
value(locv+15)=value(locv+15)/hndrd2
value(locv+19)=value(locv+19)*hndrd
value(locv+20)=value(locv+20)*hndrd
c.. move the params wd-gleff out to positions 36-40
value(locv+36)=value(locv+30)*hndrd
value(locv+37)=value(locv+31)
value(locv+38)=value(locv+32)
value(locv+39)=value(locv+33)
value(locv+40)=value(locv+34)
if(value(locv+39).ne.0.0d0) value(locv+39)=1.0d0/value(locv+39)
if (value(locv+6).ne.0.0d0) value(locv+6)=1.0d0/value(locv+6)
if (value(locv+7).ne.0.0d0) value(locv+7)=1.0d0/value(locv+7)
if (value(locv+13).ne.0.0d0) value(locv+13)=epsox/value(locv+13)
value(locv+34)=value(locv+1)-
1 type*value(locv+3)*dsqrt(value(locv+4))
if (value(locv+13).ne.0.0d0)
1 value(locv+24)=value(locv+24)*epssil/value(locv+13)
pb=value(locv+14)
c... enter here from ga-as processing also
475 xm=0.5d0
fc=value(locv+29)
value(locv+29)=fc*pb
xfc=dlog(1.0d0-fc)
value(locv+30)=pb*(1.0d0-dexp((1.0d0-xm)*xfc))/(1.0d0-xm)
value(locv+31)=dexp((1.0d0+xm)*xfc)
value(locv+32)=1.0d0-fc*(1.0d0+xm)
value(locv+33)=-1.0d0
480 loc=nodplc(loc)
go to 470
c... ga-as processing
490 value(locv+24)=2.5d+05*dexp(value(locv+2)/1.3d0)
value(locv+25)=5.0d+06*dexp(-value(locv+4)/vt)
value(locv+26)=3.9d-12*dsqrt(value(locv+5)*(value(locv+3)-
1 value(locv+1)))
value(locv+28)=value(locv+26)*(1.0d0-dsqrt((value(locv+3)-
1 0.99999d0*value(locv+1))/(value(locv+3)-value(locv+1))))
value(locv+29)=0.5d0
pb=value(locv+3)
go to 475
c
c reserve additional nodes
c convert mosfet geometries to cm
c
c diodes
c
600 loc=locate(11)
610 if (loc.eq.0) go to 700
locm=nodplc(loc+5)
locm=nodplc(locm+1)
if (value(locm+2).eq.0.0d0) go to 620
numnod=numnod+1
nodplc(loc+4)=numnod
go to 630
620 nodplc(loc+4)=nodplc(loc+2)
630 loc=nodplc(loc)
go to 610
c
c transistors
c
700 loc=locate(12)
710 if (loc.eq.0) go to 800
c
c put substrate node into nodplc(loc+30)
c
nodplc(loc+30)=nodplc(loc+5)
locm=nodplc(loc+8)
locm=nodplc(locm+1)
if(value(locm+16).eq.0.0d0) go to 720
numnod=numnod+1
nodplc(loc+6)=numnod
go to 730
720 nodplc(loc+6)=nodplc(loc+3)
730 if (value(locm+20).eq.0.0d0) go to 740
numnod=numnod+1
nodplc(loc+5)=numnod
go to 750
740 nodplc(loc+5)=nodplc(loc+2)
750 if (value(locm+19).eq.0.0d0) go to 760
numnod=numnod+1
nodplc(loc+7)=numnod
go to 770
760 nodplc(loc+7)=nodplc(loc+4)
770 loc=nodplc(loc)
go to 710
c
c jfets
c
800 loc=locate(13)
810 if (loc.eq.0) go to 900
locm=nodplc(loc+7)
locm=nodplc(locm+1)
if (value(locm+4).eq.0.0d0) go to 820
numnod=numnod+1
nodplc(loc+5)=numnod
go to 830
820 nodplc(loc+5)=nodplc(loc+2)
830 if (value(locm+5).eq.0.0d0) go to 840
numnod=numnod+1
nodplc(loc+6)=numnod
go to 850
840 nodplc(loc+6)=nodplc(loc+4)
850 loc=nodplc(loc)
go to 810
c
c mosfets
c
900 loc=locate(14)
910 if (loc.eq.0) go to 1000
locm=nodplc(loc+8)
locv=nodplc(loc+1)
if(nodplc(locm+2).eq.0) go to 960
locm=nodplc(locm+1)
value(locv+1)=value(locv+1)*hndrd
value(locv+2)=value(locv+2)*hndrd
value(locv+3)=value(locv+3)*hndrd2
value(locv+4)=value(locv+4)*hndrd2
c... check that effective channel length is greater than zero
if((value(locv+1)-2.0d0*value(locm+20)).gt.0.0d0)
1 go to 914
write(6,913) value(locv),value(locm)
913 format('0*error*: effective channel length of ',a8,' less than ',
1 'zero.',/' check value of ld for model ',a8)
nogo=1
914 if((value(locv+2)-2.0d0*value(locm+36)).gt.0.0d0) go to 916
write(6,915) value(locv),value(locm)
915 format('0*error*: effective channel width of ',a8,' less than ',
1 'zero.',/' check value of wd for model ',a8)
nogo=1
916 if (value(locv+11).eq.0.0d0) go to 917
value(locv+11)=1.0d0/value(locv+11)
go to 918
917 if(value(locm+6).eq.0.0d0) go to 920
value(locv+11)=value(locm+6)
918 numnod=numnod+1
nodplc(loc+6)=numnod
go to 930
920 nodplc(loc+6)=nodplc(loc+2)
930 if (value(locv+12).eq.0.0d0) go to 931
value(locv+12)=1.0d0/value(locv+12)
go to 932
931 if(value(locm+7).eq.0.0d0) go to 940
value(locv+12)=value(locm+7)
932 numnod=numnod+1
nodplc(loc+7)=numnod
go to 950
940 nodplc(loc+7)=nodplc(loc+4)
950 loc=nodplc(loc)
go to 910
c.. special case for ga-as devices
c.. compute rd and rs if not specified on device card
c.. rd and rs are always non-zero.
960 locm=nodplc(locm+1)
req=1.25d+14/(value(locm+5)*value(locv+2))
if (value(locv+11).eq.0.0d0) value(locv+11)=req
value(locv+11)=1.0d0/value(locv+11)
numnod=numnod+1
nodplc(loc+6)=numnod
if (value(locv+12).eq.0.0d0) value(locv+12)=req
value(locv+12)=1.0d0/value(locv+12)
numnod=numnod+1
nodplc(loc+7)=numnod
loc=nodplc(loc)
go to 910
c
c transmission lines
c
1000 loc=locate(17)
1010 if (loc.eq.0) go to 2000
numnod=numnod+1
nodplc(loc+6)=numnod
numnod=numnod+1
nodplc(loc+7)=numnod
loc=nodplc(loc)
go to 1010
c
c finished
c
2000 return
end
subroutine topchk
implicit double precision (a-h,o-z)
c
c this routine constructs the element node table. it also checks
c for voltage source/inductor loops, current source/capacitor cutsets,
c and that every node has a dc (conductive) path to ground.
c
common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
common /miscel/ atime,aprog(3),adate,atitle(10),defl,defw,defad,
1 defas,rstats(50),iwidth,lwidth,nopage
common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
common /blank/ value(1000)
integer nodplc(64)
complex*16 cvalue(32)
equivalence (value(1),nodplc(1),cvalue(1))
c
c
dimension atable(12),aide(20),nnods(20)
dimension idlist(4)
dimension toptit(4)
data toptit / 8helement , 8hnode tab, 8hle , 8h /
data idlist / 3, 6, 8, 9 /
data aide / 1hr,0.0d0,1hl,2*0.0d0,1he,0.0d0,1hh,1hv,0.0d0,1hd,
1 1hq,1hj,1hm,0.0d0,0.0d0,1ht,0.0d0,0.0d0,0.0d0 /
data nnods / 2,2,2,0,2,2,2,2,2,2,2,4,3,4,4,4,4,0,1,0 /
data ablnk /1h /
c
c allocate storage
c
call getm4(iorder,ncnods)
call getm4(iur,ncnods+1)
c
c construct node table
c
kntlim=lwidth/11
1300 call getm4(itable,0)
call getm4(itabid,0)
istop=ncnods+1
do 1310 i=1,istop
1310 nodplc(iur+i)=1
do 1370 id=1,19
if (nnods(id).eq.0) go to 1370
loc=locate(id)
1320 if (loc.eq.0) go to 1370
nloc=loc+1
jstop=nnods(id)
if (id.ne.19) go to 1330
nloc=nodplc(loc+2)
call sizmem(nodplc(loc+2),jstop)
1330 do 1360 j=1,jstop
node=nodplc(nloc+j)
ispot=nodplc(iur+node+1)
k=nodplc(iur+ncnods+1)
call extmem(itable,1)
call extmem(itabid,1)
if (k.le.ispot) go to 1340
call copy4(nodplc(itable+ispot),nodplc(itable+ispot+1),k-ispot)
call copy4(nodplc(itabid+ispot),nodplc(itabid+ispot+1),k-ispot)
1340 nodplc(itable+ispot)=loc
nodplc(itabid+ispot)=id
c... treat the substrate node of a mosfet as if it were a transmission
c... line node, i.e. let it dangle if desired
if(id.eq.14.and.j.eq.4) nodplc(itabid+ispot)=17
k=node
kstop=ncnods+1
1350 k=k+1
if (k.gt.kstop) go to 1360
nodplc(iur+k)=nodplc(iur+k)+1
go to 1350
1360 continue
loc=nodplc(loc)
go to 1320
1370 continue
c
c check that every node has a dc path to ground
c
call zero4(nodplc(iorder+1),ncnods)
nodplc(iorder+1)=1
1420 iflag=0
do 1470 i=2,ncnods
if (nodplc(iorder+i).eq.1) go to 1470
jstart=nodplc(iur+i)
jstop=nodplc(iur+i+1)-1
if (jstart.gt.jstop) go to 1470
do 1450 j=jstart,jstop
loc=nodplc(itable+j)
id=nodplc(itabid+j)
if (aide(id).eq.0.0d0) go to 1450
if (id.eq.17) go to 1445
kstop=loc+nnods(id)-1
do 1440 k=loc,kstop
node=nodplc(k+2)
if (nodplc(iorder+node).eq.1) go to 1460
1440 continue
go to 1450
1445 if (nodplc(loc+2).eq.i) node=nodplc(loc+3)
if (nodplc(loc+3).eq.i) node=nodplc(loc+2)
if (nodplc(loc+4).eq.i) node=nodplc(loc+5)
if (nodplc(loc+5).eq.i) node=nodplc(loc+4)
if (nodplc(iorder+node).eq.1) go to 1460
1450 continue
go to 1470
1460 nodplc(iorder+i)=1
iflag=1
1470 continue
if (iflag.eq.1) go to 1420
c
c print node table and topology error messages
c
if (iprntn.eq.0) go to 1510
call title(0,lwidth,1,toptit)
1510 do 1590 i=1,ncnods
jstart=nodplc(iur+i)
jstop=nodplc(iur+i+1)-1
if (iprntn.eq.0) go to 1550
if (jstart.le.jstop) go to 1520
write (6,1511) nodplc(junode+i)
1511 format(1h0,i7)
go to 1550
1520 kntr=0
jflag=1
do 1540 j=jstart,jstop
loc=nodplc(itable+j)
locv=nodplc(loc+1)
kntr=kntr+1
atable(kntr)=value(locv)
if (kntr.lt.kntlim) go to 1540
if (jflag.eq.0) go to 1525
jflag=0
write (6,1521) nodplc(junode+i),(atable(k),k=1,kntr)
1521 format(1h0,i7,3x,12(1x,a8))
go to 1530
1525 write (6,1526) (atable(k),k=1,kntr)
1526 format(11x,12(1x,a8))
1530 kntr=0
1540 continue
if (kntr.eq.0) go to 1550
if (jflag.eq.0) go to 1545
write (6,1521) nodplc(junode+i),(atable(k),k=1,kntr)
go to 1550
1545 write (6,1526) (atable(k),k=1,kntr)
1550 if (jstart-jstop) 1560,1552,1556
c
c allow node with only one connection iff element is a t-line
c
1552 if (nodplc(itabid+jstart).eq.17) go to 1560
1556 nogo=1
write (6,1557) nodplc(junode+i)
1557 format('0*error*: less than 2 connections at node ',i6/)
go to 1590
1560 if (nodplc(iorder+i).eq.1) go to 1590
nogo=1
write (6,1561) nodplc(junode+i)
1561 format('0*error*: no dc path to ground from node ',i6/)
1590 continue
c
c check for inductor/voltage source loops
c
do 1700 i=1,ncnods
call zero4(nodplc(iorder+1),ncnods)
nodplc(iorder+i)=-1
do 1690 idcntr=1,4
id=idlist(idcntr)
loc=locate(id)
1610 if (loc.eq.0) go to 1690
node1=nodplc(loc+2)
node2=nodplc(loc+3)
if (nodplc(iorder+node1)) 1620,1640,1630
1620 nodplc(iorder+node1)=loc
1630 node=node2
go to 1670
1640 if (nodplc(iorder+node2)) 1650,1680,1660
1650 nodplc(iorder+node2)=loc
1660 node=node1
1670 if (nodplc(iorder+node).ne.0) go to 1710
nodplc(iorder+node)=loc
1680 loc=nodplc(loc)
go to 1610
1690 continue
1700 continue
go to 1900
c ... loop found
1710 locv=nodplc(loc+1)
write (6,1711) value(locv)
1711 format('0*error*: inductor/voltage source loop found, containing
1',a8/)
nogo=1
c
c
1900 call clrmem(iorder)
call clrmem(iur)
call clrmem(itable)
call clrmem(itabid)
2000 return
end