From 9f4743350195ffba9ed34d71d8c5425f02ed3f8f Mon Sep 17 00:00:00 2001 From: peteraa Date: Mon, 29 Jun 2020 16:17:24 +0200 Subject: [PATCH] Stuff I forgot to commit. --- Images/BranchPredictor.png | Bin 0 -> 44133 bytes TODO.org | 57 ----- branchProfiler.scala | 0 src/main/scala/main.scala | 7 + src/test/resources/tests/programs/constants.s | 15 ++ src/test/resources/tests/programs/halfwords.s | 18 ++ src/test/scala/Manifest.scala | 12 +- src/test/scala/RISCV/DataTypes.scala | 12 +- src/test/scala/RISCV/branchProfiler.scala | 147 +++++++++++++ src/test/scala/RISCV/cacheProfiler.scala | 204 ++++++++++++++++++ src/test/scala/RISCV/testRunner.scala | 94 -------- src/test/scala/TestUtils.scala | 4 + src/test/scala/chiselTestRunner.scala | 2 +- theory2.org | 194 +++++++++-------- 14 files changed, 517 insertions(+), 249 deletions(-) create mode 100644 Images/BranchPredictor.png create mode 100644 branchProfiler.scala create mode 100644 src/main/scala/main.scala create mode 100644 src/test/resources/tests/programs/constants.s create mode 100644 src/test/resources/tests/programs/halfwords.s create mode 100644 src/test/scala/RISCV/branchProfiler.scala create mode 100644 src/test/scala/RISCV/cacheProfiler.scala diff --git a/Images/BranchPredictor.png b/Images/BranchPredictor.png new file mode 100644 index 0000000000000000000000000000000000000000..03641dca5ea7eea7b9109860bd72732ccf8704dd GIT binary patch literal 44133 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

