From 722df73955c1c821c7946a471f0f13453a384fdf Mon Sep 17 00:00:00 2001 From: cdez Date: Thu, 18 Apr 2024 22:05:38 -0700 Subject: [PATCH] Finally gotten to the point with NO MORE WARNINGS!!! YAY --- Sim04/logfile_1.lgf | 7 - Sim04/sim04 | Bin 68984 -> 73944 bytes Sim04/simulator.c | 307 ++++++++++++++++++++++++++++++++++++++------ Sim04/simulator.h | 16 ++- 4 files changed, 283 insertions(+), 47 deletions(-) diff --git a/Sim04/logfile_1.lgf b/Sim04/logfile_1.lgf index 52b0e91..e69de29 100644 --- a/Sim04/logfile_1.lgf +++ b/Sim04/logfile_1.lgf @@ -1,7 +0,0 @@ -0.000000, OS: Simulator start - READY state from NEW state -ate - -ate - - diff --git a/Sim04/sim04 b/Sim04/sim04 index 0b1c3b8a2ddbdd807cd63b47a05023f108f4fba5..52d566410c0ce6b0efe5cc02c0b61ae27c4f8967 100755 GIT binary patch delta 24835 zcmeIacYG98-#0vSW@k%!Z=?~@sG&+|Aprs#YCs~9t^^H&fDjNPVWW^sLX2iTV5ky1 zR=`-08dMBmLoW*!B=$s50a3B;^ZlJOyV=Bc-|y#r{(FYc&N;tcPMtFoE^RiQJZ!2- zXB#7(T|Rc)QlN;-T`EBmR#BL!x>&;P%g@6l-d%djnL#>HE$Jt=wJmor1C}MfO$`Y) zSep#irfvLD^^L@vCF7-bm)$x!D{cXRR9d{~sM-R1$8l(ih&r3xi{=g3#}m zJNU}rSnzHNj_(XfWm(q(`|2SvRJB)rQQ~K>8gdVS=FU*wT!h=p`nEfGQ*d6;4B}{P zj{U>sf`z6Td_c&!zGH?c%9@6fxWH#Cg29X`G~}Km#?nEG@^Y?AJri%QuAo@$l`liE zWCq_Gk{8#byAbRT!H`zLW)i%tD^CoK4Oin7rJbz*3_dY5vh%(HcS-S{kvuc3w-=&xBwyYJF?b|@I;=OVv-9S#M89bs z$*)H8u<*ewdnBI}o;OzD8=D{fMP#Cr0dA4t2m`!bf^!Y9OoFQnaG?b6o>u==c#@V{ z=&|%+j-sF^UxwKB*sH@=wNeh}@Qmm#eOeJ!f^}IxN<&ro8g$~y+y?;cf?U^DwxS$< zdvvUqiNR8?J6IdQdU1-!cv233J-Xx7t%x78$(v>I2J7Bd%7>C-TAh1T1(kfQYo#6# z)WC{Y;glg;*h<}=T|Y7A54B5y$MA+MvJ+TQ_8U?v-J01-y)ld56gzZ!W!WWr<+5{? z1!q^6oz+UR>3(Al?yRIc-EZuNyHaAsT`dValLkfS8naDsLD@sMGcmFVm4)9P;FL4E zDERK!K7O}N_Bd3^&&9^|i2a`23IF|85k-^Hjm*H7mwluJuHjHXR;Y6|T;PM^qEq99 zj>hKd3nG$cyZ!(%Rfqp^xkvf=3%oQgwkrn<=_yHu4usa&JQ0{P5wJMBt;Ko#a9j)9 zex5%bzdYbQD5^3s`$i~z<#OILVNSGp66tPi9)C{s$Swvr^c>GlijM0fK@n$jf63A? zQA$|(rwLuv(L5lrbJW!a?$Pgr7B|ZlJ|Qt9@P0{@N>+VGigSi}d3?vn{)HD^uC=*m%FDh+(#xT=yzC5W zwIZ|nNQ3zfDeE#o$G1E`u}8pd-s-RBLz7~1QoT_FrPPZPq~E>(TTWBAt=4xMxSzfe zPL&yoo4+B&f#)Pu`u)l`l#%{-dgJbwV%-caB>-FOazN~;%Fjfj?~wD-0$!68opNrx z^dOVOK&w*3eEFug%EA2gr1kGIA*&+<2t z;;wRft9+37tMwj+_;P?}@+tWx;w1VTOg@Ur4PymRosD8dWrZEZ*vjfm6pa-Na7So} zO;oW4Tv}ZgWGxBA-4?iJB$C^*id0rrka$)3Mlc8NtRR(@6$>0FAi7wtMTclkX#QxB zqFiGST-6{Klmq00y{ei#s@g!t?N!Upkr1kRm6yP}5UW_frAEGlj@J>Ey}FuM49k0k zmzA&6p#1VDLKj@JS34?Z6HDcrG+7Q*l!KD1v3VgWs1j5UZkI8$RqZ;-tM)b$Ie95)xbXNj=2| zv>23TP*^J^Q&PqY4Ol9w6#j8q+?cUd)xucS24QRUS!J~F9jKv z_(+eX6B)u%JAGIFi@x0yL#w_~t@?_EzQBsZVyFu56I-dHGk8vVOvsmgTl>)onTr#h zqZ~phJTGgS;$CnXMdZf(^Va8v)#~benM4ZKyBWTuZC;hkdzDCg)wrgrg3n=tlAl-k zb6(}SgK!OrZft(_JngSeV`)CU`kcCkn>t5^r2dax>+kJa$iKRl3fEd@ioqwclHS^; zU*VyU9s{z8T3wOvy-=_2L#gtUEA>C;sz~J7$kn3H{w-IlX28ts_bt9|&`JYk59J3);In1wpaV_9YJo<6f6@k?Gq&6Z~O343TZy6@a_la zG49<{uj~enzp=KkowaY9{>hqIY`gz$#9)#Vz2Gdk-AlaVmb2#=p$|mS;#>Jl5EWGw z1XY!oP?plc%cXgSqG4~>!1)Z^=LWe|%o_4Z0 zIyppg%|BpP@xqakX2&N$dZna*(%t|mO8X0#HSZoy-cfImY5(f9NCdGMZhB80F69>v0rU$s|Q#yV=Fg`zT!IOqo>xtAI%2175&pXpbHIP( zZj-%ggUCI(A-nzM7#o$CUxZ_L)_O*?#<-JJ1s@SkPJjiT?c+}fx-s`Gx!v*!%|39p zD%-UBk|}Uai5pf1c7c< zuGq;IG$Fi1Pd;22s~%@xJB5xl?xJiK5g55klanuY@90R@l6YSfwvy5o=U=$EqWhm* zEN|!H3YhqN7i(z$3zJ9z4Tv+b80%0es7${4mi+nM<9hkr6b zij1*%hQ^}k|BcOSX<;#%L$Fl)|2ovedH5?nr&o1CyaoBhs0*ur5_Dtz5Lny?OZ7u} zVDIj%v#E`HWB=*f)ef-@6xkwKG54yI07fR(9$P z&4=D6cJ|&Ed|aRS;O#gpN9S|}uF1u`-cqCUm3`7#NM~Vb9nO=zhf0VLHFf!-)za{m zXUSjp0A+z|HhaSuuYisJ&};7u-7mWGK1~;lrQZ22un-l(fxXayf(0{vAB0h!ml4% z3R_z&5G@h>=02U-`V?Wnua#XGSpSYN@HiGs!$8L1rL8$AndYgRN+x*fTFG##y9e3{ z43^4wF-<(w1lLBW<-ERcks8jU`elUd!&8@$c##a>x5=P?C#;#$zcZE^?&#Nzt@&^L z6a6}ycv=W z2IC-|-c-EhO*eVyYoS1#%pEZ3XewCv{Dch5UR7QL4qAILxbz1MCZLq&2IBGHnw=+j zcIJt}Z}cON#AfYM464-y?_%)U(d!IsJc-dNx4NuJS=I@}Od?i?Khuwo9gxlL=*RCE z5FM2H29O@wt^N3O1LD}UH~6~)ir9m%^T7iXgD!vFo8^bTe8Ip|ET=CYGbpvgW!Uf= z25X}*sV_k@HBr+RyvA=Il-OT;jh4vY%m}2_Nb~8svFc>TdA(D{FV_>mz~ABV0idifJg|QNriVSS}FCC z($}CI>B`?25yf_PV+a-%N$PP`Tq{i;V>MW%tf2MloAwzBYFV z`}zgmnEQ3%kDbY*#^#6@sMqPg8lZ(hdi7J~>FpOKNv;we`sxO&9C2%HH>;Zykg6vIdY#Ab+;Xx-7}=N9s1n^{LJXC zAv4;cHyz;VW5xt*1=_t=s7d3uj45R|r}E#&Y>N%w-)et=sJrdIlER-In-KfKzE*}m zMBUA>D}|pQJC@y=!iSEFj-BGgcXJ!QWhuO5+*QnHAAfIL57s+{TgE4_$P}KA;`d~p zhvKtje%<(1o-6j4Nk~jUkqo%r{I(U|GrhSrp01{JjYSI{nniBXxx#g(=bkIY`lg)rXyUpZvOj z$>4LR%if89lHY+{-iiN_AI*MA;?Wahr?VuFqFz{kaR{WJorlRd#*A~+}|*|C^$?AkJs~M1vA;$`ucYY@>CZ5 z6i=LTHS4~cFTOm2Z=RCGmhR>Ur`*hz@8W|Br?BgH@%4qNEO!^*U$}4N+MV=qK?OFQ z^a8o5Qg_f6l{OptO{iTH_+7(=z+gON=+^xCmY7{x3-s?p{8sG+pL7zhn4)jGy&=mn#OpZun*4H|>4?>~$BC4&a&Q&W~NLFHo+*Q`7?kNNTWy&d!!7q;z6`g)fu8{N~o!R4Y)XrfRCp;Yh2dv27E*1BAEC_h5kfO5+w zm#YcoZzvUvp5VvNQ|pNBl2N&+#{r=v`u zg$?Cwl*K5&Kq}Xw9P*OOwFBior1L1sSFx+Ps5=zpVQh`UurZp5?NwitH=>-3@(GkB zC_h8F9%T(Sa!;eoz-IC!${8pxp-g+r<%+_raq7P=S0>8EXoKk}{XRhBqP+P-muoA^ zcTny}*%1x$5z1UNg5tnA(J!bZqTG5Kk)za`5IMmp*Py)X6GV>kO_VR84E_|6qa1_M zWW(oHcyLKZc?_i;aG}K4p-ph{bO@em8Mmx-g!x4SX|-unl}Kiu$|x2PiJy&3{4BayO4z6wg-G z@_{HmtmRWtd|Jy(Q6y~Sn^AP%$oHa{zmb2iD2d&^mH)9QKIu+$hB;&_Cm`rQY`DLf z&GfUt2Qr+s+j!RE7{_c>58m%`okr=A(mr4$MpEU#mp$Zi{nUnj z!9%YDe)1zOS7$U}t9-KAE#Cn842;T1^psY5h)(oG`f#p^6rc<4L`$|ZJZces14T}l z(9cir!#KhiYvu7(-A0l@e`CMPl>@SezEWx+`4OO>1HGb+d^zOD$|#G#P;k)YD)d&s zE*Ba|!5Yx3L0^T^V?et}BZhRK9svH#VSe8Yspb=?o_LwRenX7;9I91~{99CmFu=l( z@_;2V=ANi_ILgN_iD$iz@*cn}24>Vzz7W+KRNp?v?^qIVej3#Y$I;d?j<->raopuP z-p0Kn9``PSZh6J!dbUk`yG4EyArpq=Z^JO<-i5DaUpYFH0`&JVbf>maP~dTLBj~|z<2!~n^ihJI2;3gfhk%~krl%#K zr}5)Ueas&b`Cb0O(irn^sJ`_s|7B^sIT771|2-aGf=-R~3ET8`?M zC;2K=>rmC-=l7u6fNIM7{2;1Ls1ALfe~c=90Q%|s{Ew1&M>486Vctphc6OHVRU~5s z=w+ZE@usr|Pq0OxCt;qlwF$=L88&M`_r)UeQXBb0Zh4FH02p?js=sfU*~(9pWrnPn zOPq=lEeqwuHXgGoLEXj&u5zf`>-Vn8Pyy^_5qFi}pw{sv<=3;&G`_n$HtgvL_ZO@d zTAy$w1_{DX32s6fzCoZX!e0;`Lzk8l*AUT|in2o|g5QA*H{pv}^_y-f)>x)by;kvz z>ev~K+$yT|Npy~cVyN=F4L3a9DHp?W!xfq)%U$5GeTby9cOwS^_hF zHPB8-)w+?8%#w}-`l#m30@Cp{oYK*x&s$gmIek2kHXlDl(HtA2mw;qDMZl&GR5#x( z^qB7jQyA65uk}@wlcrwQ&QQrd#gH-evCIcSVNr8(vd?0R*uh;ixH7 z08xzA4$}YuB(j6hW*R7fbmmx3>IMm@Cp!l(OoIiG$vP5chyb!#J!!}mfSp}Sx^o1O z&(5Gvn}!LXkaZ+rM8q&SI-AWQZ6m`*0Vrlqkc?fpy_l5~C654yQo^Q@L!*6fLJ%w1 zvqTyfas_~LW}}G42hIR+EBg|Yl4*iyRnG<6M#@JDLQLqInZ+Lv04+zO&T0%SkbBZA?S`6{ZNf=A~0 zs0qdjhnq80F;nw)`WzYbs|lz;9UUc)dXLF8oC>RnCiCDNQW_a>5e%kT@KiBvf{1D= zM+nT63`3gfZi>J(3y$fgo5-N)1%zQS%|ZsOra8FV6k9$7%$++1JqAsY^u8rsHFv5( z$zsSvir)huD2%?IHmCa3@HZ+`F+P8+%ytmd12TX*R7Io?baqw`2^&(Rm@_m5lt`TK zD0QkOv@=X5FP>MVSi)`dfm7H+AX_4QNR^325)dhXHU9Sih>`@={}*VC79wj@e+Ej7 zZ9aBv%39U`NkAQhlQpXU6l5qip3GqQnd?EaeFT&xPNRCt5v0gsqSW~&m?;aUy}&4@ zL&$+@a=~S$n708FNJNb6BM`QI1W{{;4%CpTHzKi_)=W#C34JzdC(=34inzL48SJyo%N4T3Eu@RCO^)_*d|orMX-^dGRQ zrnf0z3}={AYpvb%{gSjc3u zTS!}0ngwjxin#~)%=3|d#XK99ZJkK{P>t$geqagzl^V>J6O;*n-9^+9F;s^D(QVgJ zsJU7k>VEXZ;Pav1d=QHO>$I2Asiv6ixcQNsZ>ojr^hY8(RTRH2kaGAO7h(?(`VqR- z(`^skMiZCV7X=d8ydPQvpQPFW+|o$NtHdX?h4e>C{H{@jwiZIuM6Od8j8^=jK=e(w z(kL_``8s(j7#vDSCJ7cv!B`?1GG_??l+f3k&@_!GAsS(sDkhcjgf0@X;->f|;pU$q zl+SZ3655pXF@OUyng2?{ONS|Q0glcrfIv=onlhD`aY)PWn$S{+<8ZpfwiuTA$$^1x--+QBt9|7`Ukuv^^Vbafaax4OYX#XJPs%@3pR1gyZY zzh29sX$zOw`lD30?uNI*zuqIHl8YD$f%@dYFxmS$6z zssua@-~x;4A_Nri6h@L;AAxUL9c~v`Dvd$Sxo5dZ{RNgIdy8Y&a*a}bfz6Sr-mzS} z4-S3LuBTN|b3U+KB=ZMmbSIh2OUy`S!zwid>G_%Y2wTnuu)~>OnV8S0yV2tG8}p^n zNU81)<-fbZLe=pO$bT@SAt$R1AiLaPzFGjM70riMM&_I#7lpluM@FtG0l~=j^Q>c< zj9fgQipU>COd6Sfo`sNU&3Uv`Bimq>a6_pE+YTTy<_m`Xr6M)Yvr#fNyGpf42<&A+ zlD?-@q;fCoDO0(lRAg!|8$+35PDLbYzdKR0MXx*HPE^w>)egrGGNY3=m8us2I}XWU zHRngA>M3Ndfr+j|nfnqAf0!9P=R~OzPz`q+Y*?}kRy?eWU~A9}s!I-@?GY%`4d7;QLyySSN#C$$T8N zYEiH>OxAe?8}l<5_N!)U`Y!P@;wb73xX`iv5i#}K{c5^&H1!Ln=RmR zGN4@!Z8y@iU%gVok2^$bJNB!KWCrRSqInOfi)6$b#V6v*A=T)8Q^h>mpn9gDN;r5} z_4M2sF#CcVEK=VE_@W!kSFcA~zvKqTsuKYoArR{?jf%(7)Gw<>%V(=gpt{k`Jzc#K zfgE-FF--~RjX+kb5pgmbVeW}y>p;A~5>c&I6DcU>EYxz4v(;)Z>IRryv~n0)t!Bvq zHMa9WhoR&esY{813UvW|U#kYvf(Pf64o@3Q_=7ER35G3hhGIpDI}B@uva#yv90AuH zS)j4jx!o#M)1+I)BGrZJsLT#<4>mM9$}3chXm`b&)0Mba5i%dUK6=oH5bm;Q;ao)> zu8O`1vPNt8a5aWn5;3Z27&p1@bS+RqUxCtRqw;y(`fx`x9zU(LKt7u(+j-9_>t-l_ zc7j}LcCE6~a{BC2WBOZV`3lT?jp?h4h9mey640(9g3MiUZBn%Cyb& zWG^ZR0i1@%TSgEA#)=Y}gLK~(MIIkA_A>B5N7>GaqZd4Xgn_n&1(dlM* z_&M>@8nLLe)L&@j=wFL6rRS3^*CUV{jIb6cU4I6vI#n1SWEfBLD0>OYEVR_m5G%JZ zz7fW=$@swt$ye5Dylb#wJUh*8oJMW-WrlGpjoIvB63Q2jWsjB6Sj!?fHq7H#=v!b- zKoa@+yTiK7BgMW@l`tquWKFTqSJg@G(W`X38)!AaT*otNBc@UO0qI75t>i*Le`%&j zxDYU0LbGv91gmt&u@>qgiV>0DSPVcqQ3L@cs`p8RYMew&1f^UxP9kv3%BS2H4wXrn?b=5i>vl6q?hYOnZd(=%n?(nLO6EvN&f17pqi0UX6_hChnm zOmIg^Z7Nm$A|ImM(Q`XUymRi7S0zG0O)9`HidCkwF2S?4gDGa;}@ z^_e6PH9+)(#>J!o?`SpWeup_9h#OQ9ndaQ*Fu%{&-7|&t%jTcmlkE5z`u1e>#R@>~ z*}ekro?L1G&ADThWfhd~4;la}bB?sU3f_b6gj-$%?O>!#U$JEq(b6PTWH|}iA)o7! zOR*+@2C%_M?Hr2+=y0$|mowOINr&VM23Tl$g4b^E=P<@*ol~ zx#`N01)9-<)x$MQ-&uNK{Qs>ym>mD& z+#5~V!B}|$vGRO>pImvw*>>P5o_PN-MH9EGGE;N*Z}bOE4E7{5FSK_VWHGBBk6k`CeFW^IR9qi z{F^14yOJ$&0M5h#I1>lpOdNnSIwrF+&jC31d*I{oZ@|vIV?fZHP^@)BO^K_Av$m&H zzeiEhpjtrmbu@?dLM>bgqNNQlWW+((Y9jUkm*RJZXFk}IVU4`*!FXCD*F6}6S55q( z2fHTHahes!X+1GNYIfrG&qq|hsAdiF(S`i{gW*@aC@{txGTrA60j9`dUFdUKfPJ^Y z4?Gz8ybADFHH$oEPJ6%xfG*XCv|+wh5@rBaPpRhDrts+xrOc!mqDju9wAT3F0`h(} zm=d{k3b~^wQ)Pi69FOpPMk4tAY8R=$FyMP6szD7GnI{F;04`UQfDa4$+>6}d zpl_uw&BhCi+4$&6Qw!8B7E1?~GZW3tOM)H)FLMqvb%1*%;SUMOZh8XIFZY#?hxsOQ z^hO{05|3tMQz4Ap*vSCPOjc-JAs3v9&i!Skz96p%k&Q6Iv<-S!BuZ$ysT8!E{HR5+ zT9lb)g1FLWpK!OlEa}mFnNj?o58?uykK8dnJz>0r#d~j5)vXbj6n!b!q3Pr@)*6Rt zK?vW!Bi^zcI=d8%_1-HI9g&?jicnfNkQ}E75+DyULQ~cXUVjb=&*pHfy zcK>}WqfERpDoPG{r=U~Ldd?PSUuZ)Om}k5H3ir(>8^WBPPKM@r++#V8 zo1qq0;4C~gnN=qC<2yn25&s!dG|fF0%snpAg&`PxfwG!qi?IQfERC^PN zIkU}s(VeT^b5fzXE2wv>#<^?0nP#jSH+8yV*#;%SO%N$mhZ~0tFG_0;I2Vk*p`8@e zXt%k!P*|w;FwALp0=!a9ki%!cLwixc84}*(5bn%y8!R$6fjr9%E-)tmyvhw03uosT z&N`fhO2~MmZiG4!ZrBX(=&YMAbt_@DSD|2pnm|p0XB6#g0cJ>FXXBY#ygv;oMSlAV zHOGuYhisvQ)I97~(^u{2R^tP+etp%RvO$WpukU&?#<9*29qJMNiA2M|8=-cT`6x8I zkgaHUL<`J~0_;HPpl2xG`{3XQW^#S~bgAb@k2-o~z$l;(3`YuCXDI)mC$Te!b23{5 z;)jU>bmlWZf-)sEmXXgNB}$L&j1uvYaom?}$^mrRy>~THA2@A1V!oVpAW`9*K~dC{ki> zLVs1u%e6LK7t0s^mb;ZIzDe+Is_^%MvAEvn@%KJ6{Cy76 zQxl|vc6I?RFf~&`*`{v*%`kKo3e7VD;S#<7nXYswfTWscc2C&Pc=R&zFD*j)XBYmZ zb$9EeKHb&rpNYm_cLORiy#rc?G5QKk)ZKd;G%OKUpj~On2%wn!fl&PDFDubJ$`{7a z7hh=sUKzz7+%?Gm9b~jFhG=I0aQ@A%jvamnCP=ed_X20_iIpWlOjLNu9?m=O?lVok zrXLKdDZy-kc3r%t*TrjkUB0Hb(TddZPVm^~qn1Q9AL5O-X-&p7=o1V$!KQs;z@eSO z`E$EFIS#?Tdc=I=9LV5O(V0ZK^;7U`cYt~%ioT?y^V&LsQY2KUeN0fl)q<8EzF^Uf zirQ$C#0BaY_|X_3p<t=00G;8H1$1wkZY)7I7z3LRIacoxJ)t z=U9=8WRVMO$5o0qnf{kIYIo6GDTZLNdNtIf7;+;-!=}VZ&TREn$fX!^Me3J;QhiPd zErse5$fX%tCd2#sx1a9FIz=d2z(C(Yz5{$|0`y5%e0{TgH7q*5s+t$70_Vqj?TrZa z_b0}V7Ri~3$u)rgb}%+Iu)jirK^;+K;J7&0q-J%r_;$p6D%FyT5Weua2tISKFW-DH zG$AZih=hl#T7a)_D_2A)Obm|Z?>;xtCe*=5++BMjEv3<bgFD$OJuS#B!d-xVa=+r5bEDG}~@9=z#+Ko3Hh^Qa?{QWjI(5L?V z3*WE^{~o&jrJlr6BlMsrZd!4(?zci$udF|H#D_TodgwORH(K}EuIoE>o0f1vPtl4B z^_Zi2aETsqt!}gKV}nAi$5~RS9$_8gf%TMW|H^bsS5uK;vJm01(D8zvtX*BGM<3OL zN+x)jIM&X@F+FLzp8TF<^ybqeh|_TFRjb=dFiVZ*6OZ;t8muQguKVAr`?0ie-Pc;E z`;XK6S_kX#9xUH}^r`^caowL=kM-6Aw0(|5ZaUV79aVVdv6L8J>#aX7U#44^>wOev zQm@f_U8~1jw?Wr$s%L}u24@6kJGAyBhP(>u)OCy)1X z2rXB7v`i%}S=04SHSn~j-lIm3s?ob0(4*Ev)k3MNL=Q7-;n(Ov@9B~A^n_k|REgeg zn%>>1r_|`N%k>29#=Uxw=2xP}&(nk9PX91H5;^d{Ry(_@hc5l4XlaCe6KJ+1#Zi{N7J~Xhn{@YT;Ga&RxPce7Y!M_}JW>Nwf0C zPtKh*sUUx{GJMg(Yvx@$;;NFXhA%3byOe96@gU*WvIX-NUMqd8-|*R6s?YHJf?1bO z$(uaf&ae4mey~TytV!@9Z+vcj%NP0P`nIiKJ&SYShyrV4)b_ZfNHq!IW1a!~1i9(Mod%x*kA&#O4_Zr<+3 z$Z{p{A=tIyu=|7Wd$1elaG#4k7&f*8FOGB!OO{OT&otP6h>E-@G)~OLA87y`M0ggYxW9ZSR=Oe#e&h49B+vI{aR#CNCqYMfuV140 zn?LrCX}?*V3JG%QaxtT`rC4Wo*~o3C;pFm_;j#>pTWT zg$`>edSx-c?^3FIh#$L@5Yzr0-Eu?q;aQyhJS?89wExUw4_JcGz3b}u=$}*71N?@c zBOR|8a_>x#M%@oJ?;H5`ANJ5+ppo+STjz6za`)JAhd>_{5&zHdpRPxYXjSZefba6B zx0NB1ptOI57=zvsc~xJ7YPv$I6My7_>Iehh{_V_I1K<8L&FKcd{bTiYWJO)c5C0Mw zeY?Ta{uR+Z{5+`78PxWtkBy`u`a@8uE!(H#D?ahp$UGH~!lH$YuH=4)7+~Przx3^7 z;NQkJjIKjQ5_|LAzeeh#K~2J+l!U5t`6s_d4xDdrw?CpPHSoo>D&X2G3uT>wUpuzG z_ixXb{oit8xi-eC_V95J_7!t$Ct210w#A07#kF?<3^IDQdzQXf z`@U7p2tHRPx!mQ&+Gv~F)3!}wPgK`VvO$#ro~*9D%L{C(u6>I@V}5VAvo^%16>Pq< zb`pVgQdMzH?Ok5rikjNDeAJ<8O>Ky;C?=s0f5HLw$iB6kebvisuOE@J%WL2FRr~vl zcuRscF|{#%AisT9!VlM8>8JMBZf0sN_fv=1GR6PcjAOUj_kqW&K-o0gYNP$3r8_N_ NxUN%cH=ES>{{!b2`BeY_ delta 23143 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 YiweBQdmF%@*SVU_*E8>hc$W6R0J5S!^#A|> diff --git a/Sim04/simulator.c b/Sim04/simulator.c index ba5a2d8..4867aca 100644 --- a/Sim04/simulator.c +++ b/Sim04/simulator.c @@ -341,9 +341,35 @@ Device Input/Device: none Device Output/Device: none Dependencies: none */ -void interruptManager() +bool interruptManager(ConfigDataType *configPtr, ProcessControlBlock *singlePCB, INTERRUPT_ROUTINE interruptRequest) { + // need to check which interrupt service routine that is selected from the list + switch (interruptRequest) + { + case IO_RETURN: + // unset the PCB's state from blocked to ready. + singlePCB->process_state = PROCESS_STATE_READY; + return true; + break; + case QUANTUM_TIMEOUT: + // set something? + // this may need to stop the current process from running, and force a new one... not sure. + return true; + break; + case CPU_SWITCH: + // needs to switch to the next process, schedule to the next process? + return true; + break; + // case FOUR: + // /* code */ + // break; + case CLEAR_INTERRUPT: + // COMMENT HERE + return false; + break; + } // + return false; } /* @@ -610,28 +636,52 @@ Device Input/Device: none Device Output/Device: none Dependencies: pthreads, sprintf, logOutput, ??? */ -void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId) +void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, + int processId, ProcessControlBlock *singlePCB, ConfigDataCodes schedMethod) { double timeDigits; char timeStringy[MAX_STR_LEN]; // char *command = workingMeta->command; // char *argument = workingMeta->strArg1; // int intArg = workingMeta->intArg2; - char cpuOutput[MAX_STR_LEN]; + char cpuOutput[MAX_STR_LEN * 4]; int cpuTime = 0; int *cpuTimePtr = &cpuTime; - cpuTime = intArg * configPtr->procCycleRate; - timeDigits = accessTimer(LAP_TIMER, timeStringy); - sprintf(cpuOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); - logOutput(configPtr, cpuOutput, false); - // run timer for intArg * procCycleRate pthread_t cpuThread; - pthread_create(&cpuThread, NULL, runTimer, (void *)cpuTimePtr); - pthread_join(cpuThread, NULL); - timeDigits = accessTimer(LAP_TIMER, timeStringy); - sprintf(cpuOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); - logOutput(configPtr, cpuOutput, false); - // pthread_exit(NULL); + + switch (schedMethod) + { + case NON_PREEMPTIVE_CODE: + cpuTime = intArg * configPtr->procCycleRate; + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(cpuOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); + logOutput(configPtr, cpuOutput, false); + // run timer for intArg * procCycleRate + pthread_create(&cpuThread, NULL, runTimer, (void *)cpuTimePtr); + pthread_join(cpuThread, NULL); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(cpuOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); + logOutput(configPtr, cpuOutput, false); + // pthread_exit(NULL); + break; + + case PREEMPTIVE_CODE: + cpuTime = intArg * configPtr->procCycleRate; + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(cpuOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); + logOutput(configPtr, cpuOutput, false); + // run timer for intArg * procCycleRate + pthread_create(&cpuThread, NULL, runTimer, (void *)cpuTimePtr); + pthread_join(cpuThread, NULL); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(cpuOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); + logOutput(configPtr, cpuOutput, false); + break; + + default: + // this should never happen... if it does, you'll know. + break; + } } /* @@ -644,23 +694,51 @@ Device Input/Device: none Device Output/Device: none Dependencies: pthreads, sprintf, logOutput, ??? */ -void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId) +void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, + int processId, ProcessControlBlock *singlePCB, ConfigDataCodes schedMethod) { double timeDigits; char timeStringy[MAX_STR_LEN]; - char ioOutput[MAX_STR_LEN]; + char ioOutput[MAX_STR_LEN * 4]; int ioTime = 0; int *ioTimePtr = &ioTime; - ioTime = intArg * configPtr->ioCycleRate; - timeDigits = accessTimer(LAP_TIMER, timeStringy); - sprintf(ioOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); - logOutput(configPtr, ioOutput, false); pthread_t ioThread; - pthread_create(&ioThread, NULL, runTimer, (void *)ioTimePtr); - pthread_join(ioThread, NULL); - timeDigits = accessTimer(LAP_TIMER, timeStringy); - sprintf(ioOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); - logOutput(configPtr, ioOutput, false); + + switch (schedMethod) + { + case NON_PREEMPTIVE_CODE: + ioTime = intArg * configPtr->ioCycleRate; + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(ioOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); + logOutput(configPtr, ioOutput, false); + pthread_create(&ioThread, NULL, runTimer, (void *)ioTimePtr); + pthread_join(ioThread, NULL); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(ioOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); + logOutput(configPtr, ioOutput, false); + break; + + case PREEMPTIVE_CODE: + // need to set this to 'blocked' state here. + singlePCB->process_state = PROCESS_STATE_BLOCKED; + ioTime = intArg * configPtr->ioCycleRate; + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(ioOutput, "%f, Process: %d, %s %s operation start\n", timeDigits, processId, command, argument); + logOutput(configPtr, ioOutput, false); + pthread_create(&ioThread, NULL, runTimer, (void *)ioTimePtr); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(ioOutput, "%f, Process: %d, %s %s operation end\n", timeDigits, processId, command, argument); + logOutput(configPtr, ioOutput, false); + // pthread_join(ioThread, NULL); // not sure if this will be needed... + // pthread_exit(NULL); // this may be needed if pthread_join doesn't produce expected results. + // call the interruptManager here, with the IO Return code. + interruptManager(configPtr, singlePCB, IO_RETURN); + break; + + default: + // this shouldn't happen, but if it does, you'll know... + break; + } } /* @@ -673,13 +751,14 @@ Device Input/Device: none Device Output/Device: none Dependencies: accessTimer, compareString, runCPU, runIO, ??? */ -void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, ProcessControlBlockLL *pcbList) +void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, ProcessControlBlockLL *pcbList, + ConfigDataCodes schedMethod) { double timeDigits; // run over the entire process, running the CPU when a CPU cycle comes up // or a run IO when an IO cycle comes up char timeStringy[MAX_STR_LEN]; - char processOutput[HUGE_STR_LEN]; + char processOutput[HUGE_STR_LEN * 4]; // grab the next operation code for the OpCodeType *workingMeta = singlePCB->nextOpCode; char *command; @@ -701,12 +780,14 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce if (compareString(command, "cpu") == EQUIV && compareString(argument, "process") == EQUIV) { // run the CPU for the required amount of time. - runCPU(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid); + runCPU(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid, + singlePCB, schedMethod); } if(compareString(command, "dev") == EQUIV) { // run IO operations for the required amount of time. - runIO(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid); + runIO(workingMeta->command, workingMeta->strArg1, workingMeta->intArg2, configPtr, singlePCB->uniquePid, + singlePCB, schedMethod); } if(compareString(command, "mem") == EQUIV) { @@ -751,6 +832,17 @@ void runProcess(ProcessControlBlock *singlePCB, ConfigDataType *configPtr, Proce argument = workingMeta->strArg1; intArg = workingMeta->intArg2; intArgTwo = workingMeta->intArg3; + + switch (schedMethod) + { + case PREEMPTIVE_CODE: + interruptManager(configPtr, singlePCB, CLEAR_INTERRUPT); + break; + default: + // this will only happen when NON_PREEMPTIVE is in progress, but + // warnings will result without having this here, so... + break; + } } // display the process exited, if not segfaulted. if(memManagerSuccess) @@ -794,7 +886,8 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) // string variable for nextCode, temp unused // char *nextCode; // string variable for the timer stuff - char simulatorOutput[MAX_STR_LEN]; + int schedulingMethod = configPtr->cpuSchedCode; + char simulatorOutput[MAX_STR_LEN * 4]; double timeDigits; char timeStringy[MAX_STR_LEN]; int processCount = 0; @@ -802,6 +895,19 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) int memoryOffset = 0; int memorySize = 1; + if (schedulingMethod == CPU_SCHED_FCFS_P_CODE || + schedulingMethod == CPU_SCHED_RR_P_CODE || + schedulingMethod == CPU_SCHED_SRTF_P_CODE) + { + // if in a preemptive scheduling method, set to PREEMPTIVE MODE + schedulingMethod = PREEMPTIVE_CODE; + } + else + { + // if in a non-preemptive scheduling method, set to NON_PREEMPTIVE MODE + schedulingMethod = NON_PREEMPTIVE_CODE; + } + accessTimer(ZERO_TIMER, timeStringy); // Operating System start timer goes here, log it. timeDigits = accessTimer(LAP_TIMER, timeStringy); @@ -858,13 +964,23 @@ void runSim(ConfigDataType *configPtr, OpCodeType *metaDataMstrPtr) logOutput(configPtr, simulatorOutput, false); pthread_t runThread; pthread_create(&runThread, NULL, runTimer, (void *)processTimeLeftPtr); - runProcess(pcbPtr, configPtr, pcbList); - // when finished, set to terminated - timeDigits = accessTimer(LAP_TIMER, timeStringy); - sprintf(simulatorOutput, "%f, OS: Process %d set to TERMINATED state from RUNNING state\n\n", timeDigits, - pcbPtr->uniquePid); - logOutput(configPtr, simulatorOutput, false); - pcbPtr->process_state = PROCESS_STATE_TERMINATED; + runProcess(pcbPtr, configPtr, pcbList, schedulingMethod); + switch (schedulingMethod) + { + case NON_PREEMPTIVE_CODE: + // when finished, set to terminated + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(simulatorOutput, "%f, OS: Process %d set to TERMINATED state from RUNNING state\n\n", timeDigits, + pcbPtr->uniquePid); + logOutput(configPtr, simulatorOutput, false); + // this assumes that the processes finish executing all the way though. + pcbPtr->process_state = PROCESS_STATE_TERMINATED; + break; + case PREEMPTIVE_CODE: + // will need to instead, set the next process up? + interruptManager(configPtr, pcbPtr, CPU_SWITCH); + break; + } pthread_join(runThread, NULL); } processTimeLeft = pcbPtr->timeLeft; @@ -973,9 +1089,55 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt break; case CPU_SCHED_FCFS_P_CODE: // TODO: First Come, First Served, Preemptive Scheduling + // try copying the previous code, making sure that if it is in a + // blocked state, it cannot be scheduled, + // if it is in a waiting state, then it can be scheduled. + // can also be scheduled or not based on the previous section of + // code as well. + while (wkgPtr != NULL) + { + // + if (wkgPtr->process_state == PROCESS_STATE_NEW) + { + // set the process within the PCB to the ready state, report in ready state. + wkgPtr->process_state = PROCESS_STATE_READY; + // printf("Process %d set to READY from NEW\n", wkgPtr->uniquePid); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(loggingStr, "%f, OS: Process %d set to READY state from NEW state\n", timeDigits, + wkgPtr->uniquePid); + logOutput(configPtr, loggingStr, false); + } + // move to the next pointer + wkgPtr = wkgPtr->nextPtr; + } + + // reset the pointer to get ready for selection of process + wkgPtr = headPointer->headPtr; + while (wkgPtr != NULL && (returnPid == -1)) + { + // check if the process is NOT running, terminated OR blocked. + if (wkgPtr->process_state != PROCESS_STATE_RUNNING && + wkgPtr->process_state != PROCESS_STATE_TERMINATED && + wkgPtr->process_state != PROCESS_STATE_BLOCKED) + { + // printf("Process %d Selected with %.0f ms remaining\n", wkgPtr->uniquePid, wkgPtr->timeLeft); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(loggingStr, "%f, OS: Process %d selected with %.0f ms remaining\n", timeDigits, + wkgPtr->uniquePid, wkgPtr->timeLeft); + logOutput(configPtr, loggingStr, false); + returnPid = wkgPtr->uniquePid; + } + // move to next pointer + wkgPtr = wkgPtr->nextPtr; + } break; case CPU_SCHED_RR_P_CODE: // TODO: Round Robin Scheduling + // need to FCFS first. however, just rotate through each process. + // maybe keep track via an array or previously used process? not sure how exactly I want this. + // maybe an extern??? not sure how to essentially keep track even when scope is lost here. + // actually, I think a static variable may be the key to solving this. + // alternatively, I could use a circularly linked list, given that proper scheduling is done. break; case CPU_SCHED_SJF_N_CODE: // Shortest Job First Scheduling @@ -1053,6 +1215,77 @@ int scheduleProcess(ProcessControlBlockLL *headPointer, ConfigDataType *configPt break; case CPU_SCHED_SRTF_P_CODE: // TODO: Shortest Run-time First Scheduling + // may be able to copy the same code that I've used above, just + // with more restrictive rules similarly to the FCFS described above. + while (wkgPtr != NULL) + { + // + if (wkgPtr->process_state == PROCESS_STATE_NEW) + { + // set the process within the PCB to the ready state, report in ready state. + wkgPtr->process_state = PROCESS_STATE_READY; + // printf("Process %d set to READY from NEW\n", wkgPtr->uniquePid); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(loggingStr, "%f, OS: Process %d set to READY state from NEW state\n", timeDigits, + wkgPtr->uniquePid); + logOutput(configPtr, loggingStr, false); + } + // move to the next pointer + wkgPtr = wkgPtr->nextPtr; + } + + // reset the pointer to get ready for selection of process + wkgPtr = headPointer->headPtr; + // load in the first process time + shortestJob = wkgPtr->timeLeft; + // move to the next pointer. + wkgPtr = wkgPtr->nextPtr; + while (wkgPtr != NULL && (returnPid == -1)) + { + // check if the process is NOT terminated and NOT blocked. (can only be waiting) + // now, ALSO needs to check which process takes the least time. + if (wkgPtr->process_state != PROCESS_STATE_RUNNING && + wkgPtr->process_state != PROCESS_STATE_TERMINATED && + wkgPtr->process_state != PROCESS_STATE_BLOCKED) + { + // check to see if the working pointer job is shorter than the current shortest job + shortestJob = findMin(shortestJob, wkgPtr->timeLeft); + // check to see if the shortest job time changed, if it did, change the process number + if (shortestJob == wkgPtr->timeLeft) + { + // change process number, or leave it unchanged. + shortestJobProcNum = wkgPtr->uniquePid; + } + } + // move to next pointer + wkgPtr = wkgPtr->nextPtr; + } + // check the number of processes, if there is one left, then + wkgPtr = headPointer->headPtr; + if (processCount == 1) + { + // find the last process that is READY but not TERMINATED, set it's PID as the return. + while (wkgPtr != NULL) + { + // + if (wkgPtr->process_state != PROCESS_STATE_TERMINATED) + { + // + shortestJobProcNum = wkgPtr->uniquePid; + shortestJob = wkgPtr->timeLeft; + } + wkgPtr = wkgPtr->nextPtr; + } + } + if (processCount != 0) + { + // printf("Process %d Selected with %.0f ms remaining\n", wkgPtr->uniquePid, wkgPtr->timeLeft); + timeDigits = accessTimer(LAP_TIMER, timeStringy); + sprintf(loggingStr, "%f, OS: Process %d selected with %.0f ms remaining\n", timeDigits, + shortestJobProcNum, (double)shortestJob); + logOutput(configPtr, loggingStr, false); + } + returnPid = shortestJobProcNum; break; } // return returnPid diff --git a/Sim04/simulator.h b/Sim04/simulator.h index f55b9de..b31aa41 100644 --- a/Sim04/simulator.h +++ b/Sim04/simulator.h @@ -25,6 +25,13 @@ typedef enum{ MEMORY_DEALLOCATE } MEMORY_SIGNALS; +typedef enum{ + IO_RETURN = 0, + QUANTUM_TIMEOUT, + CPU_SWITCH, + CLEAR_INTERRUPT + } INTERRUPT_ROUTINE; + typedef struct ProcessControlBlockStruct { int uniquePid; @@ -143,7 +150,8 @@ Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -ProcessControlBlockLL *fillProcessList(ConfigDataType *configPtr, OpCodeType *metadataPtr, ProcessControlBlockLL *headPointer); +ProcessControlBlockLL *fillProcessList(ConfigDataType *configPtr, OpCodeType *metadataPtr, + ProcessControlBlockLL *headPointer); /* Name: findMin @@ -181,7 +189,8 @@ Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId); +void runCPU(char *command, char *argument, int intArg, ConfigDataType *configPtr, + int processId, ProcessControlBlock *singlePCB, ConfigDataCodes schedMethod); /* Name: runIO @@ -193,7 +202,8 @@ Device Input/Device: none Device Output/Device: none Dependencies: ??? */ -void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, int processId); +void runIO(char *command, char *argument, int intArg, ConfigDataType *configPtr, + int processId, ProcessControlBlock *singlePCB, ConfigDataCodes schedMethod); /* Name: runSim Process: primary simulation driver