| 1 | program spice |
| 2 | implicit double precision (a-h,o-z) |
| 3 | c |
| 4 | c |
| 5 | c |
| 6 | c *** version VAX UNIX 2X.x (19aug79) |
| 7 | c developed from |
| 8 | c *** version 2d.2 (26sep76) *** |
| 9 | c *** version hp 2.0 (6dec77) *** |
| 10 | c |
| 11 | c by dick dowell - hewlett packard company |
| 12 | c richard newton - uc berkeley |
| 13 | c |
| 14 | c spice is an electronic circuit simulation program that was deve- |
| 15 | c loped by the integrated circuits group of the electronics research |
| 16 | c laboratory and the department of electrical engineering and computer |
| 17 | c sciences at the university of california, berkeley, california. the |
| 18 | c program spice is available free of charge to any interested party. |
| 19 | c the sale, resale, or use of this program for profit without the |
| 20 | c express written consent of the department of electrical engineering |
| 21 | c and computer sciences, university of california, berkeley, california, |
| 22 | c is forbidden. |
| 23 | c |
| 24 | c |
| 25 | c implementation notes: |
| 26 | c |
| 27 | c subroutines mclock and mdate return the time (as hh:mm:ss) and |
| 28 | c the date (as dd mmm yy), respectively. subroutine getcje returns in |
| 29 | c common block /cje/ various attributes of the current job environment. |
| 30 | c spice expects getcje to set /cje/ variables maxtim, itime, and icost. |
| 31 | c maxtim is the maximum cpu time in seconds, itime is the elapsed cpu |
| 32 | c time in seconds, and icost is the job cost in cents. |
| 33 | c subroutine memory is used to change the number of memory words |
| 34 | c allocated to spice. if the amount of memory allocated to a jobstep |
| 35 | c is fixed, subroutine memory need not be changed. |
| 36 | c ifamwa (set in a data statement below) should be set to the |
| 37 | c address of the first available word of memory (following overlays, if |
| 38 | c any). the proper value should be easily obtainable from any load map. |
| 39 | c with the exception of most flags, all data in spice is stored in |
| 40 | c the form of managed tables allocated in the /blank/ array value(). |
| 41 | c spice is particularly well-suited to being run using a one-level |
| 42 | c overlay structure beginning with routines spice (the overlay root), |
| 43 | c readin, errchk, setup, dctran, dcop, acan, and ovtpvt. the order of |
| 44 | c the routines in this listing corresponds to that structure. note |
| 45 | c that if cdc-style overlay is to be used, an overlay directive card |
| 46 | c must be inserted before the first line of each of the just-named |
| 47 | c routines. |
| 48 | c |
| 49 | c |
| 50 | common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem, |
| 51 | 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize, |
| 52 | 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr, |
| 53 | 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1, |
| 54 | 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd, |
| 55 | 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval |
| 56 | common /miscel/ atime,aprog(3),adate,atitle(10),defl,defw,defad, |
| 57 | 1 defas,rstats(50),iwidth,lwidth,nopage |
| 58 | common /line/ achar,afield(15),oldlin(15),kntrc,kntlim |
| 59 | common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop, |
| 60 | 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs |
| 61 | common /mosarg/ gamma,beta,vto,phi,cox,vbi,xnfs,xnsub,xd,xj,xl, |
| 62 | 1 xlamda,utra,uexp,vbp,von,vdsat,theta,vcrit,vtra,gleff,cdrain |
| 63 | common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet, |
| 64 | 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno, |
| 65 | 2 itemno,nosolv,ipostp,iscrch |
| 66 | common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts, |
| 67 | 1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof |
| 68 | common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok, |
| 69 | 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox |
| 70 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 71 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 72 | 2 nwd8,nwd16 |
| 73 | common /dc/ tcstar(2),tcstop(2),tcincr(2),icvflg,itcelm(2),kssop, |
| 74 | 1 kinel,kidin,kovar,kidout |
| 75 | common /ac/ fstart,fstop,fincr,skw2,refprl,spw2,jacflg,idfreq, |
| 76 | 1 inoise,nosprt,nosout,nosin,idist,idprt |
| 77 | common /tran/ tstep,tstop,tstart,delmax,tdmax,forfre,jtrflg |
| 78 | common /outinf/ xincr,string(15),xstart,yvar(8),itab(8),itype(8), |
| 79 | 1 ilogy(8),npoint,numout,kntr,numdgt |
| 80 | common /cje/ maxtim,itime,icost |
| 81 | c.. common for putwds |
| 82 | common /blank/ value(50000) |
| 83 | integer nodplc(64) |
| 84 | complex*16 cvalue(32) |
| 85 | equivalence (value(1),nodplc(1),cvalue(1)) |
| 86 | integer*2 istats(200) |
| 87 | real*4 r4stat(100) |
| 88 | equivalence (rstats(1),istats(1),r4stat(1)) |
| 89 | integer*2 inknt |
| 90 | c |
| 91 | dimension acctit(4) |
| 92 | dimension remain(4) |
| 93 | data amrje /4hmrje/ |
| 94 | data ablnk /1h / |
| 95 | data acctit / 8hjob stat, 8histics s, 8hummary , 8h / |
| 96 | data ahdr1, ahdr2, ahdr3 / 8h spice 2,8h.Xx (vax,8h11/780) / |
| 97 | c |
| 98 | c |
| 99 | ipostp=0 |
| 100 | maxtim=1e8 |
| 101 | maxlin=50000 |
| 102 | icost=0 |
| 103 | ilines=0 |
| 104 | c |
| 105 | c initialization |
| 106 | c |
| 107 | aprog(1)=ahdr1 |
| 108 | aprog(2)=ahdr2 |
| 109 | aprog(3)=ahdr3 |
| 110 | achar=ablnk |
| 111 | keof=0 |
| 112 | call mclock(atime) |
| 113 | call mdate(adate) |
| 114 | boltz=1.3806226d-23 |
| 115 | charge=1.6021918d-19 |
| 116 | ctok=273.15d0 |
| 117 | eps0=8.854214871d-14 |
| 118 | epssil=11.7d0*eps0 |
| 119 | epsox=3.9d0*eps0 |
| 120 | twopi=8.0d0*datan2(1.0d0,1.0d0) |
| 121 | rad=360.0d0/twopi |
| 122 | xlog2=dlog(2.0d0) |
| 123 | xlog10=dlog(10.0d0) |
| 124 | root2=dsqrt(2.0d0) |
| 125 | nodata=1 |
| 126 | c |
| 127 | c begin job |
| 128 | c |
| 129 | 10 if (keof.eq.1) go to 1000 |
| 130 | call getcje |
| 131 | call second(time1) |
| 132 | icost1=icost |
| 133 | igoof=0 |
| 134 | mode=0 |
| 135 | nogo=0 |
| 136 | maxmem=100000 |
| 137 | call setmem(nodplc(1),maxmem) |
| 138 | if (nogo.ne.0) go to 1000 |
| 139 | call zero8(rstats,50) |
| 140 | c |
| 141 | c read remainder of data deck and check for input errors |
| 142 | c |
| 143 | call readin |
| 144 | if (nogo.ne.0) go to 300 |
| 145 | if (keof.eq.1) go to 1000 |
| 146 | nodata=0 |
| 147 | call errchk |
| 148 | if (nogo.ne.0) go to 300 |
| 149 | call setup |
| 150 | if (nogo.ne.0) go to 300 |
| 151 | c |
| 152 | c cycle through temperatures |
| 153 | c |
| 154 | itemno=1 |
| 155 | if (numtem.eq.1) go to 110 |
| 156 | 100 if (itemno.eq.numtem) go to 320 |
| 157 | itemno=itemno+1 |
| 158 | call tmpupd |
| 159 | c |
| 160 | c dc transfer curves |
| 161 | c |
| 162 | 110 if (icvflg.eq.0) go to 150 |
| 163 | c... see routine *dctran* for explanation of *mode*, etc. |
| 164 | mode=1 |
| 165 | modedc=3 |
| 166 | call dctran |
| 167 | call ovtpvt |
| 168 | if (nogo.ne.0) go to 300 |
| 169 | c |
| 170 | c small signal operating point |
| 171 | c |
| 172 | 150 if (kssop.gt.0) go to 170 |
| 173 | if (jacflg.ne.0) go to 170 |
| 174 | if ((icvflg+jtrflg).gt.0) go to 250 |
| 175 | 170 mode=1 |
| 176 | modedc=1 |
| 177 | call dctran |
| 178 | if (nogo.ne.0) go to 300 |
| 179 | call dcop |
| 180 | if (nogo.ne.0) go to 300 |
| 181 | c |
| 182 | c ac small signal analysis |
| 183 | c |
| 184 | 200 if (jacflg.eq.0) go to 250 |
| 185 | mode=3 |
| 186 | call acan |
| 187 | call ovtpvt |
| 188 | if (nogo.ne.0) go to 300 |
| 189 | c |
| 190 | c transient analysis |
| 191 | c |
| 192 | 250 if (jtrflg.eq.0) go to 100 |
| 193 | mode=1 |
| 194 | modedc=2 |
| 195 | call dctran |
| 196 | if (nogo.ne.0) go to 300 |
| 197 | call dcop |
| 198 | if (nogo.ne.0) go to 300 |
| 199 | mode=2 |
| 200 | call dctran |
| 201 | call ovtpvt |
| 202 | if (nogo.ne.0) go to 300 |
| 203 | go to 100 |
| 204 | c |
| 205 | c job concluded |
| 206 | c |
| 207 | 300 write (6,301) |
| 208 | 301 format(1h0,9x,'***** job aborted') |
| 209 | nodata=0 |
| 210 | c |
| 211 | c job accounting |
| 212 | c |
| 213 | 320 continue |
| 214 | numel=0 |
| 215 | do 360 i=1,18 |
| 216 | 360 numel=numel+jelcnt(i) |
| 217 | numtem=max0(numtem-1,1) |
| 218 | idist=min0(idist,1) |
| 219 | if (iprnta.eq.0) go to 800 |
| 220 | call title(-1,lwidth,1,acctit) |
| 221 | write (6,361) nunods,ncnods,numnod,numel,(jelcnt(i),i=11,14) |
| 222 | 361 format(' nunods ncnods numnod numel diodes bjts jfets mfets' |
| 223 | 1 //,i9,2i7,i6,i8,i6,2i7) |
| 224 | write (6,371) numtem,icvflg,jtrflg,jacflg,inoise,idist,nogo |
| 225 | 371 format(/'0 numtem icvflg jtrflg jacflg inoise idist nogo'/, |
| 226 | 1 2h0 ,7i7) |
| 227 | write (6,381) rstats(20),rstats(21),rstats(22),rstats(23), |
| 228 | 1 rstats(26),rstats(27) |
| 229 | 381 format(/'0 nstop nttbr nttar ifill iops perspa'//, |
| 230 | 1 1x,5f8.0,f9.3) |
| 231 | write (6,391) rstats(30),rstats(31),rstats(32),maxmem,maxuse, |
| 232 | 1 cpyknt |
| 233 | 391 format(/'0 numttp numrtp numnit maxmem memuse copyknt',//, |
| 234 | 1 2x,3f8.0,2x,i6,2x,i6,2x,f8.0) |
| 235 | write (6,401) (rstats(i),i=1,11) |
| 236 | 401 format(/, |
| 237 | 1 1h0,9x,'readin ',12x,f10.2/, |
| 238 | 2 1h0,9x,'setup ',12x,f10.2/, |
| 239 | 3 1h0,9x,'trcurv ',12x,f10.2,10x,f6.0/, |
| 240 | 4 1h0,9x,'dcan ',12x,f10.2,10x,f6.0/, |
| 241 | 5 1h0,9x,'acan ',12x,f10.2,10x,f6.0/, |
| 242 | 6 1h0,9x,'tranan ',12x,f10.2,10x,f6.0/, |
| 243 | 7 1h0,9x,'output ',12x,f10.2) |
| 244 | 800 call getcje |
| 245 | call second(time2) |
| 246 | et=time2-time1 |
| 247 | tcost=dfloat(icost-icost1)/100.0d0 |
| 248 | if (iprnta.eq.0) go to 810 |
| 249 | ohead=et-(rstats(1)+rstats(2)+rstats(3)+rstats(5)+rstats(7) |
| 250 | 1 +rstats(9)+rstats(11)) |
| 251 | write (6,801) ohead |
| 252 | 801 format(1h0,9x,'overhead',12x,f10.2) |
| 253 | 810 write (6,811) et |
| 254 | 811 format(1h0,9x,'total job time ',f10.2) |
| 255 | tcost=tcost*11.5d0/23.0d0 |
| 256 | c write(6,812) tcost |
| 257 | c 812 format(1h0,9x,'total job cost $',f8.2, |
| 258 | c 1 ' @ $11.50 per cpu minute', |
| 259 | c 2 /'0this lower rate applies for remainder of fiscal 79') |
| 260 | rstats(33)=cpyknt |
| 261 | rstats(34)=et |
| 262 | rstats(35)=tcost |
| 263 | rstats(36)=ohead |
| 264 | c.. convert dble to sgl - 72/2 is how many to convert |
| 265 | c call dblsgl(rstats(1),72) |
| 266 | istats(73)=nunods |
| 267 | istats(74)=ncnods |
| 268 | istats(75)=numnod |
| 269 | istats(76)=numel |
| 270 | istats(77)=jelcnt(11) |
| 271 | istats(78)=jelcnt(12) |
| 272 | istats(79)=jelcnt(13) |
| 273 | istats(80)=jelcnt(14) |
| 274 | istats(81)=numtem |
| 275 | istats(82)=icvflg |
| 276 | istats(83)=jtrflg |
| 277 | istats(84)=jacflg |
| 278 | istats(85)=inoise |
| 279 | istats(86)=idist |
| 280 | istats(87)=nogo |
| 281 | istats(88)=maxmem |
| 282 | istats(89)=maxuse |
| 283 | c do 820 i=1,36 |
| 284 | c 820 r4stat(i)=rlconv(r4stat(i)) |
| 285 | c call cadend(istats,100) |
| 286 | 900 if ((maxtim-itime).ge.limtim) go to 10 |
| 287 | write (6,901) |
| 288 | 901 format('1warning: further analysis stopped due to cpu time limit' |
| 289 | 1/) |
| 290 | 1000 if(nodata.ne.0) write(6,1001) |
| 291 | 1001 format(/1x,'input deck (file) contains no data.') |
| 292 | stop |
| 293 | end |
| 294 | subroutine tmpupd |
| 295 | implicit double precision (a-h,o-z) |
| 296 | c |
| 297 | c this routine updates the temperature-dependent parameters in the |
| 298 | c device models. it also updates the values of temperature-dependent |
| 299 | c resistors. the updated values are printed. |
| 300 | c |
| 301 | common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem, |
| 302 | 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize, |
| 303 | 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr, |
| 304 | 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1, |
| 305 | 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd, |
| 306 | 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval |
| 307 | common /miscel/ atime,aprog(3),adate,atitle(10),defl,defw,defad, |
| 308 | 1 defas,rstats(50),iwidth,lwidth,nopage |
| 309 | common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop, |
| 310 | 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs |
| 311 | common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet, |
| 312 | 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno, |
| 313 | 2 itemno,nosolv,ipostp,iscrch |
| 314 | common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok, |
| 315 | 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox |
| 316 | common /blank/ value(50000) |
| 317 | integer nodplc(64) |
| 318 | complex*16 cvalue(32) |
| 319 | equivalence (value(1),nodplc(1),cvalue(1)) |
| 320 | c |
| 321 | c |
| 322 | dimension tmptit(4) |
| 323 | data tmptit / 8htemperat, 8hure-adju, 8hsted val, 8hues / |
| 324 | c |
| 325 | c |
| 326 | tempd=value(itemps+itemno)+ctok |
| 327 | xkt=boltz*tempd |
| 328 | oldvt=vt |
| 329 | vt=xkt/charge |
| 330 | ratio=tempd/(value(itemps+itemno-1)+ctok) |
| 331 | ratlog=dlog(ratio) |
| 332 | ratio1=ratio-1.0d0 |
| 333 | delt=value(itemps+itemno)-value(itemps+1) |
| 334 | deltsq=delt*delt |
| 335 | reftmp=27.0d0+ctok |
| 336 | oldeg=egfet |
| 337 | egfet=1.16d0-(7.02d-4*tempd*tempd)/(tempd+1108.0d0) |
| 338 | oldxni=xni |
| 339 | arg=-egfet/(xkt+xkt)+1.1151d0/(boltz*(reftmp+reftmp)) |
| 340 | factor=tempd/reftmp |
| 341 | factor=factor*dsqrt(factor) |
| 342 | xni=1.45d10*factor*dexp(charge*arg) |
| 343 | pbfact=(vt+vt)*dlog(oldxni/xni) |
| 344 | call title(0,lwidth,1,tmptit) |
| 345 | c |
| 346 | c resistors |
| 347 | c |
| 348 | loc=locate(1) |
| 349 | ititle=0 |
| 350 | 10 if (loc.eq.0) go to 100 |
| 351 | locv=nodplc(loc+1) |
| 352 | tc1=value(locv+3) |
| 353 | tc2=value(locv+4) |
| 354 | if (tc1.ne.0.0d0) go to 20 |
| 355 | if (tc2.eq.0.0d0) go to 40 |
| 356 | 20 if (ititle.ne.0) go to 30 |
| 357 | write (6,21) |
| 358 | 21 format(//'0**** resistors',/,'0name',8x,'value',//) |
| 359 | ititle=1 |
| 360 | 30 rnew=value(locv+2)*(1.0d0+tc1*delt+tc2*deltsq) |
| 361 | value(locv+1)=1.0d0/rnew |
| 362 | write (6,31) value(locv),rnew |
| 363 | 31 format(1x,a8,1p6d11.2) |
| 364 | 40 loc=nodplc(loc) |
| 365 | go to 10 |
| 366 | c |
| 367 | c diode model |
| 368 | c |
| 369 | 100 loc=locate(21) |
| 370 | if (loc.eq.0) go to 200 |
| 371 | write (6,101) |
| 372 | 101 format(//'0**** diode model parameters',/,'0name',9x,'is',9x,'pb', |
| 373 | 1//) |
| 374 | 110 if (loc.eq.0) go to 200 |
| 375 | locv=nodplc(loc+1) |
| 376 | c... is(t2)=is(t1)*dexp(eg/(n*vt)*(t2/t1-1))*(t2/t1)^(pt/n) |
| 377 | xn=value(locv+3) |
| 378 | factor=ratio1*value(locv+8)/(xn*vt)+value(locv+9)/xn*ratlog |
| 379 | factor=dexp(factor) |
| 380 | value(locv+1)=value(locv+1)*factor |
| 381 | oldpb=value(locv+6) |
| 382 | value(locv+6)=ratio*oldpb+pbfact |
| 383 | value(locv+12)=value(locv+12)*value(locv+6)/oldpb |
| 384 | value(locv+15)=value(locv+15)*value(locv+6)/oldpb |
| 385 | vte=value(locv+3)*vt |
| 386 | value(locv+18)=vte*dlog(vte/(root2*value(locv+1))) |
| 387 | write (6,31) value(locv),value(locv+1),value(locv+6) |
| 388 | loc=nodplc(loc) |
| 389 | go to 110 |
| 390 | c |
| 391 | c bipolar transistor model |
| 392 | c |
| 393 | 200 loc=locate(22) |
| 394 | if (loc.eq.0) go to 300 |
| 395 | write (6,201) |
| 396 | 201 format(//'0**** bjt model parameters',/,'0name',9x,'js',8x,'bf ', |
| 397 | 1 7x,'jle',7x,'br ',7x,'jlc',7x,'vje',7x,'vjc',//) |
| 398 | 210 if (loc.eq.0) go to 300 |
| 399 | locv=nodplc(loc+1) |
| 400 | c... is(t2)=is(t1)*dexp(eg/vt*(t2/t1-1))*(t2/t1)^pt |
| 401 | factln=ratio1*value(locv+42)/vt+value(locv+43)*ratlog |
| 402 | factor=dexp(factln) |
| 403 | value(locv+1)=value(locv+1)*factor |
| 404 | tb=value(locv+41) |
| 405 | bfactr=dexp(tb*ratlog) |
| 406 | value(locv+2)=value(locv+2)*bfactr |
| 407 | value(locv+8)=value(locv+8)*bfactr |
| 408 | value(locv+6)=value(locv+6)*dexp(factln/value(locv+7))/bfactr |
| 409 | value(locv+12)=value(locv+12)*dexp(factln/value(locv+13)) |
| 410 | 1 /bfactr |
| 411 | oldpb=value(locv+22) |
| 412 | value(locv+22)=ratio*oldpb+pbfact |
| 413 | value(locv+46)=value(locv+46)*value(locv+22)/oldpb |
| 414 | value(locv+47)=value(locv+47)*value(locv+22)/oldpb |
| 415 | oldpb=value(locv+30) |
| 416 | value(locv+30)=ratio*oldpb+pbfact |
| 417 | value(locv+50)=value(locv+50)*value(locv+30)/oldpb |
| 418 | value(locv+51)=value(locv+51)*value(locv+30)/oldpb |
| 419 | value(locv+54)=vt*dlog(vt/(root2*value(locv+1))) |
| 420 | write (6,211) value(locv),value(locv+1),value(locv+2), |
| 421 | 1 value(locv+6),value(locv+8),value(locv+12),value(locv+22), |
| 422 | 2 value(locv+30) |
| 423 | 211 format(1x,a8,1p7d10.2) |
| 424 | loc=nodplc(loc) |
| 425 | go to 210 |
| 426 | c |
| 427 | c jfet model |
| 428 | c |
| 429 | 300 loc=locate(23) |
| 430 | if (loc.eq.0) go to 400 |
| 431 | write (6,301) |
| 432 | 301 format(//'0**** jfet model parameters',/,'0name',9x,'is',9x,'pb', |
| 433 | 1//) |
| 434 | 310 if (loc.eq.0) go to 400 |
| 435 | locv=nodplc(loc+1) |
| 436 | value(locv+9)=value(locv+9)*dexp(ratio1*1.11d0/vt) |
| 437 | oldpb=value(locv+8) |
| 438 | value(locv+8)=ratio*oldpb+pbfact |
| 439 | value(locv+12)=value(locv+12)*value(locv+8)/oldpb |
| 440 | value(locv+13)=value(locv+13)*value(locv+8)/oldpb |
| 441 | value(locv+16)=vt*dlog(vt/(root2*value(locv+9))) |
| 442 | write (6,31) value(locv),value(locv+9),value(locv+8) |
| 443 | loc=nodplc(loc) |
| 444 | go to 310 |
| 445 | c |
| 446 | c mosfet model |
| 447 | c |
| 448 | 400 loc=locate(24) |
| 449 | if (loc.eq.0) go to 1000 |
| 450 | iprnt=1 |
| 451 | 410 if (loc.eq.0) go to 1000 |
| 452 | c.. no temperature effects have been coded for ga-as fets |
| 453 | if(nodplc(loc+2).eq.0) go to 430 |
| 454 | locv=nodplc(loc+1) |
| 455 | if(iprnt.ne.0) write (6,401) |
| 456 | 401 format(//'0**** mosfet model parameters',/,'0name',8x,'vto',8x, |
| 457 | 1 'phi',9x,'pb',9x,'js',7x,'kp',//) |
| 458 | iprnt=0 |
| 459 | ratio4=ratio*dsqrt(ratio) |
| 460 | value(locv+2)=value(locv+2)/ratio4 |
| 461 | value(locv+23)=value(locv+23)/ratio4 |
| 462 | oldphi=value(locv+4) |
| 463 | value(locv+4)=ratio*oldphi+pbfact |
| 464 | phi=value(locv+4) |
| 465 | type=nodplc(loc+2) |
| 466 | tps=value(locv+22) |
| 467 | vfb=value(locv+34)-type*oldphi |
| 468 | vstrip=vfb+0.5d0*type*oldphi |
| 469 | if(value(locv+21).ne.0.0d0) go to 415 |
| 470 | vstrip=vstrip+0.5d0*(oldeg-egfet) |
| 471 | go to 420 |
| 472 | 415 oldgat=oldvt*dlog(value(locv+21)/oldxni) |
| 473 | gatnew=vt*dlog(value(locv+21)/xni) |
| 474 | vstrip=vstrip+type*tps*(oldgat-gatnew) |
| 475 | 420 vfb=vstrip-0.5d0*type*phi |
| 476 | value(locv+34)=vfb+type*phi |
| 477 | value(locv+1)=value(locv+34)+type*value(locv+3)*dsqrt(phi) |
| 478 | value(locv+15)=value(locv+15)*dexp(-egfet/vt+oldeg/oldvt) |
| 479 | oldpb=value(locv+14) |
| 480 | value(locv+14)=ratio*oldpb+pbfact |
| 481 | pb=value(locv+14) |
| 482 | ratio2=oldpb/pb |
| 483 | ratio3=dsqrt(ratio2) |
| 484 | value(locv+11)=value(locv+11)*ratio3 |
| 485 | value(locv+12)=value(locv+12)*ratio3 |
| 486 | pbrat=1.0d0/ratio2 |
| 487 | value(locv+29)=value(locv+29)*pbrat |
| 488 | value(locv+30)=value(locv+30)*pbrat |
| 489 | write (6,31) value(locv),value(locv+1),value(locv+4), |
| 490 | 1 value(locv+14),value(locv+15),value(locv+2) |
| 491 | 430 loc=nodplc(loc) |
| 492 | go to 410 |
| 493 | c |
| 494 | c finished |
| 495 | c |
| 496 | 1000 return |
| 497 | end |
| 498 | subroutine find(aname,id,loc,iforce) |
| 499 | implicit double precision (a-h,o-z) |
| 500 | c |
| 501 | c this routine searches the list with number 'id' for an element |
| 502 | c with name 'aname'. loc is set to point to the element. if iforce is |
| 503 | c nonzero, then find expects to have to add the element to the list, and |
| 504 | c reports a fatal error if the element is found. if subcircuit defini- |
| 505 | c tion is in progress (nonzero value for nsbckt), then find searches the |
| 506 | c current subcircuit definition list rather than the nominal element |
| 507 | c list. |
| 508 | c |
| 509 | common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem, |
| 510 | 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize, |
| 511 | 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr, |
| 512 | 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1, |
| 513 | 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd, |
| 514 | 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval |
| 515 | common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop, |
| 516 | 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs |
| 517 | common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts, |
| 518 | 1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof |
| 519 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 520 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 521 | 2 nwd8,nwd16 |
| 522 | common /blank/ value(50000) |
| 523 | integer nodplc(64) |
| 524 | complex*16 cvalue(32) |
| 525 | equivalence (value(1),nodplc(1),cvalue(1)) |
| 526 | c |
| 527 | c index to the contents of the various lists: |
| 528 | c |
| 529 | c list contents |
| 530 | c ---- -------- |
| 531 | c |
| 532 | c 1 resistors |
| 533 | c 2 nonlinear capacitors |
| 534 | c 3 nonlinear inductors |
| 535 | c 4 mutual inductors |
| 536 | c 5 nonlinear voltage controlled current sources |
| 537 | c 6 nonlinear voltage controlled voltage sources |
| 538 | c 7 nonlinear current controlled current sources |
| 539 | c 8 nonlinear current controlled voltage sources |
| 540 | c 9 independent voltage sources |
| 541 | c 10 independent current sources |
| 542 | c 11 diodes |
| 543 | c 12 bipolar junction transistors |
| 544 | c 13 junction field-effect transistors (jfets) |
| 545 | c 14 metal-oxide-semiconductor junction fets (mosfets) |
| 546 | c 15 s-parameter 2-port network |
| 547 | c 16 y-parameter 2-port network |
| 548 | c 17 transmission lines |
| 549 | c 18 <unused> |
| 550 | c 19 subcircuit calls |
| 551 | c 20 subcircuit definitions |
| 552 | c 21 diode model |
| 553 | c 22 bjt model |
| 554 | c 23 jfet model |
| 555 | c 24 mosfet model |
| 556 | c 25-30 <unused> |
| 557 | c 31 .print dc |
| 558 | c 32 .print tran |
| 559 | c 33 .print ac |
| 560 | c 34 .print noise |
| 561 | c 35 .print distortion |
| 562 | c 36 .plot dc |
| 563 | c 37 .plot tr |
| 564 | c 38 .plot ac |
| 565 | c 39 .plot noise |
| 566 | c 40 .plot distortion |
| 567 | c 41 outputs for dc |
| 568 | c 42 outputs for transient |
| 569 | c 43 outputs for ac |
| 570 | c 44 outputs for noise |
| 571 | c 45 outputs for distortion |
| 572 | c 46-50 <unused> |
| 573 | c |
| 574 | integer xxor |
| 575 | dimension lnod(50),lval(50) |
| 576 | data lnod / 9,13,15, 7,14,15,14,15,12, 7, |
| 577 | 1 17,37,26,34, 7, 7,34, 0, 5, 5, |
| 578 | 2 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, |
| 579 | 3 21,21,21,21,21,21,21,21,21,21, |
| 580 | 4 8, 8, 8, 8, 8, 0, 0, 0, 0, 0 / |
| 581 | data lval / 5, 4, 4, 2, 1, 1, 1, 1, 4, 4, |
| 582 | 1 3, 4, 4,13, 1, 1, 9, 0, 1, 1, |
| 583 | 2 19,55,17,41, 0, 0, 0, 0, 0, 0, |
| 584 | 3 1, 1, 1, 1, 1,17,17,17,17,17, |
| 585 | 4 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 / |
| 586 | data ndefin /2h.u/ |
| 587 | c |
| 588 | c |
| 589 | anam=aname |
| 590 | call sizmem(ielmnt,isize) |
| 591 | locn=ielmnt+isize+2 |
| 592 | if (nsbckt.eq.0) go to 10 |
| 593 | loct=nodplc(isbckt+nsbckt) |
| 594 | loc=nodplc(loct+3) |
| 595 | if (loc.ne.0) go to 20 |
| 596 | nodplc(loct+3)=locn |
| 597 | go to 60 |
| 598 | 10 loc=locate(id) |
| 599 | if (loc.ne.0) go to 20 |
| 600 | locate(id)=locn |
| 601 | go to 50 |
| 602 | c |
| 603 | c search list for a name match |
| 604 | c |
| 605 | 20 locv=nodplc(loc+1) |
| 606 | if (xxor(anam,value(locv)).ne.0) go to 30 |
| 607 | if (nsbckt.eq.0) go to 25 |
| 608 | if (nodplc(loc-1).ne.id) go to 30 |
| 609 | 25 if (nodplc(loc+2).eq.ndefin) go to 200 |
| 610 | if (iforce.eq.0) go to 200 |
| 611 | write (6,26) anam |
| 612 | 26 format('0*error*: above line attempts to redefine ',a8/) |
| 613 | nogo=1 |
| 614 | 30 if (nodplc(loc).eq.0) go to 40 |
| 615 | loc=nodplc(loc) |
| 616 | go to 20 |
| 617 | c |
| 618 | c reserve space for this element |
| 619 | c |
| 620 | 40 nodplc(loc)=locn |
| 621 | if (nsbckt.ne.0) go to 60 |
| 622 | 50 jelcnt(id)=jelcnt(id)+1 |
| 623 | 60 loc=locn |
| 624 | itemp=loc+lnod(id)*nwd4-1 |
| 625 | locv=nxtevn(itemp-1)+1 |
| 626 | itemp=locv-itemp |
| 627 | ktmp=lnod(id)*nwd4+lval(id)*nwd8+itemp |
| 628 | call extmem(ielmnt,ktmp) |
| 629 | locv=(locv-1)/nwd8+1 |
| 630 | iptr=0 |
| 631 | if (nsbckt.eq.0) go to 80 |
| 632 | iptr=id |
| 633 | 80 nodplc(loc-1)=iptr |
| 634 | nodplc(loc)=0 |
| 635 | nodplc(loc+1)=locv |
| 636 | value(locv)=anam |
| 637 | c |
| 638 | c background storage |
| 639 | c |
| 640 | 100 nodplc(loc+2)=ndefin |
| 641 | nword=lnod(id)-4 |
| 642 | if (nword.lt.1) go to 120 |
| 643 | call zero4(nodplc(loc+3),nword) |
| 644 | 120 nword=lval(id)-1 |
| 645 | if (nword.lt.1) go to 200 |
| 646 | call zero8(value(locv+1),nword) |
| 647 | c |
| 648 | c exit |
| 649 | c |
| 650 | 200 return |
| 651 | end |
| 652 | subroutine title(ifold,len,icom,coment) |
| 653 | implicit double precision (a-h,o-z) |
| 654 | c |
| 655 | c this routine writes a title on the output file. ifold indicates |
| 656 | c whether the page eject should be to the next concave, convex, or any |
| 657 | c page fold depending on whether its value is <0, >0, or =0. the page |
| 658 | c eject is suppressed (as is much of the heading) if the variable nopage |
| 659 | c is nonzero. |
| 660 | c |
| 661 | common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem, |
| 662 | 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize, |
| 663 | 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr, |
| 664 | 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1, |
| 665 | 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd, |
| 666 | 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval |
| 667 | common /miscel/ atime,aprog(3),adate,atitle(10),defl,defw,defad, |
| 668 | 1 defas,rstats(50),iwidth,lwidth,nopage |
| 669 | common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet, |
| 670 | 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno, |
| 671 | 2 itemno,nosolv,ipostp,iscrch |
| 672 | common /blank/ value(50000) |
| 673 | integer nodplc(64) |
| 674 | complex*16 cvalue(32) |
| 675 | equivalence (value(1),nodplc(1),cvalue(1)) |
| 676 | c |
| 677 | c |
| 678 | dimension coment(4) |
| 679 | c |
| 680 | c |
| 681 | if(nopage.eq.1) go to 150 |
| 682 | c |
| 683 | 30 if (len.le.80) go to 100 |
| 684 | write (6,31) adate,aprog,atime,(atitle(i),i=1,10) |
| 685 | 31 format(1h1,9(2h* ),a10,1x,11(2h* ),3a8,11(2h* ),a10,9(2h *),//1h0, |
| 686 | 1 15a8/) |
| 687 | if (icom.eq.0) go to 40 |
| 688 | write (6,36) coment,value(itemps+itemno) |
| 689 | 36 format(5h0****,17x,4a8,21x,'temperature =',f9.3,' deg c'/) |
| 690 | 40 write (6,41) |
| 691 | 41 format(1h0,63(2h* )//) |
| 692 | go to 200 |
| 693 | c |
| 694 | c |
| 695 | 100 write (6,101) adate,aprog,atime,(atitle(i),i=1,10) |
| 696 | 101 format(1h1,5(1h*),a10,1x,8(1h*),3a8,8(1h*),a10,5(1h*)//1h0,10a8/) |
| 697 | if (icom.eq.0) go to 110 |
| 698 | write (6,106) coment,value(itemps+itemno) |
| 699 | 106 format(10h0**** ,4a8,' temperature =',f9.3,' deg c'/) |
| 700 | 110 write (6,111) |
| 701 | 111 format(1h0,71(1h*)//) |
| 702 | go to 200 |
| 703 | c |
| 704 | c |
| 705 | 150 if (icom.eq.0) go to 160 |
| 706 | write (6,106) coment,value(itemps+itemno) |
| 707 | go to 200 |
| 708 | 160 write (6,161) aprog |
| 709 | 161 format(1h0,3a8,/) |
| 710 | c |
| 711 | c finished |
| 712 | c |
| 713 | 200 return |
| 714 | end |
| 715 | subroutine dcdcmp |
| 716 | implicit double precision (a-h,o-z) |
| 717 | c |
| 718 | c this routine performs an in-place lu factorization of the coef- |
| 719 | c ficient matrix. |
| 720 | c |
| 721 | common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem, |
| 722 | 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize, |
| 723 | 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr, |
| 724 | 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1, |
| 725 | 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd, |
| 726 | 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval |
| 727 | common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop, |
| 728 | 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs |
| 729 | common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts, |
| 730 | 1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof |
| 731 | common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok, |
| 732 | 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox |
| 733 | common /blank/ value(50000) |
| 734 | integer nodplc(64) |
| 735 | complex*16 cvalue(32) |
| 736 | equivalence (value(1),nodplc(1),cvalue(1)) |
| 737 | data ikount /0/ |
| 738 | c |
| 739 | c |
| 740 | do 100 i=2,nstop |
| 741 | io=nodplc(iorder+i) |
| 742 | if (dabs(value(lynl+io)).ge.gmin) go to 10 |
| 743 | value(lynl+io)=gmin |
| 744 | igoof=igoof+1 |
| 745 | if(ikount.gt.20) go to 10 |
| 746 | ikount=ikount+1 |
| 747 | if(io.le.nunods) write(6,9) nodplc(junode+io) |
| 748 | 9 format(' at node ',i5) |
| 749 | 10 jstart=nodplc(ilc+i) |
| 750 | jstop=nodplc(ilc+i+1)-1 |
| 751 | if (jstart.gt.jstop) go to 100 |
| 752 | do 90 j=jstart,jstop |
| 753 | value(lyl+j)=value(lyl+j)/value(lynl+io) |
| 754 | icol=nodplc(ilr+j) |
| 755 | kstart=nodplc(iur+i) |
| 756 | kstop=nodplc(iur+i+1)-1 |
| 757 | if (kstart.gt.kstop) go to 90 |
| 758 | do 80 k=kstart,kstop |
| 759 | irow=nodplc(iuc+k) |
| 760 | if (icol-irow) 20,60,40 |
| 761 | c |
| 762 | c find (icol,irow) matrix term (upper triangle) |
| 763 | c |
| 764 | 20 l=nodplc(iur+icol+1) |
| 765 | 30 l=l-1 |
| 766 | if (nodplc(iuc+l).ne.irow) go to 30 |
| 767 | ispot=lyu+l |
| 768 | go to 70 |
| 769 | c |
| 770 | c find (icol,irow) matrix term (lower triangle) |
| 771 | c |
| 772 | 40 l=nodplc(ilc+irow+1) |
| 773 | 50 l=l-1 |
| 774 | if (nodplc(ilr+l).ne.icol) go to 50 |
| 775 | ispot=lyl+l |
| 776 | go to 70 |
| 777 | c |
| 778 | c find (icol,irow) matrix term (diagonal) |
| 779 | c |
| 780 | 60 ispot=lynl+nodplc(iorder+irow) |
| 781 | c |
| 782 | 70 value(ispot)=value(ispot)-value(lyl+j)*value(lyu+k) |
| 783 | 80 continue |
| 784 | 90 continue |
| 785 | 100 continue |
| 786 | return |
| 787 | end |
| 788 | subroutine dcsol |
| 789 | implicit double precision (a-h,o-z) |
| 790 | c |
| 791 | c this routine solves the system of circuit equations by performing |
| 792 | c a forward and backward substitution step using the previously-computed |
| 793 | c lu factors. |
| 794 | c |
| 795 | common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem, |
| 796 | 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize, |
| 797 | 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr, |
| 798 | 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1, |
| 799 | 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd, |
| 800 | 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval |
| 801 | common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop, |
| 802 | 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs |
| 803 | common /blank/ value(50000) |
| 804 | integer nodplc(64) |
| 805 | complex*16 cvalue(32) |
| 806 | equivalence (value(1),nodplc(1),cvalue(1)) |
| 807 | c |
| 808 | c forward substitution |
| 809 | c |
| 810 | do 20 i=2,nstop |
| 811 | jstart=nodplc(ilc+i) |
| 812 | jstop=nodplc(ilc+i+1)-1 |
| 813 | if (jstart.gt.jstop) go to 20 |
| 814 | io=nodplc(iorder+i) |
| 815 | if (value(lvn+io).eq.0.0d0) go to 20 |
| 816 | do 10 j=jstart,jstop |
| 817 | jo=nodplc(ilr+j) |
| 818 | jo=nodplc(iorder+jo) |
| 819 | value(lvn+jo)=value(lvn+jo)-value(lyl+j)*value(lvn+io) |
| 820 | 10 continue |
| 821 | 20 continue |
| 822 | c |
| 823 | c back substitution |
| 824 | c |
| 825 | k=nstop+1 |
| 826 | do 50 i=2,nstop |
| 827 | k=k-1 |
| 828 | io=nodplc(iorder+k) |
| 829 | jstart=nodplc(iur+k) |
| 830 | jstop=nodplc(iur+k+1)-1 |
| 831 | if (jstart.gt.jstop) go to 40 |
| 832 | do 30 j=jstart,jstop |
| 833 | jo=nodplc(iuc+j) |
| 834 | jo=nodplc(iorder+jo) |
| 835 | value(lvn+io)=value(lvn+io)-value(lyu+j)*value(lvn+jo) |
| 836 | 30 continue |
| 837 | 40 value(lvn+io)=value(lvn+io)/value(lynl+io) |
| 838 | 50 continue |
| 839 | return |
| 840 | end |
| 841 | subroutine setmem(ipntr,ksize) |
| 842 | implicit double precision (a-h,o-z) |
| 843 | c |
| 844 | c this routine performs dynamic memory management. it is used in |
| 845 | c spice2, and useable in any program. |
| 846 | c |
| 847 | c memory is managed within an array selected by the calling program. |
| 848 | c one may either dimension this array to the 'maxmem' size, or more |
| 849 | c desirably, find the address of the first available word of memory |
| 850 | c above your program, and dimension your array to '1'. passing the |
| 851 | c address of the first data word available permits the manager to |
| 852 | c use 'illegal' indices into the data area. |
| 853 | c |
| 854 | c this routine must have access to an integer function called 'locf' |
| 855 | c which returns the address of its argument. addresses as used by this |
| 856 | c program refer to 'integer' addresses, not byte addresses. |
| 857 | c |
| 858 | c entry points: |
| 859 | c setmem - set initial memory |
| 860 | c getm4 - get block for table of integers |
| 861 | c getm8 - get block for table of floating point variables |
| 862 | c getm16 - get block for table of complex variables |
| 863 | c relmem - release part of block |
| 864 | c extmem - extend size of existing block |
| 865 | c sizmem - determine size of existing block |
| 866 | c clrmem - release block |
| 867 | c ptrmem - reset memory pointer |
| 868 | c crunch - force memory compaction |
| 869 | c avlm4 - amount of space available (integers) |
| 870 | c avlm8 - amount of space available (real) |
| 871 | c avlm16 - amount of space available (complex) |
| 872 | c |
| 873 | c calling sequences: |
| 874 | c call setmem(imem(1),maxmem) |
| 875 | c call setmem(imem(1),maxmem,kfamwa) non 3000 machines kfamwa is |
| 876 | c address of first available word |
| 877 | c of data |
| 878 | c call getm4 (ipntr,blksiz) where blksize is the number of entries |
| 879 | c call getm8 (ipntr,blksiz) |
| 880 | c call getm16(ipntr,blksiz) |
| 881 | c call relmem(ipntr,relsiz) |
| 882 | c call extmem(ipntr,extsiz) extsiz is the number of entries to be added |
| 883 | c call sizmem(ipntr,blksiz) |
| 884 | c call clrmem(ipntr) |
| 885 | c call ptrmem(ipntr1,ipntr2) |
| 886 | c call avlm4(ispace) |
| 887 | c call avlm8(ispace) |
| 888 | c call avlm16(ispace) |
| 889 | c call crunch |
| 890 | c |
| 891 | c |
| 892 | c general comments: |
| 893 | c for each block which is allocated, a 5-word entry is maintained |
| 894 | c in a table kept in high memory, of the form |
| 895 | c |
| 896 | c word contents |
| 897 | c ---- -------- |
| 898 | c |
| 899 | c 1 index of imem(.) into origin of block |
| 900 | c i.e. contents of pointer (used for error check) |
| 901 | c 2 block size (in words) |
| 902 | c 3 number of words in use |
| 903 | c 4 address of variable containing block origin |
| 904 | c 5 number of words used per table entry |
| 905 | c |
| 906 | c all allocated blocks are an 'even' (nxtevn) number of words in length, |
| 907 | c where a 'word' is the storage unit required for an 'integer' variable. |
| 908 | c since block repositioning may be necessary, the convention that |
| 909 | c only one variable contain a block origin should be observed. |
| 910 | c for *getmem*, *ipntr* is set such that *array(ipntr+1)* is the |
| 911 | c first word of the allocated block. 'ipntr' is set to address the first |
| 912 | c entry of the table when used with the appropriate variable type, i.e., |
| 913 | c nodplc(ipntr+1), value(ipntr+1), or cvalue(ipntr+1). |
| 914 | c for *clrmem*, *ipntr* is set to 'invalid' to enable rapid detection |
| 915 | c of an attempt to use a cleared block. |
| 916 | c if any fatal errors are found, a message is printed and a flag |
| 917 | c set inhibiting further action until *setmem* is called. (in this |
| 918 | c context, insufficient memory is considered a fatal error.) |
| 919 | c throughout this routine, *ldval* always contains the subscript of |
| 920 | c the last addressable word of memory, *memavl* always contains the |
| 921 | c number of available words of memory, *numblk* always contains the |
| 922 | c number of allocated blocks, and istack(*loctab* +1) always contains |
| 923 | c the first word of the block table. |
| 924 | c |
| 925 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 926 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 927 | 2 nwd8,nwd16 |
| 928 | c |
| 929 | c.. arguments to memory manager are set up as arrays, even though |
| 930 | c.. the calling programs usually use simple variables for arguments. |
| 931 | c.. this is necessary if we are to guarantee that the parameters are |
| 932 | c.. passed by 'address' and not by 'value'. we must insure that locf(arg) |
| 933 | c.. returns the address of the argument, and not the address of a local |
| 934 | c.. copy of the argument. as currently configured, this subroutine should |
| 935 | c.. work on any ansi fortran compiler, provided the function 'locf' can |
| 936 | c.. be provided. |
| 937 | dimension ipntr(1) |
| 938 | c |
| 939 | logical memptr |
| 940 | c |
| 941 | c... approximate time required to copy *nwords* integer values |
| 942 | nwd4=1 |
| 943 | nwd8=2 |
| 944 | nwd16=4 |
| 945 | memerr=0 |
| 946 | nevn=nxtevn(1) |
| 947 | icheck=mod(nevn,nwd4)+mod(nevn,nwd8)+mod(nevn,nwd16)+ |
| 948 | 1 mod(nxtmem(1),nevn) |
| 949 | if(icheck.eq.0) go to 2 |
| 950 | memerr=1 |
| 951 | call errmem(6,memerr,ipntr(1)) |
| 952 | 2 cpyknt=0.0d0 |
| 953 | ifamwa=locf(ipntr(1)) |
| 954 | maxmem=ksize |
| 955 | ntab=nxtevn(5) |
| 956 | c... add 'lorg' to an address and you get the 'istack' index to that word |
| 957 | lorg=1-locf(istack(1)) |
| 958 | ifwa=ifamwa+lorg-1 |
| 959 | nwoff=locf(ipntr(1))+lorg-1 |
| 960 | icore=nxtmem(1) |
| 961 | c... don't take chances, back off from 'end of memory' by nxtevn(1) |
| 962 | ldval=ifwa+nxtmem(1)-nxtevn(1) |
| 963 | memavl=ldval-ntab-ifwa |
| 964 | maxcor=0 |
| 965 | maxuse=0 |
| 966 | call memory |
| 967 | if(memerr.ne.0) call errmem(6,memerr,ipntr(1)) |
| 968 | numblk=1 |
| 969 | loctab=ldval-ntab |
| 970 | istack(loctab+1)=0 |
| 971 | istack(loctab+2)=memavl |
| 972 | istack(loctab+3)=0 |
| 973 | istack(loctab+4)=-1 |
| 974 | istack(loctab+5)=1 |
| 975 | return |
| 976 | end |
| 977 | subroutine getm4(ipntr,ksize) |
| 978 | implicit double precision (a-h,o-z) |
| 979 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 980 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 981 | 2 nwd8,nwd16 |
| 982 | dimension ipntr(1) |
| 983 | iwsize=nwd4 |
| 984 | call getmx(ipntr(1),ksize,iwsize) |
| 985 | return |
| 986 | end |
| 987 | subroutine getm8(ipntr,ksize) |
| 988 | implicit double precision (a-h,o-z) |
| 989 | dimension ipntr(1) |
| 990 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 991 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 992 | 2 nwd8,nwd16 |
| 993 | iwsize=nwd8 |
| 994 | call getmx(ipntr(1),ksize,iwsize) |
| 995 | return |
| 996 | end |
| 997 | subroutine getm16(ipntr,ksize) |
| 998 | implicit double precision (a-h,o-z) |
| 999 | dimension ipntr(1) |
| 1000 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1001 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1002 | 2 nwd8,nwd16 |
| 1003 | iwsize=nwd16 |
| 1004 | call getmx(ipntr(1),ksize,iwsize) |
| 1005 | return |
| 1006 | end |
| 1007 | subroutine getmx(ipntr,ksize,iwsize) |
| 1008 | implicit double precision (a-h,o-z) |
| 1009 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1010 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1011 | 2 nwd8,nwd16 |
| 1012 | logical memptr |
| 1013 | dimension ipntr(1) |
| 1014 | c |
| 1015 | c*** getmem - get block |
| 1016 | c |
| 1017 | c |
| 1018 | isize=ksize*iwsize |
| 1019 | c... check for valid size |
| 1020 | if (isize.ge.0) go to 5 |
| 1021 | memerr=2 |
| 1022 | call errmem(3,memerr,ipntr(1)) |
| 1023 | c... check for attempt to reallocate existing block |
| 1024 | 5 if (.not.memptr(ipntr(1))) go to 8 |
| 1025 | memerr=3 |
| 1026 | call errmem(3,memerr,ipntr(1)) |
| 1027 | 8 jsize=nxtevn(isize) |
| 1028 | call comprs(0,ldval) |
| 1029 | c... check if enough space already there |
| 1030 | need=jsize+ntab-memavl |
| 1031 | if (need.le.0) go to 10 |
| 1032 | c... insufficient space -- bump memory size |
| 1033 | need=nxtmem(need) |
| 1034 | icore=icore+need |
| 1035 | call memory |
| 1036 | if(memerr.ne.0) call errmem(3,memerr,ipntr(1)) |
| 1037 | ltab1=ldval-ntab |
| 1038 | istack(ltab1+2)=istack(ltab1+2)+need |
| 1039 | c... relocate block entry table |
| 1040 | nwords=numblk*ntab |
| 1041 | cpyknt=cpyknt+dfloat(nwords) |
| 1042 | call copy4(istack(loctab+1),istack(loctab+need+1),nwords) |
| 1043 | loctab=loctab+need |
| 1044 | ldval=ldval+need |
| 1045 | memavl=memavl+need |
| 1046 | c... a block large enough now exists -- allocate it |
| 1047 | 10 ltab1=ldval-ntab |
| 1048 | morg=istack(ltab1+1) |
| 1049 | msiz=istack(ltab1+2) |
| 1050 | muse=istack(ltab1+3) |
| 1051 | muse=nxtevn(muse) |
| 1052 | madr=istack(ltab1+4) |
| 1053 | c... construct new table entry |
| 1054 | 15 istack(ltab1+2)=muse |
| 1055 | loctab=loctab-ntab |
| 1056 | nwords=numblk*ntab |
| 1057 | cpyknt=cpyknt+dfloat(nwords) |
| 1058 | call copy4(istack(loctab+ntab+1),istack(loctab+1),nwords) |
| 1059 | numblk=numblk+1 |
| 1060 | memavl=memavl-ntab |
| 1061 | istack(ltab1+1)=morg+muse |
| 1062 | istack(ltab1+2)=msiz-muse-ntab |
| 1063 | c... set user size into table entry for this block |
| 1064 | 20 istack(ltab1+3)=isize |
| 1065 | istack(ltab1+4)=locf(ipntr(1)) |
| 1066 | istack(ltab1+5)=iwsize |
| 1067 | memavl=memavl-jsize |
| 1068 | ipntr(1)=istack(ltab1+1)/iwsize |
| 1069 | call memadj |
| 1070 | return |
| 1071 | end |
| 1072 | subroutine avlm4(iavl) |
| 1073 | implicit double precision (a-h,o-z) |
| 1074 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1075 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1076 | 2 nwd8,nwd16 |
| 1077 | c |
| 1078 | c*** avlmem - how much space is available ? |
| 1079 | c |
| 1080 | iavl=((maxmem-icore)/nxtmem(1))*nxtmem(1)-ntab+memavl |
| 1081 | iavl=iavl/nwd4 |
| 1082 | return |
| 1083 | end |
| 1084 | subroutine avlm8(iavl) |
| 1085 | implicit double precision (a-h,o-z) |
| 1086 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1087 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1088 | 2 nwd8,nwd16 |
| 1089 | iavl=((maxmem-icore)/nxtmem(1))*nxtmem(1)-ntab+memavl |
| 1090 | iavl=iavl/nwd8 |
| 1091 | return |
| 1092 | end |
| 1093 | subroutine avlm16(iavl) |
| 1094 | implicit double precision (a-h,o-z) |
| 1095 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1096 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1097 | 2 nwd8,nwd16 |
| 1098 | iavl=((maxmem-icore)/nxtmem(1))*nxtmem(1)-ntab+memavl |
| 1099 | iavl=iavl/nwd16 |
| 1100 | return |
| 1101 | end |
| 1102 | subroutine relmem(ipntr,ksize) |
| 1103 | implicit double precision (a-h,o-z) |
| 1104 | dimension ipntr(1) |
| 1105 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1106 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1107 | 2 nwd8,nwd16 |
| 1108 | logical memptr |
| 1109 | c |
| 1110 | c*** relmem - release part of block |
| 1111 | c |
| 1112 | c |
| 1113 | c... check for valid pointer |
| 1114 | if (memptr(ipntr(1))) go to 10 |
| 1115 | memerr=5 |
| 1116 | call errmem(5,memerr,ipntr(1)) |
| 1117 | 10 isize=ksize*istack(ltab+5) |
| 1118 | c... check for valid size |
| 1119 | if (isize.ge.0) go to 20 |
| 1120 | memerr=2 |
| 1121 | call errmem(5,memerr,ipntr(1)) |
| 1122 | 20 jsize=istack(ltab+3) |
| 1123 | if (isize.le.jsize) go to 30 |
| 1124 | memerr=6 |
| 1125 | call errmem(5,memerr,ipntr(1)) |
| 1126 | 30 istack(ltab+3)=istack(ltab+3)-isize |
| 1127 | memavl=memavl+(nxtevn(jsize)-nxtevn(istack(ltab+3))) |
| 1128 | call memadj |
| 1129 | return |
| 1130 | end |
| 1131 | subroutine extmem(ipntr,ksize) |
| 1132 | implicit double precision (a-h,o-z) |
| 1133 | dimension ipntr(1) |
| 1134 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1135 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1136 | 2 nwd8,nwd16 |
| 1137 | logical memptr |
| 1138 | c |
| 1139 | c*** extmem - extend size of existing block |
| 1140 | c |
| 1141 | c |
| 1142 | c... check for valid pointer |
| 1143 | if (memptr(ipntr(1))) go to 10 |
| 1144 | memerr=5 |
| 1145 | call errmem(2,memerr,ipntr(1)) |
| 1146 | 10 isize=ksize*istack(ltab+5) |
| 1147 | c... check for valid size |
| 1148 | if (isize.ge.0) go to 20 |
| 1149 | memerr=2 |
| 1150 | call errmem(2,memerr,ipntr(1)) |
| 1151 | c... check if enough space already there |
| 1152 | 20 if ((istack(ltab+2)-istack(ltab+3)).ge.isize) go to 40 |
| 1153 | need=nxtevn(isize)-memavl |
| 1154 | if (need.le.0) go to 30 |
| 1155 | c... insufficient space -- bump memory size |
| 1156 | need=nxtmem(need) |
| 1157 | icore=icore+need |
| 1158 | call memory |
| 1159 | if(memerr.ne.0) call errmem(2,memerr,ipntr(1)) |
| 1160 | ltab1=ldval-ntab |
| 1161 | istack(ltab1+2)=istack(ltab1+2)+need |
| 1162 | c... relocate block entry table |
| 1163 | nwords=numblk*ntab |
| 1164 | cpyknt=cpyknt+dfloat(nwords) |
| 1165 | call copy4(istack(loctab+1),istack(loctab+need+1),nwords) |
| 1166 | loctab=loctab+need |
| 1167 | ldval=ldval+need |
| 1168 | memavl=memavl+need |
| 1169 | ltab=ltab+need |
| 1170 | c... move blocks to make space |
| 1171 | 30 continue |
| 1172 | call comprs(0,ltab) |
| 1173 | call comprs(1,ltab) |
| 1174 | 40 jsize=istack(ltab+3) |
| 1175 | istack(ltab+3)=istack(ltab+3)+isize |
| 1176 | memavl=memavl-(nxtevn(istack(ltab+3))-nxtevn(jsize)) |
| 1177 | call memadj |
| 1178 | return |
| 1179 | end |
| 1180 | subroutine sizmem(ipntr,ksize) |
| 1181 | implicit double precision (a-h,o-z) |
| 1182 | dimension ipntr(1) |
| 1183 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1184 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1185 | 2 nwd8,nwd16 |
| 1186 | logical memptr |
| 1187 | c |
| 1188 | c*** sizmem - determine size of existing block |
| 1189 | c |
| 1190 | c |
| 1191 | c... check for valid pointer |
| 1192 | if (memptr(ipntr(1))) go to 10 |
| 1193 | memerr=5 |
| 1194 | call errmem(7,memerr,ipntr(1)) |
| 1195 | 10 ksize=istack(ltab+3)/istack(ltab+5) |
| 1196 | return |
| 1197 | end |
| 1198 | subroutine clrmem(ipntr) |
| 1199 | implicit double precision (a-h,o-z) |
| 1200 | dimension ipntr(1) |
| 1201 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1202 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1203 | 2 nwd8,nwd16 |
| 1204 | logical memptr |
| 1205 | c |
| 1206 | c*** clrmem - release block |
| 1207 | c |
| 1208 | c |
| 1209 | c... check that pointer is valid |
| 1210 | if (memptr(ipntr(1))) go to 10 |
| 1211 | memerr=5 |
| 1212 | call errmem(1,memerr,ipntr(1)) |
| 1213 | 10 msiz=istack(ltab+2) |
| 1214 | muse=istack(ltab+3) |
| 1215 | memavl=memavl+nxtevn(muse) |
| 1216 | c... assumption: first allocated block is never cleared. |
| 1217 | ltab1=ltab-ntab |
| 1218 | istack(ltab1+2)=istack(ltab1+2)+msiz |
| 1219 | c... reposition the block table |
| 1220 | nwords=ltab-loctab |
| 1221 | cpyknt=cpyknt+dfloat(nwords) |
| 1222 | call copy4(istack(loctab+1),istack(loctab+ntab+1),nwords) |
| 1223 | numblk=numblk-1 |
| 1224 | loctab=loctab+ntab |
| 1225 | memavl=memavl+ntab |
| 1226 | ltab1=ldval-ntab |
| 1227 | istack(ltab1+2)=istack(ltab1+2)+ntab |
| 1228 | ipntr(1)=2**31-1 |
| 1229 | call memadj |
| 1230 | return |
| 1231 | end |
| 1232 | subroutine ptrmem(ipntr,ipntr2) |
| 1233 | implicit double precision (a-h,o-z) |
| 1234 | dimension ipntr(1),ipntr2(1) |
| 1235 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1236 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1237 | 2 nwd8,nwd16 |
| 1238 | logical memptr |
| 1239 | c |
| 1240 | c*** ptrmem - reset memory pointer |
| 1241 | c |
| 1242 | c... verify that pointer is valid |
| 1243 | if (memptr(ipntr(1))) go to 10 |
| 1244 | memerr=5 |
| 1245 | call errmem(4,memerr,ipntr(1)) |
| 1246 | c... reset block pointer to be *ipntr2* |
| 1247 | 10 ipntr2(1)=ipntr(1) |
| 1248 | istack(ltab+4)=locf(ipntr2(1)) |
| 1249 | call memadj |
| 1250 | return |
| 1251 | end |
| 1252 | subroutine crunch |
| 1253 | implicit double precision (a-h,o-z) |
| 1254 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1255 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1256 | 2 nwd8,nwd16 |
| 1257 | c |
| 1258 | c*** crunch - force memory compaction |
| 1259 | c |
| 1260 | call comprs(0,ldval) |
| 1261 | call memadj |
| 1262 | return |
| 1263 | end |
| 1264 | subroutine errmem(inam,ierror,ipntr) |
| 1265 | implicit double precision (a-h,o-z) |
| 1266 | dimension ipntr(1) |
| 1267 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1268 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1269 | 2 nwd8,nwd16 |
| 1270 | dimension errnam(7) |
| 1271 | data errnam /6hclrmem,6hextmem,6hgetmem,6hptrmem,6hrelmem, |
| 1272 | 1 6hsetmem,6hsizmem/ |
| 1273 | c |
| 1274 | go to (200,410,420,300,510,530),ierror |
| 1275 | c |
| 1276 | c*** error(s) found *** |
| 1277 | c |
| 1278 | c.. nxtevn and/or nxtmem incompatible with nwd4, nwd8, and nwd16 |
| 1279 | c |
| 1280 | 200 write(6,201) |
| 1281 | 201 format('0memory manager variables nwd4-8-16 incompatible with nxte |
| 1282 | 1vn and nxtmem') |
| 1283 | go to 900 |
| 1284 | c |
| 1285 | c... memory needs exceed maximum available space |
| 1286 | 300 write (6,301) maxmem |
| 1287 | 301 format('0*error*: memory needs exceed',i6,/, |
| 1288 | 1 '0probable remedy, replace your "// exec spice" card with',/ |
| 1289 | 2 '0// exec spice,region=2000k') |
| 1290 | go to 900 |
| 1291 | c... *isize* < 0 |
| 1292 | 410 write(6,411) |
| 1293 | 411 format('0size parameter negative') |
| 1294 | go to 900 |
| 1295 | c... getmem: attempt to reallocate existing block |
| 1296 | 420 write(6,421) |
| 1297 | 421 format('0attempt to reallocate existing table') |
| 1298 | go to 900 |
| 1299 | c... *ipntr* invalid |
| 1300 | 510 write(6,511) |
| 1301 | 511 format('0table pointer invalid') |
| 1302 | go to 900 |
| 1303 | c... relmem: *isize* larger than indicated block |
| 1304 | 530 write(6,531) |
| 1305 | 531 format('0attempt to release more than total table') |
| 1306 | c... issue error message |
| 1307 | 900 write (6,901) errnam(inam) |
| 1308 | 901 format('0*abort*: internal memory manager error at entry ', |
| 1309 | 1 a7) |
| 1310 | 950 call dmpmem(ipntr(1)) |
| 1311 | 1000 stop |
| 1312 | end |
| 1313 | subroutine memadj |
| 1314 | implicit double precision (a-h,o-z) |
| 1315 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1316 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1317 | 2 nwd8,nwd16 |
| 1318 | c |
| 1319 | c*** adjust memory downward *** |
| 1320 | c |
| 1321 | 50 maxuse=max0(maxuse,ldval-memavl-ifwa) |
| 1322 | memdec=2*nxtmem(1) |
| 1323 | if (memavl.lt.memdec) return |
| 1324 | c... compress current allocations of memory |
| 1325 | call comprs(0,ldval) |
| 1326 | c... adjust memory size |
| 1327 | memdel=0 |
| 1328 | 60 icore=icore-memdec |
| 1329 | memdel=memdel+memdec |
| 1330 | memavl=memavl-memdec |
| 1331 | if (memavl.ge.memdec) go to 60 |
| 1332 | ltab1=ldval-ntab |
| 1333 | istack(ltab1+2)=istack(ltab1+2)-memdel |
| 1334 | c... relocate block entry table |
| 1335 | nwords=numblk*ntab |
| 1336 | cpyknt=cpyknt+dfloat(nwords) |
| 1337 | call copy4(istack(loctab+1),istack(loctab-memdel+1),nwords) |
| 1338 | loctab=loctab-memdel |
| 1339 | ldval=ldval-memdel |
| 1340 | call memory |
| 1341 | return |
| 1342 | end |
| 1343 | integer function nxtevn(n) |
| 1344 | c |
| 1345 | c.. function returns the smallest value nxtevn greater than or equal to |
| 1346 | c.. n which is evenly divisible by 'nwd4, nwd8, and nwd16' as defined |
| 1347 | c.. in setmem |
| 1348 | c |
| 1349 | nxtevn=((n+3)/4)*4 |
| 1350 | return |
| 1351 | end |
| 1352 | integer function nxtmem(memwds) |
| 1353 | c |
| 1354 | c.. function returns the in nxtmem the next available memory size |
| 1355 | c.. (which must be evenly divisible by 'nwd4, nwd8, and nwd16' as |
| 1356 | c.. defined in setmem |
| 1357 | c |
| 1358 | nxtmem=((memwds+1999)/2000)*2000 |
| 1359 | return |
| 1360 | end |
| 1361 | subroutine comprs(icode,limit) |
| 1362 | implicit double precision (a-h,o-z) |
| 1363 | c |
| 1364 | c this routine compresses all available memory into a single block. |
| 1365 | c if *icode* is zero, compression of memory from word 1 to *limit* is |
| 1366 | c done; otherwise, compression from *ldval* down to *limit* is done. |
| 1367 | c |
| 1368 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1369 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1370 | 2 nwd8,nwd16 |
| 1371 | c |
| 1372 | c... approximate time required to copy *nwords* real values |
| 1373 | if (icode.ne.0) go to 100 |
| 1374 | nblk=numblk |
| 1375 | ltab2=loctab |
| 1376 | 10 ltab1=ltab2 |
| 1377 | if (ltab1.ge.limit) go to 200 |
| 1378 | if (nblk.eq.1) go to 200 |
| 1379 | nblk=nblk-1 |
| 1380 | ltab2=ltab1+ntab |
| 1381 | morg=istack(ltab1+1) |
| 1382 | msiz=istack(ltab1+2) |
| 1383 | muse=istack(ltab1+3) |
| 1384 | muse=nxtevn(muse) |
| 1385 | if (msiz.eq.muse) go to 10 |
| 1386 | c... move succeeding block down |
| 1387 | morg2=istack(ltab2+1) |
| 1388 | muse2=istack(ltab2+3) |
| 1389 | madr2=istack(ltab2+4) |
| 1390 | iwsize=istack(ltab2+5) |
| 1391 | if (madr2.ne.0) go to 15 |
| 1392 | if (muse2.eq.0) go to 20 |
| 1393 | 15 cpyknt=cpyknt+dfloat(muse2) |
| 1394 | call copy4(istack(nwoff+morg2+1),istack(nwoff+morg+muse+1),muse2) |
| 1395 | istack(lorg+madr2)=(morg+muse)/iwsize |
| 1396 | 20 istack(ltab1+2)=muse |
| 1397 | istack(ltab2+1)=morg+muse |
| 1398 | istack(ltab2+2)=istack(ltab2+2)+(msiz-muse) |
| 1399 | go to 10 |
| 1400 | c |
| 1401 | c |
| 1402 | 100 nblk=numblk |
| 1403 | ltab2=ldval-ntab |
| 1404 | 110 ltab1=ltab2 |
| 1405 | if (ltab1.le.limit) go to 200 |
| 1406 | if (nblk.eq.1) go to 200 |
| 1407 | nblk=nblk-1 |
| 1408 | ltab2=ltab1-ntab |
| 1409 | morg=istack(ltab1+1) |
| 1410 | msiz=istack(ltab1+2) |
| 1411 | muse=istack(ltab1+3) |
| 1412 | muse=nxtevn(muse) |
| 1413 | madr=istack(ltab1+4) |
| 1414 | iwsize=istack(ltab1+5) |
| 1415 | mspc=msiz-muse |
| 1416 | if (mspc.eq.0) go to 110 |
| 1417 | cpyknt=cpyknt+dfloat(muse) |
| 1418 | call copy4(istack(nwoff+morg+1),istack(nwoff+morg+mspc+1),muse) |
| 1419 | istack(ltab1+1)=morg+mspc |
| 1420 | istack(ltab1+2)=muse |
| 1421 | istack(ltab2+2)=istack(ltab2+2)+mspc |
| 1422 | if (madr.eq.0) go to 110 |
| 1423 | istack(lorg+madr)=(morg+mspc)/iwsize |
| 1424 | go to 110 |
| 1425 | c... all done |
| 1426 | 200 return |
| 1427 | end |
| 1428 | logical function memptr(ipntr) |
| 1429 | implicit double precision (a-h,o-z) |
| 1430 | c |
| 1431 | c this routine checks whether *ipntr* is a valid block pointer. |
| 1432 | c if it is valid, *ltab* is set to point to the corresponding entry in |
| 1433 | c the block table. |
| 1434 | c |
| 1435 | c... ipntr is an array to avoid 'call by value' problems (see setmem) |
| 1436 | dimension ipntr(1) |
| 1437 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1438 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1439 | 2 nwd8,nwd16 |
| 1440 | c |
| 1441 | memptr=.false. |
| 1442 | ltab=loctab |
| 1443 | locpnt=locf(ipntr(1)) |
| 1444 | do 20 i=1,numblk |
| 1445 | if (locpnt.ne.istack(ltab+4)) go to 10 |
| 1446 | if (ipntr(1)*istack(ltab+5).ne.istack(ltab+1)) go to 10 |
| 1447 | memptr=.true. |
| 1448 | go to 30 |
| 1449 | 10 ltab=ltab+ntab |
| 1450 | 20 continue |
| 1451 | 30 return |
| 1452 | end |
| 1453 | subroutine dmpmem(ipntr) |
| 1454 | implicit double precision (a-h,o-z) |
| 1455 | c |
| 1456 | c this routine prints out the current memory allocation map. |
| 1457 | c *ipntr* is the table pointer of the current memory manager call |
| 1458 | c |
| 1459 | common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem, |
| 1460 | 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize, |
| 1461 | 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr, |
| 1462 | 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1, |
| 1463 | 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd, |
| 1464 | 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval |
| 1465 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1466 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1467 | 2 nwd8,nwd16 |
| 1468 | c... ipntr is an array to avoid 'call by value' problems |
| 1469 | dimension ipntr(1) |
| 1470 | dimension aptr(61) |
| 1471 | data aptr /6hielmnt,6hisbckt,6hnsbckt,6hiunsat,6hnunsat,6hitemps, |
| 1472 | 1 6hnumtem,6hisens ,6hnsens ,6hifour ,6hnfour ,6hifield, |
| 1473 | 2 6hicode ,6hidelim,6hicolum,6hinsize, |
| 1474 | 3 6hjunode,6hlsbkpt,6hnumbkp,6hiorder,6hjmnode, |
| 1475 | 4 6hiur ,6hiuc ,6hilc ,6hilr ,6hnumoff,6hisr , |
| 1476 | 5 6hnmoffc,6hiseq ,6hiseq1 ,6hneqn ,6hnodevs, |
| 1477 | 6 6hndiag ,6hiswap ,6hiequa ,6hmacins,6hlvnim1, |
| 1478 | 7 6hlx0 ,6hlvn ,6hlynl ,6hlyu ,6hlyl , |
| 1479 | 8 6hlx1 ,6hlx2 ,6hlx3 ,6hlx4 ,6hlx5 ,6hlx6 , |
| 1480 | 9 6hlx7 ,6hld0 ,6hld1 ,6hltd ,6himynl ,6himvn ,6hloutpt, |
| 1481 | * 6hnsnod ,6hnsmat ,6hnsval ,6hicnod ,6hicmat ,6hicval / |
| 1482 | data ablnk /1h / |
| 1483 | iaddr=locf(ielmnt)-1 |
| 1484 | itemp=locf(ipntr(1))-iaddr |
| 1485 | anam=ablnk |
| 1486 | if(itemp.gt.0.and.itemp.le.61) anam=aptr(itemp) |
| 1487 | iadr=locf(ipntr(1)) |
| 1488 | write (6,5) anam,iadr,icore,maxmem,memavl,ldval |
| 1489 | 5 format('0current pointer 'a6,'@ = z',z6,/' corsiz=',i7, |
| 1490 | 1 /' maxmem=',i7,/' avlspc=',i7,/' ldval=',i7, |
| 1491 | 2 /1h0,24x,'memory allocation map'/14x,'blknum memorg memsiz', |
| 1492 | 3 ' memuse usrptr addr name') |
| 1493 | ltab1=loctab |
| 1494 | do 20 i=1,numblk |
| 1495 | morg=istack(ltab1+1) |
| 1496 | msiz=istack(ltab1+2) |
| 1497 | muse=istack(ltab1+3) |
| 1498 | madr=istack(ltab1+4) |
| 1499 | anam=ablnk |
| 1500 | ndex=madr-iaddr |
| 1501 | if(ndex.gt.0.and.ndex.le.61) anam=aptr(ndex) |
| 1502 | jptr=0 |
| 1503 | if (madr.gt.0) jptr=istack(lorg+madr) |
| 1504 | write (6,11) i,morg,msiz,muse,jptr,madr,anam |
| 1505 | 11 format(13x,5i7,3x,z7,'z',1x,a6) |
| 1506 | ltab1=ltab1+ntab |
| 1507 | 20 continue |
| 1508 | write (6,21) |
| 1509 | 21 format(1h0,24x,'end of allocation map'/) |
| 1510 | return |
| 1511 | end |
| 1512 | subroutine memory |
| 1513 | implicit double precision (a-h,o-z) |
| 1514 | common /memmgr/ cpyknt,istack(1),lorg,icore,maxcor,maxuse,memavl, |
| 1515 | 1 ldval,numblk,loctab,ltab,ifwa,nwoff,ntab,maxmem,memerr,nwd4, |
| 1516 | 2 nwd8,nwd16 |
| 1517 | if(icore.le.maxmem) go to 10 |
| 1518 | memerr=4 |
| 1519 | return |
| 1520 | 10 continue |
| 1521 | return |
| 1522 | end |
| 1523 | subroutine magphs(cvar,xmag,xphs) |
| 1524 | implicit double precision (a-h,o-z) |
| 1525 | c |
| 1526 | c this routine computes the magnitude and phase of its complex arg- |
| 1527 | c ument cvar, storing the results in xmag and xphs. |
| 1528 | c |
| 1529 | common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok, |
| 1530 | 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox |
| 1531 | complex*16 cvar |
| 1532 | c |
| 1533 | c |
| 1534 | xreal=dreal(cvar) |
| 1535 | ximag=dimag(cvar) |
| 1536 | xmag=dsqrt(xreal*xreal+ximag*ximag) |
| 1537 | if (xmag.ge.1.0d-20) go to 10 |
| 1538 | xmag=1.0d-20 |
| 1539 | xphs=0.0d0 |
| 1540 | return |
| 1541 | 10 xphs=rad*datan2(ximag,xreal) |
| 1542 | return |
| 1543 | end |
| 1544 | integer function xxor(a,b) |
| 1545 | implicit double precision (a-h,o-z) |
| 1546 | c |
| 1547 | c this routine computes a single-precision integer result which is |
| 1548 | c the result of exclusive-or*ing the two real-valued arguments a and b |
| 1549 | c together. |
| 1550 | c |
| 1551 | xxor=1 |
| 1552 | if(a.eq.b) xxor=0 |
| 1553 | return |
| 1554 | end |
| 1555 | subroutine outnam(loc,ktype,string,ipos) |
| 1556 | implicit double precision (a-h,o-z) |
| 1557 | c |
| 1558 | c this routine constructs the 'name' for the output variable indi- |
| 1559 | c cated by loc, adding the characters to the character array 'string', |
| 1560 | c beginning with the position marked by ipos. |
| 1561 | c |
| 1562 | common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem, |
| 1563 | 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize, |
| 1564 | 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr, |
| 1565 | 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1, |
| 1566 | 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd, |
| 1567 | 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval |
| 1568 | common /blank/ value(50000) |
| 1569 | integer nodplc(64) |
| 1570 | complex*16 cvalue(32) |
| 1571 | equivalence (value(1),nodplc(1),cvalue(1)) |
| 1572 | c |
| 1573 | dimension string(1) |
| 1574 | dimension aout(19),lenout(19),aopt(5),lenopt(5) |
| 1575 | data aout / 6hv , 6hvm , 6hvr , 6hvi , 6hvp , |
| 1576 | 1 6hvdb , 6hi , 6him , 6hir , 6hii , |
| 1577 | 2 6hip , 6hidb , 6honoise, 6hinoise, 6hhd2 , |
| 1578 | 1 6hhd3 , 6hdim2 , 6hsim2 , 6hdim3 / |
| 1579 | data lenout / 1,2,2,2,2,3,1,2,2,2,2,3,6,6,3,3,4,4,4 / |
| 1580 | data aopt / 5hmag , 5hreal , 5himag , 5hphase, 5hdb / |
| 1581 | data lenopt / 3,4,4,5,2 / |
| 1582 | data alprn, acomma, arprn, ablnk / 1h(, 1h,, 1h), 1h / |
| 1583 | c |
| 1584 | c |
| 1585 | ioutyp=nodplc(loc+5) |
| 1586 | if (ioutyp.ge.2) go to 10 |
| 1587 | lout=ktype+ioutyp*6 |
| 1588 | go to 20 |
| 1589 | 10 lout=ioutyp+11 |
| 1590 | 20 call move(string,ipos,aout(lout),1,lenout(lout)) |
| 1591 | ipos=ipos+lenout(lout) |
| 1592 | if (ioutyp.ge.2) go to 200 |
| 1593 | call move(string,ipos,alprn,1,1) |
| 1594 | ipos=ipos+1 |
| 1595 | if (ioutyp.ne.0) go to 100 |
| 1596 | node1=nodplc(loc+2) |
| 1597 | call alfnum(nodplc(junode+node1),string,ipos) |
| 1598 | node2=nodplc(loc+3) |
| 1599 | if (node2.eq.1) go to 30 |
| 1600 | call move(string,ipos,acomma,1,1) |
| 1601 | ipos=ipos+1 |
| 1602 | call alfnum(nodplc(junode+node2),string,ipos) |
| 1603 | 30 call move(string,ipos,arprn,1,1) |
| 1604 | ipos=ipos+1 |
| 1605 | go to 1000 |
| 1606 | c |
| 1607 | 100 locv=nodplc(loc+1) |
| 1608 | anam=value(locv) |
| 1609 | achar=ablnk |
| 1610 | do 110 i=1,8 |
| 1611 | call move(achar,1,anam,i,1) |
| 1612 | if (achar.eq.ablnk) go to 120 |
| 1613 | call move(string,ipos,achar,1,1) |
| 1614 | ipos=ipos+1 |
| 1615 | 110 continue |
| 1616 | 120 call move(string,ipos,arprn,1,1) |
| 1617 | ipos=ipos+1 |
| 1618 | go to 1000 |
| 1619 | c |
| 1620 | 200 if (ktype.eq.1) go to 1000 |
| 1621 | call move(string,ipos,alprn,1,1) |
| 1622 | ipos=ipos+1 |
| 1623 | call move(string,ipos,aopt(ktype-1),1,lenopt(ktype-1)) |
| 1624 | ipos=ipos+lenopt(ktype-1) |
| 1625 | call move(string,ipos,arprn,1,1) |
| 1626 | ipos=ipos+1 |
| 1627 | c |
| 1628 | c finished |
| 1629 | c |
| 1630 | 1000 return |
| 1631 | end |
| 1632 | subroutine alfnum(number,string,ipos) |
| 1633 | implicit double precision (a-h,o-z) |
| 1634 | c |
| 1635 | c this routine converts number into character form, storing the |
| 1636 | c characters in the character array string, beginning with the position |
| 1637 | c indicated by ipos. |
| 1638 | c |
| 1639 | c **** note that the 'ipos' variable is changed to indicate the position |
| 1640 | c of the next unwritten character. this could clobber constants if |
| 1641 | c ipos is not a variable in the calling program |
| 1642 | c |
| 1643 | dimension string(1) |
| 1644 | dimension adigit(10) |
| 1645 | data adigit / 1h0,1h1,1h2,1h3,1h4,1h5,1h6,1h7,1h8,1h9 / |
| 1646 | data aminus / 1h- / |
| 1647 | c |
| 1648 | c |
| 1649 | num=number |
| 1650 | c |
| 1651 | c check for number < 0 |
| 1652 | c |
| 1653 | if (num.ge.0) go to 10 |
| 1654 | num=-num |
| 1655 | c... negative number: insert minus sign |
| 1656 | call move(string,ipos,aminus,1,1) |
| 1657 | ipos=ipos+1 |
| 1658 | c |
| 1659 | c convert number one digit at a time, in reverse order |
| 1660 | c |
| 1661 | 10 istart=ipos |
| 1662 | 20 numtmp=num/10 |
| 1663 | idigit=num-numtmp*10 |
| 1664 | call move(string,ipos,adigit(idigit+1),1,1) |
| 1665 | ipos=ipos+1 |
| 1666 | num=numtmp |
| 1667 | if (num.ne.0) go to 20 |
| 1668 | istop=ipos-1 |
| 1669 | c |
| 1670 | c now reverse the order of the digits |
| 1671 | c |
| 1672 | 30 if (istop.le.istart) go to 40 |
| 1673 | call move(tmpdgt,1,string,istart,1) |
| 1674 | call move(string,istart,string,istop,1) |
| 1675 | call move(string,istop,tmpdgt,1,1) |
| 1676 | istart=istart+1 |
| 1677 | istop=istop-1 |
| 1678 | go to 30 |
| 1679 | c |
| 1680 | c conversion complete |
| 1681 | c |
| 1682 | 40 return |
| 1683 | end |
| 1684 | subroutine getcje |
| 1685 | implicit double precision (a-h,o-z) |
| 1686 | common /cje/ maxtim,itime,icost |
| 1687 | call second(xtime) |
| 1688 | itime=xtime |
| 1689 | icost=xtime*38.3333 |
| 1690 | return |
| 1691 | end |
| 1692 | subroutine move(a,iposa,b,iposb,nchar) |
| 1693 | character a(1),b(1) |
| 1694 | do 10 i=1,nchar |
| 1695 | a(iposa+i-1)=b(iposb+i-1) |
| 1696 | 10 continue |
| 1697 | return |
| 1698 | end |
| 1699 | subroutine copy4(ifrom,ito,nwords) |
| 1700 | implicit double precision (a-h,o-z) |
| 1701 | c |
| 1702 | dimension ifrom(1),ito(1) |
| 1703 | c this routine copies a block of #nwords# words (of the appropriate |
| 1704 | c type) from the array #from# to the array #to#. it determines from |
| 1705 | c which end of the block to transfer first, to prevent over-stores which |
| 1706 | c might over-write the data. |
| 1707 | c |
| 1708 | if (nwords.eq.0) return |
| 1709 | if (locf(ifrom(1)).lt.locf(ito(1))) go to 20 |
| 1710 | c... locf() returns as its value the address of its argument |
| 1711 | do 10 i=1,nwords |
| 1712 | ito(i)=ifrom(i) |
| 1713 | 10 continue |
| 1714 | return |
| 1715 | c |
| 1716 | 20 i=nwords |
| 1717 | 30 ito(i)=ifrom(i) |
| 1718 | i=i-1 |
| 1719 | if (i.ne.0) go to 30 |
| 1720 | return |
| 1721 | c |
| 1722 | c |
| 1723 | end |
| 1724 | subroutine copy8(rfrom,rto,nwords) |
| 1725 | implicit double precision (a-h,o-z) |
| 1726 | c |
| 1727 | dimension rfrom(1),rto(1) |
| 1728 | if (nwords.eq.0) return |
| 1729 | if (locf(rfrom(1)).lt.locf(rto(1))) go to 120 |
| 1730 | do 110 i=1,nwords |
| 1731 | rto(i)=rfrom(i) |
| 1732 | 110 continue |
| 1733 | return |
| 1734 | c |
| 1735 | 120 i=nwords |
| 1736 | 130 rto(i)=rfrom(i) |
| 1737 | i=i-1 |
| 1738 | if (i.ne.0) go to 130 |
| 1739 | return |
| 1740 | c |
| 1741 | c |
| 1742 | end |
| 1743 | subroutine copy16(cfrom,cto,nwords) |
| 1744 | implicit double precision (a-h,o-z) |
| 1745 | c |
| 1746 | complex*16 cfrom(1),cto(1) |
| 1747 | if (nwords.eq.0) return |
| 1748 | if (locf(cfrom(1)).lt.locf(cto(1))) go to 220 |
| 1749 | do 210 i=1,nwords |
| 1750 | cto(i)=cfrom(i) |
| 1751 | 210 continue |
| 1752 | return |
| 1753 | c |
| 1754 | 220 i=nwords |
| 1755 | 230 cto(i)=cfrom(i) |
| 1756 | i=i-1 |
| 1757 | if (i.ne.0) go to 230 |
| 1758 | return |
| 1759 | end |
| 1760 | subroutine zero4(iarray,length) |
| 1761 | implicit double precision (a-h,o-z) |
| 1762 | c |
| 1763 | dimension iarray(1) |
| 1764 | c this routine zeroes the memory locations indicated by array(1) |
| 1765 | c through array(length). |
| 1766 | c |
| 1767 | if (length.eq.0) return |
| 1768 | do 10 i=1,length |
| 1769 | iarray(i)=0 |
| 1770 | 10 continue |
| 1771 | return |
| 1772 | end |
| 1773 | subroutine zero8(array,length) |
| 1774 | implicit double precision (a-h,o-z) |
| 1775 | c |
| 1776 | dimension array(1) |
| 1777 | c this routine zeroes the memory locations indicated by array(1) |
| 1778 | c through array(length). |
| 1779 | c |
| 1780 | if (length.eq.0) return |
| 1781 | do 10 i=1,length |
| 1782 | array(i)=0.0d0 |
| 1783 | 10 continue |
| 1784 | return |
| 1785 | end |
| 1786 | subroutine zero16(carray,length) |
| 1787 | implicit double precision (a-h,o-z) |
| 1788 | complex*16 carray(1) |
| 1789 | c |
| 1790 | c this routine zeroes the memory locations indicated by array(1) |
| 1791 | c through array(length). |
| 1792 | c |
| 1793 | if (length.eq.0) return |
| 1794 | do 10 i=1,length |
| 1795 | carray(i)=dcmplx(0.0d0,0.0d0) |
| 1796 | 10 continue |
| 1797 | return |
| 1798 | c |
| 1799 | c |
| 1800 | c |
| 1801 | end |
| 1802 | integer function locf(ivar) |
| 1803 | iabsa=loc(ivar) |
| 1804 | locf=iabsa/4 |
| 1805 | if(iabsa.eq.locf*4) return |
| 1806 | write(6,100) iabsa |
| 1807 | 100 format('0*error*: system 370 error..address ',t10, |
| 1808 | 1 ' is not on a 4-byte boundary') |
| 1809 | stop |
| 1810 | end |
| 1811 | subroutine mdate(anam) |
| 1812 | implicit double precision (a-h,o-z) |
| 1813 | call date(anam) |
| 1814 | return |
| 1815 | end |
| 1816 | subroutine mclock(anam) |
| 1817 | implicit double precision (a-h,o-z) |
| 1818 | call todalf(anam) |
| 1819 | 100 return |
| 1820 | end |
| 1821 | subroutine second(t1) |
| 1822 | implicit double precision (a-h,o-z) |
| 1823 | dimension ibuff(4) |
| 1824 | real*8 t1 |
| 1825 | call times (ibuff) |
| 1826 | t1 = dfloat (ibuff(1)) / 60.d0 |
| 1827 | return |
| 1828 | end |
| 1829 | subroutine todalf(anam) |
| 1830 | double precision anam |
| 1831 | anam=0.0d0 |
| 1832 | return |
| 1833 | end |
| 1834 | double precision function cpusec(time) |
| 1835 | cpusec=0.0d0 |
| 1836 | return |
| 1837 | end |
| 1838 | subroutine date(anam) |
| 1839 | double precision anam |
| 1840 | anam=1.0d0 |
| 1841 | return |
| 1842 | end |
| 1843 | FUNCTION DREAL ( X ) |
| 1844 | COMPLEX*16 X |
| 1845 | DREAL = REAL (X) |
| 1846 | RETURN |
| 1847 | END |
| 1848 | cunix FUNCTION DIMAG ( X ) |
| 1849 | cunix COMPLEX*16 X |
| 1850 | cunix DIMAG = AIMAG (X) |
| 1851 | cunix RETURN |
| 1852 | cunix END |
| 1853 | cunix COMPLEX FUNCTION DCMPLX ( X , Y ) |
| 1854 | cunix DCMPLX = CMPLX ( X , Y ) |
| 1855 | cunix RETURN |
| 1856 | cunix END |
| 1857 | cunix COMPLEX FUNCTION DCONJG ( X ) |
| 1858 | cunix COMPLEX*16 X |
| 1859 | cunix DCONJG = CONJG ( X ) |
| 1860 | cunix RETURN |
| 1861 | cunix END |
| 1862 | FUNCTION IFIXD ( X ) |
| 1863 | IFIXD = IFIX ( X ) |
| 1864 | RETURN |
| 1865 | END |