Zhcv>^5sw+`&eUOCFA# z^+WD`>i#j&2Nz+k0wt=y?DwBP|1mQYhP@H7Dck(bKL3XIk3wq}`CwvV54Hb(rl0%> zdhzbvF9Z3~nMUnf-#(`$yNsSDoyculwiN1Storw8`Y}t0#uT*raa6ww(>MK5=>x@Q zWmS$~e9d`DI!Bf~y|?3pk$}7f@n0>4yO?qHvMI{_Z{A%gWi5e8LGkcRMM$7nU0BR z#q}uf*J=!3q>3?@brFO3w&-l3!X-Ze?Ty8w&vgwu=5Ay`7mVi)hLiJocGu;H`f;<|-7&gX)Jh1Qnkha}TSgnn z4R4$>m?V|fjMUTd%`0OhLdx1l2vQUDN6oxJHnscuh9fRRV(kc%0c+RpE-+S(CH0F4 z7vx#;@@)^M8) zKG@;{i&ZjNd3>(#u)3R@zkIzYiZY zd-s0&qui+cKu(j4z zCEM*7hu>P##K}F&-?ee6e8IW={Ctd1*z7bFXxM8uE{yKBt3Y=;X1p}N2r$NK@sRYv zbS>j2_Ls%+%01WjR%uOW`6iblvl@Z>&Qa4}wvzdG;18KD<}@&b(J1RZ`)v2PC1YPf za3rQtfq_OcR6}9-2+R5Tg=gs_(G}{wb6w#~j|Ik}rt&r4OghI4i^s7{&R>K;#fcfzaI$!Vc@p*JHoP?zXM zHfOGNpH2b)}w=seO<6%tEqT_2N%;!j0IbZMJzd;BXd zfG7k`KTgU!A$m)`Hnk#Vyj=h3MCA|WkuZsw8QHPGtP=wR6@pxqABU) zV~LQZnUNd4AXo7^K+TI()#8E9Ue?rneE(iuMa6IKT(QFvgI|0({gVgz2I?!VVhTXe zpw^ptI}{Ujm19FgLkV=Zl$+-79zNE)>FiIfr1Kr;4YhaQ>8-9F)c$L^(iWp+M_Neu zP5EF&tE`MOo207huBqQD8d_?MH_=jtMN1|?uM2R6YPuz$k3?iUPFF0O?;bI&wcbY^ zyP$?NlV>zGE;=b61l);(&|eFu#SDGN>0{TVTjy)OoV~bv=T0_e10f%-BO#R)Y!%RI ziW%76osT3YIx=i?nNdrK>7H zuN|YOX9u6ETUzr5dDX8MSwi4-;Gk8rndimNA3e&cI)(g+6q4m$IX(V_y?2?hSXvO@ znU5$HX7GOJg{B%5s^e1wzPc;Nj$nKYZ%-+0NW)SFB?}n$Uz07y_O7Df1480wAS&>h z7EhE=mPRju+8ig8+9~H{PtHCS_`Igzb=@s#BPH3-IE#I)xBXyj1f`o^2QK5luN3b* zgQ~@*_cOiMjJC>+{Y!8L)Q7*q{YCVs%TrKkiWt#*IS6Tnd`Zd=gFhQj>=6H#UN4D& zU4!}cDU?B8$L0Ht%iU^p4g0?p$G-hMOvq~HI3P+F^J%7H}QI8at zVHs9NY9Pgc1J+7A)6$M*WT0Zg^kl`th3`LodUr|%& zAc1(2Bd|o@$&Oukt9N~ioydc3)FYk@P7V+Z>4&>4%!Y$AXa{m*1XBQ6D-9%twHcqp z>V-=!{%Eslz*Q6k2&t}I0c&|q8y2?~v zsBHWBe*FTl53-*L1m%lQk4CuwG)ve>J-#n6xWSifZHs|ipzirBTzG_8>`-Nq1Zrrs zAkBuy`H2=TT|J#;?^tBG$^HKMlY120kvWPu%Yd3Mk~~3%DzHCSbyr80+2U&2+Fp2i z6{+Ck&C=n}H&QDH4P(3waI_F;K7EgVq?mA)NUYMQ54h*ytgLx{et3IZZ3;@vCw(ZY zsDQ!)KzcRkszLGDM-#+alrRr~nfDXM+sWNaQY!74LQU7`|LSH)QnKB1uZ`Qc-??*BnQ~H(T8SIme|;pwSif%FlvGo($1^@;MT9`}fj&$&M9lQ5g!GEb zv!ZS$9UA&QH;Ri{=fVxbEyuH+xt!|ut}9o5fh>257#^7sMqNV|h-k>;{1O~~1W~|T z4GX+^c^k9>+VnSypH`8NX5UdBNS&5iTp&@IP0;5>=I6hxu7++?LD!R%VgCa!|3RM$ zCsb_;*If-HG1bW_1a&>LN*H*-`>d?IaroQh1rLCgq3hM9<~`Gv%TXBlUTnrIei6HV z%!x9qE08As<;g#NDlaJx;0$vYV?t%E{JK4^DGqY+wS zzpunaQy}CK^0vr+eDtH%<0xMy6xaZj^yMgZ;0VKGpu_5CmNqFH7iZ`$y0SJ|73?JI zDcuxfb{sfBry6-Y0}TcH0NF@mxHFXXR0+Q&Dt+^+c@P_!oIsd;zg$skz;MAzgQ&nt8s>}uXQ2PDPfi4%rHCo@(R`zauUE4y~7zO!#! zljP?gH&+A8s#el2G;UOJ@Ds)cw&^O#vMHob%VoN_&z$)i_zTv^cBeroA%GVSQ%H7fDt%%KYnZK=f9)C<&oDp$ zCH>`jHcEDxE;JCt?_TAC;7n4m@+jzMxhtWg4%A@ ztQuOM=30u|93E9v09K7td-Z+b;U4dr{;xqNEc|B&W^1Yrsk=p@$8tvW8xk@u_49qn z!6qhH4KBiDV)_w!MgmEOxf%AZJULzt$0gl*B15P49tB5;Tkp|}1BCebL0|@@oCviB zxNt=8d%y(K4}DQhxOK3GP8ggHtI=(p$Abx(c%RtW+b>?S6cc=n%|g}2@*?6jmya%bI?L5{6$4<<=rJFYLk}afCVz?GOkT&~ z!wWbu)#CT=*~7!)JiyaSAT?)a^Tn(YEN2r3__iyhGYMeO4!LvVecE+p4^j&qJNDuA zYrx7E@e8!f!{~}p{1l&2 zqZrywlNIoiPsVs6X;4~l|BVhq_s)=QUTKwpH8%^C4b8{M=x%xW2~s*2eH_rk9mt}s zGb&PMFRm<3+OY#P{(EyXq@j;tnXjN!zJHJMlhpw|KjPI;L~~SEECvDrf=<;gZ97eIWF>&=V`D!hFL`wnUbWV2!#LVI+1a=9;qcOF1Xa0 zlFAS)!zUu=0VPGw57tJQ5IZsH*^`d%9Ww2g2r5^vwnOR6mCao_eBN2(>4(H7xslru z}KpV81iaFS9OS(6S)8GavQMe(yGE#=nCB#aktS zvi$%EAqVrS`FGh!A!X*xGmP+h`mS%UBp&$*LQ1NutINZl3~UVvg%%7u98a3?0o@u$ zFc_FWCrQfAzIFRHR*Xc`txkjD?GDm{V>xnA5ybZGyW8-MDR7DjejHUk8h}Hje9)XZ z#BSd{di{RiEdoIcOrCKBh`ZZ%4psi|kjPxcbTR!0g<`@xmGTeLUHI zbav@s_THN}BYbaeiBKwgnf>MJh6xV`o4LmPDGjy6mjqQ4Rwe>~neni;RO3k0z-^ys zdu_S5AkW=MXBm_a7kzjVywW0p1E;BF+Hc+f?k*T@{nZ{CoR?n<_fe1mN( z=LP#5=7N7feb2Gx>#ghyi^#E(pp;Pl&_s>8dqlA}+5Y^zYENTzQ-hddQhl3DCI2K| zo@qDJHA(cw`#uOCUu2A!CuaYq0L-USHOJX8cyIWu2rE&`ITk-mmEw9)F051;@vcLy z0IX|0W_&cvRY=t&L#M|~tmdP%w&i8M(MGqUfd)Mw+QG~M6F`%kqfy%B`B+gtG$v+V z%?>+Vu}?Scb$ez&VbD>M{R>!%jelZYy4qzl?tqfkJ{r>7MSoZuk_MDgd?fCGwt)ZJ z>8_F0YRV{BbD?mtW>)O}yTa05HCbvvCQcGb(9!^GZ0UkegOu6{s zz{Ii7YqgCd!+J`RAInCH6mPk!S}W;15C0jp%J7mit<3w9`|QJK=Ng7jg-BC3LpNEU zdsS{2qmWU4JS+dUdF2kelAO~F=A%JpH9x3&wA|+tHrbP(OWi&Bmol)ft8=`LXHt4? zn(l@fPwFhUz3ppUJgR^6{npH?ZbNo0AqV1&n?IlO&F`a++=Q-P!*!BdDgKGM3c;!@%{|o3LEz%CNM~U+?qm;#V)|#_W%XwTar|!*GgfK1*MXq51ufm1P9=61{e>)(zG9gw z(Sp%LpF^b)&w)MBAJn~h^EgO-RiWH2;{i``L+gKoeoEtY1hGbH|8<=Y`fTmGtE->o zhKT6-DZg%<7n?6JcaevVap*=Br zu8bLp-jJYWcc}_VYK>0EZGI82-lOu{w^eVl&dfNG9Pn(?%90n_CRkzsq^@2B|DSNv z-3@g0#*XeCSH{jc!a;Q8NK9p7qTI@_+iyfYRk^(f$$mit=A>DC!=o#+PC2*^!kaD& z0dntCGfq5NlDss_`G{@7Ry1;xLz9Z$rc7lm5ijuUuwQow=Rclx0_-E=tE8T_` z^oX19@%_GZ^raN3?rPFGH4gn!%I!l(bWOfvg7)uki2JPJUEb8cw%ovH)sSr)KG|3% zW!)ia;oGH9>@Z;hxS!Q@A5)`KVhouY8n8R${auTdGNM1zHrZsl9rMgweq#QMqr07M zBo2M++M4+0UNC4w_m9e|h`~ljD6ae}v2IGr+}3{;?#b4fD4ZOEtvb2~SC6uo;f^W& zmUfkY>76*|%$eiIZECw{b5w=NtSj>oiMrjIXlFgWTub(#xJcwf&sl9;Uj{!c+tsW- z-*M^k<^N32Y6S&3)~88~p9n8Y>x2^oesE$)9OQ_Azf2QH-DGGNX;(JJ3|AG2oD%48 z931f9lU|-oeJ)v$2Z4#b8*9^B?MQ%>tC&c1DU3pt$#%Y54;pDcZz=5X?i*=KqP5NW z2$?QPEQj9Xjcao{r1*tQI%ozH(9DzCq}Ap+qUv>e?Y9Rq2MrD1CvCoFi|2#uF{`b2 zM&GcWE)toJ2HFn`yUx(%1r972x@fx?F14Cw z;cxjVgD09{bSBJa|5J=R2~DBu>go;A{b9Ak;XS$N%-Atw^!NYlW+x>Q^}-*RWP)B+ z?{(uRZV$1r#MU)o`}ak&n*?>-nKRcJ_&!NW@CzTZi+`MWBHiGS>2mam(2zlc5vlWd z$xphT!0XJ*>MnOvVU$+y-l&$X(#()KyV5?btxa^>#`&bb>kefH`5+Zmua1Ye=LD`@ z+t%Jb?d32r;YxNy>6O8nKpod$Pd<8vs(`-1r3MRBooKDVOvu8iN6ZrhS4em)l%Gpi ztQfh)1)kfC6EDGFu}#F)9ceRr1#TZR3cw*=Z#xTjeS(7n6Oohk)`5!ApCU&B(9s?f zxJ9pwL`4wkzPL0DdL$J(UAL0oSMu_P>*$1k@BctgBnmf(I2niM z->RxodGI!w0)7?{zzTsDgi0B9Xny|w2k$B1_UmjR^3an2qSGoJKW-duZR);a+x1{> zvzEyV{I#Y63*WnEA3KOXxN@I9@eRRPX21;r!=N@!_NpZNudBn&Xj4rN%0W`EmDf9V zmp0JXtuvnkzzSugp(X4Slbfg_=_)Vk+Ey7pd6-Bv=;H6_xv4xQY`{H@6JukGw*GjF zQZ|T_hRz!Y>%+KKp+l^wh-(W@@1+g-UvG3#o1*-cI7^##QRQ~|#@59l>=B;5=D2^9gx$VV-8+PM z5;h_6*peYnX*uj_yT#}x_j_uo%1{A)WVm9asNfTw?c(k}WLqsBx zVKfoWN++rOZMkREeLa`ab5v|v(2Q8NzS*&82;S4Mmzd^gfj+6v%4?ZVmej8QZ|HVC z%5_M}A&`us4(3!Z`wQS!0kUamq^75LJ(=m9-__X;1c$bEq{>8Jvovnd9v&8GEiV~z z+EoNToL&H60$GEe#PAnN|J-#PE~Wh-W6JR3#g0>_#ssO0MAJNfRDQsxhoZ4j<;|R4 zBch5p-We2dG=Wj1v^IW!`z9wVn{)2miz{mkQ_2y+&+_r{VUL|UHFTSUZTocUV)SN> z7YNHdfAa*O-~t5qWJv!0rhlEJ?%lud{MUUA8u#nh%#%j)WTmtzC1s|kr&jze8it67 z(>MOoOe|&W0S7EhHoG-m_==FRq$I29S>Cn>DpJS_T|BVn_#Fv(k?6dJw)QSZJzg`X z)4LQ8Wdj@+x8kW85RixNbhMFF-6<(ipCFNUahs#azE*B5Fs*0ZyJA56rUPxn646#O>w@6Zkkd6#Ra*L1VM)m9aj@L?Wy6 z>*BD|{lNTzGx@)2CiL5A_jAAQc0Ky28=`H#-5>iU<8(we*Z|B6d>G>0d0FAXNn3{&W3C+`P9r2(mHZ znSMOgObv0yMc$+VR?CSWSdie z4|CI4xjj0vX->Ogx4^oOOG#~#-1g2rQU{a)JknrC8941dH)kcMU~4f^M%AoT2j-3w z`6yUufi7OQEReOlN|k9?XloC88ZXRsf7cOM=fpi7KO5E+dTe^z9m6wD&dz(@9qzV7 z@Uo+#q$B_bZJlhfEKE#f<<-2t0|7DxDP!K`qYpnF7pX(ak#^ufC_P1jlh*J@0V+8{ zhR_S|8883_olG{#5B%|N%4)G`Ij)Y|5uLOm;+SuihO~IdI^Dm|ew}>QBM+k)^aKf? z)2BbC&F&IjfBjVs71vaY);9!C_BQg0BSVE1C-V7-YKNDE-#7zEE_)^ny?MIJ@F|Yr z;KHm-|E>va)z`#@hWoZ?O)_3~rBkp&Y4$q_g4mYc@F= zXL7?CiQE3ZnsCl&k-Den$9F?&LxxqCvnm zL4a6ZP5`L}GK$o3$vz{~?aC>)V}I(RdI0Tm6q>> bitsRight - // say(i) - // say(rightShifted) + rightShifted + } + + // To get the entire word call with from = 31, to = 0 + def bits(from: Int, to: Int): Int = { + val bitsLeft = 31 - from + val bitsRight = bitsLeft + to + val leftShifted = i << bitsLeft + val rightShifted = leftShifted >>> bitsRight + rightShifted } } diff --git a/src/test/scala/RISCV/branchProfiler.scala b/src/test/scala/RISCV/branchProfiler.scala new file mode 100644 index 0000000..20d4235 --- /dev/null +++ b/src/test/scala/RISCV/branchProfiler.scala @@ -0,0 +1,147 @@ +package FiveStage + +import org.scalatest.{Matchers, FlatSpec} +import cats._ +import cats.implicits._ +import fileUtils._ + +import chisel3.iotesters._ +import scala.collection.mutable.LinkedHashMap + +import fansi.Str + +import Ops._ +import Data._ +import VM._ + +import PrintUtils._ +import LogParser._ + +object BranchProfiler { + + def profileBranching(testOptions: TestOptions): Boolean = { + + val testResults = for { + lines <- fileUtils.readTest(testOptions) + program <- FiveStage.Parser.parseProgram(lines, testOptions) + (binary, (trace, finalVM)) <- program.validate(testOptions.maxSteps).map(x => (x._1, x._2.run)) + } yield { + + sealed trait BranchEvent + case class Taken(from: Int, to: Int) extends BranchEvent { override def toString = s"Taken ${from.hs}\t${to.hs}" } + case class NotTaken(addr: Int) extends BranchEvent { override def toString = s"Not Taken ${addr.hs}" } + + val events: List[BranchEvent] = trace.flatMap(_.event).collect{ + case PcUpdateBranch(from, to) => Taken(from.value, to.value) + case PcUpdateNoBranch(at) => NotTaken(at.value) + } + + + /** + * This is a sample profiler for a rather unrealistic branch predictor which has an unlimited amount + * of slots + */ + def OneBitInfiniteSlots(events: List[BranchEvent]): Int = { + + // Uncomment to take a look at the event log + // say(events.mkString("\n","\n","\n")) + + // Helper inspects the next element of the event list. If the event is a mispredict the prediction table is updated + // to reflect this. + // As long as there are remaining events the helper calls itself recursively on the remainder + def helper(events: List[BranchEvent], predictionTable: Map[Int, Boolean]): Int = { + events match { + + // Scala syntax for matching a list with a head element of some type and a tail + // `case h :: t =>` + // means we want to match a list with at least a head and a tail (tail can be Nil, so we + // essentially want to match a list with at least one element) + // h is the first element of the list, t is the remainder (which can be Nil, aka empty) + + // `case Constructor(arg1, arg2) :: t => ` + // means we want to match a list whose first element is of type Constructor, giving us access to its internal + // values. + + // `case Constructor(arg1, arg2) :: t => if(p(arg1, arg2))` + // means we want to match a list whose first element is of type Constructor while satisfying some predicate p, + // called an if guard. + case Taken(from, to) :: t if( predictionTable(from)) => helper(t, predictionTable) + case Taken(from, to) :: t if(!predictionTable(from)) => 1 + helper(t, predictionTable.updated(from, true)) + case NotTaken(addr) :: t if( predictionTable(addr)) => 1 + helper(t, predictionTable.updated(addr, false)) + case NotTaken(addr) :: t if(!predictionTable(addr)) => helper(t, predictionTable) + case Nil => 0 + } + } + + // Initially every possible branch is set to false since the initial state of the predictor is to assume branch not taken + def initState = events.map{ + case Taken(from, addr) => (from, false) + case NotTaken(addr) => (addr, false) + }.toMap + + helper(events, initState) + } + + + def twoBitPredictor(events: List[BranchEvent], slots: Int): Int = { + + case class nBitPredictor( + values : List[Int], + predictionRules : List[Boolean], + transitionRules : Int => Boolean => Int, + ){ + val slots = values.size + + def predict(pc: Int): Boolean = predictionRules(values(pc.getTag(slots))) + + def update(pc: Int, taken: Boolean): nBitPredictor = { + val current = values(pc.getTag(slots)) + val next = copy(values = values.updated(pc.getTag(slots), transitionRules(current)(taken))) + next + } + + override def toString = values.map(x => x.binary(2)).mkString("[","][","]") + } + + val initPredictor = nBitPredictor( + List.fill(slots)(0), + List( + false, + false, + true, + true, + ), + r => r match { + case 0 => taken => if(taken) 1 else 0 + case 1 => taken => if(taken) 2 else 0 + case 2 => taken => if(taken) 3 else 1 + case 3 => taken => if(taken) 3 else 2 + } + ) + + events.foldLeft((0, initPredictor)){ case(((acc, bp), event)) => + println() + say(s"total misses: $acc") + say(event) + event match { + case Taken(pc, _) => say(s"taken at tag: ${pc.getTag(slots)}") + case NotTaken(pc) => say(s"not taken at tag: ${pc.getTag(slots)}") + } + say(bp) + event match { + case Taken(pc, _) if bp.predict(pc) => {say("HIT!"); (acc, bp.update(pc, true))} + case Taken(pc, _) => {say("MISS!"); (acc + 1, bp.update(pc, true))} + case NotTaken(pc) if !bp.predict(pc) => {say("HIT!"); (acc, bp.update(pc, false))} + case NotTaken(pc) => {say("MISS!"); (acc + 1, bp.update(pc, false))} + } + }._1 + } + + say(events.mkString("\n","\n","\n")) + say(twoBitPredictor(events, 8)) + } + + + true + } +} diff --git a/src/test/scala/RISCV/cacheProfiler.scala b/src/test/scala/RISCV/cacheProfiler.scala new file mode 100644 index 0000000..1765626 --- /dev/null +++ b/src/test/scala/RISCV/cacheProfiler.scala @@ -0,0 +1,204 @@ +package FiveStage + +import org.scalatest.{Matchers, FlatSpec} +import cats._ +import cats.implicits._ +import fileUtils._ + +import chisel3.iotesters._ +import scala.collection.mutable.LinkedHashMap + +import fansi.Str + +import Ops._ +import Data._ +import VM._ + +import PrintUtils._ +import LogParser._ + +object CacheProfiler { + + def profileCache(testOptions: TestOptions): Boolean = { + + val testResults = for { + lines <- fileUtils.readTest(testOptions) + program <- FiveStage.Parser.parseProgram(lines, testOptions) + (binary, (trace, finalVM)) <- program.validate(testOptions.maxSteps).map(x => (x._1, x._2.run)) + } yield { + + import TestUtils._ + + sealed trait MemoryEvent + case class Write(addr: Int) extends MemoryEvent + case class Read(addr: Int) extends MemoryEvent + + val events = trace.flatMap(_.event).collect{ + case MemWrite(addr, _) => Write(addr.value) + case MemRead(addr, _) => Read(addr.value) + } + + + class CacheProfiler(setCount: Int, setSize: Int, blockSize: Int){ + + // If we set counter to 0 we risk evicting the first allocated block. + var counter = 1 + var misses = 0 + var mostRecent = 0 + var wasMiss = false + + implicit class AddrOps(i: Int){ + val blockOffsetBits = blockSize.log2 + val lineBits = setSize.log2 + + def lineIdx: Int = { + i.bits(2 + blockOffsetBits + lineBits - 1, 2 + blockOffsetBits) + } + } + + + case class CacheLine(tag: Int, lastUsed: Int){ + def matches(addr: Int): Boolean = List.fill(blockSize)(tag) + .zipWithIndex + .map{ case(btag, idx) => btag + idx*4 } + .map(_ == addr) + .foldLeft(false)(_ || _) + + def renderContent(addr: Int): String = (addr == mostRecent, wasMiss) match { + case (true, true) => Console.RED + addr.hs + Console.RESET + case (true, false) => Console.GREEN + addr.hs + Console.RESET + case _ => addr.hs + } + + def render: String = { + val blockContents = List.fill(blockSize)(tag) + .zipWithIndex + .map{ case(btag, idx) => renderContent(btag + idx*4) } + .mkString("Contents: || ", " | ", " |") + + s"Base: ${tag.hs} LRU: $lastUsed\t" + blockContents + } + } + object CacheLine { + def truncateTag(addr: Int) = addr - (addr % (blockSize*4)) + } + + + case class CacheSet(blocks: Array[CacheLine]){ + def lineIdx(addr: Int): Int = addr.lineIdx + def contains(addr: Int): Boolean = blocks.map(_.matches(addr)).foldLeft(false)(_ || _) + + def updateLRU(addr: Int): Unit = { + val idx = lineIdx(addr) + val next = blocks(idx).copy(lastUsed = counter) + blocks(idx) = next + } + + def render: String = { + blocks.map(_.render).mkString("\n", "\n", "\n") + } + } + + + case class Cache(sets: Array[CacheSet]){ + + /** returns the index of set if hit */ + def checkHit(addr: Int): Option[Int] = sets + .zipWithIndex + .map{ case(set, idx) => Option.when(set.contains(addr))(idx) } + .flatten.headOption + + + /** Updates the LRU counter */ + def updateLRU(addr: Int, setIdx: Int): Unit = sets(setIdx).updateLRU(addr) + + + /** Gets set with least recently used */ + def getLRU(addr: Int): Int = sets + .map( set => set.blocks(set.lineIdx(addr)).lastUsed) + .zipWithIndex + .sortBy(_._1) + .map(_._2) + .head + + + /** Entry point */ + def handleAccess(addr: Int): Unit = { + mostRecent = addr + counter += 1 + + checkHit(addr) match { + + case Some(setIdx) => { + wasMiss = false + updateLRU(addr, setIdx) + // say(s"${addr.hs} HIT") + } + + case None => { + val set = sets(getLRU(addr)) + val nextTag = CacheLine.truncateTag(addr) + set.blocks(set.lineIdx(addr)) = set.blocks(set.lineIdx(addr)).copy( + tag = nextTag, + lastUsed = counter + ) + misses += 1 + + wasMiss = true + // say(s"${addr.hs} MISS") + // say(s"BLOCK ${addr.lineIdx} IN SET ${getLRU(addr)} EVICTED. BYE BYE") + } + } + } + + /** Pretty pictures! */ + def render: String = { + sets.map(_.render).mkString("\n", "\n", "\n") + } + } + + object Cache { + def init: Cache = Cache(Array.fill(setCount)( + CacheSet(Array.fill(setSize)(CacheLine(57005, 0)))) + ) + } + } + + for{ + sets <- List(2, 4, 8) + blockSize <- List(4, 8) + lines <- List(2, 4, 8) + } yield { + + val myTest = new CacheProfiler(sets, lines, blockSize) + val myCache = myTest.Cache.init + events.foreach{ + case Write(addr) => myCache.handleAccess(addr) + case Read(addr) => myCache.handleAccess(addr) + } + + say(s"sets: $sets, lines: $lines, blockSize: $blockSize yields ${myTest.misses} misses") + } + + // val myTest = new CacheProfiler(2, 4, 4) + // val myCache = myTest.Cache.init + // events.foreach{ + // case Write(addr) => { + // say(addr.hs) + // myCache.handleAccess(addr) + // say(myCache.render) + // } + // case Read(addr) => { + // say(addr.hs) + // myCache.handleAccess(addr) + // say(myCache.render) + // } + // } + + // say(myTest.misses) + + } + + true + } +} diff --git a/src/test/scala/RISCV/testRunner.scala b/src/test/scala/RISCV/testRunner.scala index 3d9d60c..f59dcf6 100644 --- a/src/test/scala/RISCV/testRunner.scala +++ b/src/test/scala/RISCV/testRunner.scala @@ -101,98 +101,4 @@ object TestRunner { successful }.toOption.getOrElse(false) } - - def profileBranching(testOptions: TestOptions): Boolean = { - - val testResults = for { - lines <- fileUtils.readTest(testOptions) - program <- FiveStage.Parser.parseProgram(lines, testOptions) - (binary, (trace, finalVM)) <- program.validate(testOptions.maxSteps).map(x => (x._1, x._2.run)) - } yield { - - sealed trait BranchEvent - case class Taken(from: Int, to: Int) extends BranchEvent { override def toString = s"Taken ${from.hs}\t${to.hs}" } - case class NotTaken(addr: Int) extends BranchEvent { override def toString = s"Not Taken ${addr.hs}" } - - val events: List[BranchEvent] = trace.flatMap(_.event).collect{ - case PcUpdateBranch(from, to) => Taken(from.value, to.value) - case PcUpdateNoBranch(at) => NotTaken(at.value) - } - - - /** - * This is a sample profiler for a rather unrealistic branch predictor which has an unlimited amount - * of slots - */ - def OneBitInfiniteSlots(events: List[BranchEvent]): Int = { - - // Uncomment to take a look at the event log - // say(events.mkString("\n","\n","\n")) - - // Helper inspects the next element of the event list. If the event is a mispredict the prediction table is updated - // to reflect this. - // As long as there are remaining events the helper calls itself recursively on the remainder - def helper(events: List[BranchEvent], predictionTable: Map[Int, Boolean]): Int = { - events match { - - // Scala syntax for matching a list with a head element of some type and a tail - // `case h :: t =>` - // means we want to match a list with at least a head and a tail (tail can be Nil, so we - // essentially want to match a list with at least one element) - // h is the first element of the list, t is the remainder (which can be Nil, aka empty) - - // `case Constructor(arg1, arg2) :: t => ` - // means we want to match a list whose first element is of type Constructor, giving us access to its internal - // values. - - // `case Constructor(arg1, arg2) :: t => if(p(arg1, arg2))` - // means we want to match a list whose first element is of type Constructor while satisfying some predicate p, - // called an if guard. - case Taken(from, to) :: t if( predictionTable(from)) => helper(t, predictionTable) - case Taken(from, to) :: t if(!predictionTable(from)) => 1 + helper(t, predictionTable.updated(from, true)) - case NotTaken(addr) :: t if( predictionTable(addr)) => 1 + helper(t, predictionTable.updated(addr, false)) - case NotTaken(addr) :: t if(!predictionTable(addr)) => helper(t, predictionTable) - case Nil => 0 - } - } - - // Initially every possible branch is set to false since the initial state of the predictor is to assume branch not taken - def initState = events.map{ - case Taken(from, addr) => (from, false) - case NotTaken(addr) => (addr, false) - }.toMap - - helper(events, initState) - } - - say(OneBitInfiniteSlots(events)) - } - - - true - } - - - def profileCache(testOptions: TestOptions): Boolean = { - - val testResults = for { - lines <- fileUtils.readTest(testOptions) - program <- FiveStage.Parser.parseProgram(lines, testOptions) - (binary, (trace, finalVM)) <- program.validate(testOptions.maxSteps).map(x => (x._1, x._2.run)) - } yield { - - sealed trait MemoryEvent - case class Write(addr: Int) extends MemoryEvent - case class Read(addr: Int) extends MemoryEvent - - val events: List[MemoryEvent] = trace.flatMap(_.event).collect{ - case MemWrite(x,_) => Write(x.value) - case MemRead(x,_) => Read(x.value) - } - - // Your cache here - - } - true - } } diff --git a/src/test/scala/TestUtils.scala b/src/test/scala/TestUtils.scala index acaa741..c1a0f94 100644 --- a/src/test/scala/TestUtils.scala +++ b/src/test/scala/TestUtils.scala @@ -6,6 +6,10 @@ import PrintUtils._ object TestUtils { + implicit class OptionBackport(t: Option.type){ + def when[T](b: Boolean)(t: => T) = if(b) Some(t) else None + } + /** * Generate and serialize BTrees for the test runner */ diff --git a/src/test/scala/chiselTestRunner.scala b/src/test/scala/chiselTestRunner.scala index cdd83a8..b244600 100644 --- a/src/test/scala/chiselTestRunner.scala +++ b/src/test/scala/chiselTestRunner.scala @@ -142,7 +142,7 @@ private class ChiselTestRunner ( // After finishing, let the circuit run until all updates can be committed. private def flush: List[CircuitTrace] = - (0 to 3).map(_ => stepOne).reverse.toList + (0 to 4).map(_ => stepOne).reverse.toList /** * Run the entire shebang diff --git a/theory2.org b/theory2.org index f98e836..a8b4848 100644 --- a/theory2.org +++ b/theory2.org @@ -1,36 +1,55 @@ -* Question 1 - Hazards - For the following programs describe each hazard with type (data or control), line number and a - small (max one sentence) description +* Question 0 - Testing hazards + This question is mandatory, but rewards no points (not directly at least). -** program 1 - #+begin_src asm - addi t0, zero, 10 - addi t1, zero, 20 - L2: - sub t1, t1, t0 - beq t1, zero, .L2 - jr ra - #+end_src + The tests found in the testing framework are useful for testing a fully working processor, however it + leaves much to be desired for when you actually want to design one from whole cloth. + + To rectify this, you should write some tests of your own that should serve as a minimal case for various + hazards that you will encounter. You do not need to deliver anything here, but I expect you to have + these tests if you ask me for help debugging your design during lab hours. + (You can of course come to lab hours if you're having trouble writing these tests) -** program 2 - #+begin_src asm - addi t0, zero, 10 - lw t0, 10(t0) - beq t0, zero, .L3 - jr ra - #+end_src +** Forwarding + The tests in forward1.s and forward2.s are automatically generated, long, and non-specific, + thus not very suited for debugging. + + You should write one (or more) test(s) that systematically expose your processor to dependency + hazards, including instructions that: + + Needs forwarding from MEM and WB (i.e dependencies with NOPs between them). + + Exposes results that should *not* be forwarded due to regWrite being false. + + Writes and reads to/from the zero register. -** program 3 - #+begin_src asm - lw t0, 0(t0) - lw t1, 4(t0) - sw t0, 8(t1) - lw t1, 12(t0) - beq t0, t1, .L3 - jr ra - #+end_src +** Load freezes + Loads freezes are tricky since they have an interaction with the forwarding unit, often causing + bugs that appear with low frequency in the supplied test programs. + + You should write tests (I suggest one test per case) that systematically expose your processor to + dependency hazards where one or more of the dependencies are memory accesses, including instructions that: + + Needs forwarding from MEM and WB where MEM, WB or both are load instructions. + + Exposes false dependencies from MEM and WB where one or more are loads. + For instance, consider ~addi x1, x1, 0x10~ in machine code with the rs2 field highlighted: + 0x00a08093 = 0b00000000 | 10100 | 0001000000010010011 + In this case there is a false dependency on x20 since x20 is only an artefact of the immediate + value which could cause an unecessary freeze. + + Writes and reads to/from the zero register, which could trigger an unecessary freeze + + Instructions that causes multiple freezes in a row. + + Instructions that causes multiple freezes in a row followed by an instruction with multiple + dependencies. + + +** Control hazards + There are a lot of possible interactions when jumping and branching, you need to write tests + that ensures that instructions are properly bubbled if they shouldn't have been fetched. + You should also test for interactions between forwarding and freezing here, i.e what happens + when the address calculation relies on forwarded values? What happens if the forwarded value + comes from a load instruction necessitating a freeze? + + +* TODO Question 1 - Hazards + Write programs here that are less of a crapshoot. Clarify dependency vs hazards etc etc and + *enforce* a format that is easy to grade. * Question 2 - Handling hazards @@ -39,7 +58,7 @@ ** Data hazards 1 At some cycle the following instructions can be found in a 5 stage design: - + #+begin_src text EX: || MEM: || WB: ---------------------||-------------------------||-------------------------- @@ -52,13 +71,17 @@ branch = false || branch = true || branch = false jump = false || jump = false || jump = false #+end_src - + For the operation currently in EX, from where (ID, MEM or WB) should the forwarder get data from for rs1 and rs2? - + Answer should be on the form: + + rs1: Narnia + rs2: Wikipedia + ** Data hazards 2 At some cycle the following instructions can be found in a 5 stage design: - + #+begin_src text EX: || MEM: || WB: ---------------------||-------------------------||-------------------------- @@ -73,11 +96,15 @@ #+end_src For the operation currently in EX, from where (ID, MEM or WB) should the forwarder get data from for rs1 and rs2? + Answer should be on the form: + + rs1: Random noise + rs2: WB (MEM if it's a tuesday) ** Data hazards 3 At some cycle the following instructions can be found in a 5 stage design: - + #+begin_src text EX: || MEM: || WB: ---------------------||-------------------------||-------------------------- @@ -89,24 +116,26 @@ memWrite = true || memWrite = false || memWrite = false branch = false || branch = false || branch = false jump = false || jump = false || jump = false - - Should the forwarding unit issue a load hazard signal? - (Hint: what are the semantics of the instruction currently in EX stage?) #+end_src + Should the forwarding unit issue a load hazard signal? *This is a yes/no question* + (Hint: what are the semantics of the instruction currently in EX stage?) + * Question 3 - Branch prediction - Consider a 2 bit branch predictor with only 4 slots for a 32 bit architecture (without BTB), where the decision to + Consider a 2 bit branch predictor with only 4 slots for a 32 bit architecture (without BTB), where the decision to take a branch or not is decided in accordance to the following table: #+begin_src text state || predict taken || next state if taken || next state if not taken || =======||=================||=======================||==========================|| 00 || NO || 01 || 00 || - 01 || NO || 10 || 00 || - 10 || YES || 11 || 01 || + 01 || NO || 11 || 00 || + 10 || YES || 11 || 00 || 11 || YES || 11 || 10 || #+end_src - - (This is known as a saturating 2bit counter, it is *not* the same scheme as in the lecture slides) + + Which corresponds to this figure: + #+CAPTION: FSM of a 2 bit branch predictor. Note that it is not a 2bit saturating counter. + [[./Images/BranchPredictor.png]] At some point during execution the program counter is ~0xc~ and the branch predictor table looks like this: #+begin_src text @@ -114,21 +143,34 @@ ======||======== 00 || 01 01 || 00 - 10 || 11 - 11 || 01 + 10 || 01 + 11 || 10 #+end_src For the following program: #+begin_src asm - 0xc addi x1, x3, 10 - 0x10 add x2, x1, x1 - 0x14 beq x1, x2, .L1 + .L1: + 0x0C addi x1, x1, 1 + 0x10 add x2, x2, x1 + 0x14 bge x2, x3, .L1 0x18 j .L2 + .L3: + 0x1C addi x2, x2, 0x10 + 0x20 slli x2, 0x4 + 0x24 jr ra #+end_src - - Will the predictor predict taken or not taken for the beq instruction? -* Question 4 - Benchmarking + At cycle 0 the state of the machine is as following: + #+begin_src text + PC = 0x0C + x1 = 0x0 + x2 = 0x0 + x3 = 0x7 + #+end_src + + At which cycle will the PC be 0x24 given a 2 cycle delay for mispredicts? + +* Question 4 - Benchmarking a branch profiler In order to gauge the performance increase from adding branch predictors it is necessary to do some testing. Rather than writing a test from scratch it is better to use the tester already in use in the test harness. When running a program the VM outputs a log of all events, including which branches have been taken and which @@ -148,7 +190,7 @@ To help you get started, I have provided you with much of the necessary code. In order to get an idea for how you should profile branch misses, consider the following profiler which calculates - misses for a processor with a branch predictor with a 1 bit predictor with infinite memory: + misses for a processor with a branch predictor with a 1 bit predictor with infinite slots: #+BEGIN_SRC scala def OneBitInfiniteSlots(events: List[BranchEvent]): Int = { @@ -172,11 +214,11 @@ // `case Constructor(arg1, arg2) :: t => if(p(arg1, arg2))` // means we want to match a list whose first element is of type Constructor while satisfying some predicate p, // called an if guard. - case Taken(from, to) :: t if( predictionTable(from)) => helper(t, predictionTable) - case Taken(from, to) :: t if(!predictionTable(from)) => 1 + helper(t, predictionTable.updated(from, true)) - case NotTaken(addr) :: t if( predictionTable(addr)) => 1 + helper(t, predictionTable.updated(addr, false)) - case NotTaken(addr) :: t if(!predictionTable(addr)) => helper(t, predictionTable) - case _ => 0 + case Taken(from, to) :: t if( predictionTable(from)) => helper(t, predictionTable) + case Taken(from, to) :: t if(!predictionTable(from)) => 1 + helper(t, predictionTable.updated(from, true)) + case NotTaken(addr) :: t if( predictionTable(addr)) => 1 + helper(t, predictionTable.updated(addr, false)) + case NotTaken(addr) :: t if(!predictionTable(addr)) => helper(t, predictionTable) + case _ => 0 } } @@ -207,7 +249,7 @@ With a 2 bit 8 slot scheme, how many mispredicts will happen? Answer with a number. - + Hint: Use the getTag method defined on int (in DataTypes.scala) to get the tag for an address. #+BEGIN_SRC scala val slots = 8 @@ -221,7 +263,7 @@ say(0x1C5C.getTag(slots)) // prints 7 say(0x1C60.getTag(slots)) // prints 0 (thus conflicts with 0x1C40) #+END_SRC - + * Question 5 - Cache profiling Unlike our design which has a very limited memory pool, real designs have access to vast amounts of memory, offset @@ -231,11 +273,6 @@ In order to investigate how caches can alter performance it is therefore necessary to make some rather unrealistic assumptions to see how different cache schemes impacts performance. - We will therefore assume the following: - + Reads from main memory takes 5 cycles - + cache has a total storage of 8 words (256 bits) - + cache reads work as they do now (i.e no additional latency) - For this exercise you will write a program that parses a log of memory events, similar to previous task #+BEGIN_SRC scala sealed trait MemoryEvent @@ -246,32 +283,13 @@ def profile(events: List[MemoryEvent]): Int = ??? #+END_SRC -** Your task - Your job is to implement a model that tests how many delay cycles will occur for a cache which: - + Follows a 2-way associative scheme - + set size is 4 words (128 bits) (total cache size: a whopping 256 bits) - + Block size is 1 word (32 bits) meaning that we *do not need a block offset*. - + Is write-through write no-allocate (this means that you can ignore stores, only loads will affect the cache) +** TODO Your task + Your job is to implement a *parameterised* model that tests how many delay cycles will occur for a cache with + the following configuration: + + Follows an n-way associative scheme (parameter) + + Is write-through write allocate. + Eviction policy is LRU (least recently used) - - In the typical cache each block has more than 32 bits, requiring an offset, however the - simulated cache does not. - This means that the simulated cache has two sets of 4 words, greatly reducing the complexity - of your implementation. - - Additionally, assume that writes does not change the the LRU counter. - This means that that your cache will only consider which value was most recently loaded, - not written. - It's not realistic, but it allows you to completely disregard write events (you can - just filter them out if you want.) - Your answer should be the number of cache miss latency cycles when using this cache. - -*** Further study - If you have the time I strongly encourage you to experiment with a larger cache with bigger - block sizes, forcing you to implement the additional complexity of block offsets. - Likewise, by trying a different scheme than write-through no-allocate you will get a much - better grasp on how exactly the cache works. - This is *not* a deliverable, just something I encourage you to tinker with to get a better - understanding. + To make this task easier a data structure with stub methods has been implemented for you. + Answer by pasting the output from running the branchProfiler test.