Test the predictor's response to a single pattern of branch outcomes. The pattern is repeated [`Self::PATTERN_ITERS`] times.
(
harness: &mut PerfectHarness,
pattern: &BitVec<usize, Msb0>,
padding: Option<usize>,
)
| 114 | /// Test the predictor's response to a single pattern of branch outcomes. |
| 115 | /// The pattern is repeated [`Self::PATTERN_ITERS`] times. |
| 116 | fn run_pattern( |
| 117 | harness: &mut PerfectHarness, |
| 118 | pattern: &BitVec<usize, Msb0>, |
| 119 | padding: Option<usize>, |
| 120 | ) |
| 121 | -> PatternResults |
| 122 | { |
| 123 | let edesc = Self::EVENT.as_desc(); |
| 124 | |
| 125 | // Emit a new copy of our test |
| 126 | let f = Self::emit(padding); |
| 127 | let func = f.as_fn(); |
| 128 | |
| 129 | // Build a list of all branch outcomes during this test, repeating |
| 130 | // the input pattern some number of times |
| 131 | let mut outcomes = bitvec![usize, Msb0;]; |
| 132 | for _ in 0..Self::PATTERN_ITERS { |
| 133 | outcomes.extend(pattern); |
| 134 | } |
| 135 | |
| 136 | // Generate the values for RDI/RSI that are passed to the harness |
| 137 | let inputs: Vec<(usize,usize)> = outcomes.iter() |
| 138 | .map(|bit| (*bit as usize, 0)) |
| 139 | .collect(); |
| 140 | |
| 141 | // Try to eliminate the possibility of any older BTB entries |
| 142 | // interfering with the predictor state used during the test. |
| 143 | // We expect our branch to miss in the BTB when first encountered. |
| 144 | flush_btb::<8192>(); |
| 145 | |
| 146 | // Call our function in a loop and collect the results from RDPMC. |
| 147 | let results = harness.measure(func, |
| 148 | &edesc, outcomes.len(), |
| 149 | InputMethod::List(&inputs) |
| 150 | ).unwrap(); |
| 151 | |
| 152 | // Since we're measuring a single branch, we expect to measure at |
| 153 | // most one misprediction per iteration. Otherwise, our test was |
| 154 | // probably not reliable and something is very wrong with our |
| 155 | // setup (ie. SMT is not disabled, or we have been pre-empted |
| 156 | // while running the test?) |
| 157 | assert!(results.get_max() <= 1); |
| 158 | |
| 159 | // Use observed mispredictions to recover the predicted outcomes |
| 160 | // (ie. when we mispredict, the predicted outcome must be the |
| 161 | // opposite of the input we provided) |
| 162 | let mut predictions = bitvec![usize, Msb0;]; |
| 163 | let mut misses = bitvec![usize, Msb0;]; |
| 164 | for (misp, outcome) in results.data.iter().zip(outcomes.iter()) { |
| 165 | misses.push(*misp != 0); |
| 166 | if *misp == 0 { |
| 167 | predictions.push(*outcome); |
| 168 | } else { |
| 169 | predictions.push(!*outcome); |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | PatternResults::new(pattern.clone(), outcomes, predictions, misses) |