diff --git a/src/test/scala/RISCV/testRunner.scala b/src/test/scala/RISCV/testRunner.scala index 80a582e..96e5c4b 100644 --- a/src/test/scala/RISCV/testRunner.scala +++ b/src/test/scala/RISCV/testRunner.scala @@ -164,54 +164,7 @@ object TestRunner { helper(events, initState) } - - - def nBitPredictor(events: List[BranchEvent]): 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)) - copy(values = values.updated(pc.getTag(slots), transitionRules(current)(taken))) - } - } - - val initPredictor = nBitPredictor( - List.fill(4)(0), - List( - false, - false, - true, - true, - ), - r => r match { - case 0 => taken => if(taken) 1 else 0 - case 1 => taken => if(taken) 3 else 0 - case 2 => taken => if(taken) 3 else 0 - case 3 => taken => if(taken) 3 else 2 - } - ) - - events.foldLeft((0, initPredictor)){ case(((acc, bp), event)) => event match { - case Taken(pc, _) if bp.predict(pc) => (acc, bp.update(pc, true)) - case Taken(pc, _) => (acc + 1, bp.update(pc, false)) - case NotTaken(pc) if !bp.predict(pc) => (acc, bp.update(pc, false)) - case NotTaken(pc) => (acc + 1, bp.update(pc, true)) - }}._1 - } - - - say(OneBitInfiniteSlots(events)) - say(nBitPredictor(events)) - } true diff --git a/theory2.org b/theory2.org index 90bf611..0837bb6 100644 --- a/theory2.org +++ b/theory2.org @@ -95,7 +95,7 @@ #+end_src * Question 3 - Branch prediction - Consider a 2 bit branch predictor with only 4 slots for a 32 bit architecture, 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 || @@ -137,8 +137,8 @@ #+BEGIN_SRC scala sealed trait BranchEvent - case class Taken(addr: Int) extends BranchEvent - case class NotTaken(addr: Int) extends BranchEvent + case class Taken(from: Int, to: Int) extends BranchEvent + case class NotTaken(at: Int) extends BranchEvent def profile(events: List[BranchEvent]): Int = ??? @@ -170,11 +170,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(addr) :: t if( predictionTable(addr)) => helper(t, predictionTable) - case Taken(addr) :: t if(!predictionTable(addr)) => 1 + helper(t, predictionTable.updated(addr, 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 } } @@ -191,14 +191,19 @@ ** Your task Your job is to implement a test that checks how many misses occur for a 2 bit branch predictor with 8 slots. The rule table is the same as in question 3. - For simplicitys sake, assume that every value in the table is initialized to 00. + The predictor does not use a branch target buffer (BTB), which means that the address will always be decoded in + the ID stage. + For you this means you do not need to keep track of branch targets, simplifying your simulation quite a bit. + (If not you would need to add logic for when BTB value does not match actual value) + + For simplicity's sake, assume that every value in the table is initialized to 00. For this task it is necessary to use something more sophisticated than ~Map[(Int, Boolean)]~ to represent your branch predictor model. The skeleton code is located in ~testRunner.scala~ and can be run using testOnly FiveStage.ProfileTest. - With a 2 bit 4 slot scheme, how many misses will you incur? + With a 2 bit 8 slot scheme, how many mispredicts will happen? Answer with a number. * Question 5 - Cache profiling