-
Notifications
You must be signed in to change notification settings - Fork 0
/
fp.rs
130 lines (112 loc) · 4.51 KB
/
fp.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use perfect::*;
use perfect::events::*;
use perfect::stats::*;
use rand::prelude::*;
use std::io::Write;
/// Create vector physical register file (PRF) pressure.
///
/// The Family 17h SOG mentions that the PRF has 160 entries.
///
pub struct VectorPrfPressure;
impl MispredictedReturnTemplate<usize> for VectorPrfPressure {}
impl VectorPrfPressure {
fn run(harness: &mut PerfectHarness) {
let mut events = EventSet::new();
events.add(Zen2Event::DeDisDispatchTokenStalls1(
DeDisDispatchTokenStalls1Mask::FpRegFileRsrcStall
));
let opts = MispredictedReturnOptions::zen2_defaults()
.rdpmc_strat(RdpmcStrategy::MemStatic(0x0000_5670))
.prologue_fn(Some(|mut f, _| {
dynasm!(f
; mov r8, 0x1111_2222_3333_4444
; vzeroall
);
for _ in 0..16 {
for idx in 0..=15 {
dynasm!(f; vpxor Ry(idx), Ry(idx), Ry(idx));
}
}
}));
let cases = StaticEmitterCases::new(&[
EmitterDesc { desc: "vaddpd (ymm)",
func: |f, input| {
for _ in 0..=input {
dynasm!(f ; vaddpd Ry(0), Ry(0), Ry(0));
}
}},
EmitterDesc { desc: "vaddpd (xmm)",
func: |f, input| {
for _ in 0..=input {
dynasm!(f ; vaddpd Rx(0), Rx(0), Rx(0));
}
}},
EmitterDesc { desc: "vpxor",
func: |f, input| {
for _ in 0..=input {
dynasm!(f ; vpxor Ry(0), Ry(0), Ry(0));
}
}},
EmitterDesc { desc: "vmovq (from r8)",
func: |f, input| {
for _ in 0..=input {
dynasm!(f ; vmovq Rx(0), r8);
}
}},
]);
let mut exp_results = ExperimentResults::new();
for testcase in cases.iter() {
println!("[*] Testcase '{}'", testcase.desc);
let mut case_res = ExperimentCaseResults::new(testcase.desc);
for i in 0..=256 {
let asm = Self::emit(opts, i, testcase.func);
let asm_reader = asm.reader();
let asm_tgt_buf = asm_reader.lock();
let asm_tgt_ptr = asm_tgt_buf.ptr(AssemblyOffset(0));
let asm_fn: MeasuredFn = unsafe {
std::mem::transmute(asm_tgt_ptr)
};
for event in events.iter() {
let desc = event.as_desc();
let results = harness.measure(asm_fn,
desc.id(), desc.mask(), 64, InputMethod::Fixed(0, 0)
).unwrap();
case_res.record(*event, i, results);
}
}
exp_results.push(case_res.clone());
}
for case_results in exp_results.data.iter() {
println!("# Results for case '{}'", case_results.desc);
for (event, event_results) in case_results.data.iter() {
let edesc = event.as_desc();
let case_name = case_results.desc.replace(" ", "_").to_lowercase();
let event_name = edesc.name().replace(".", "_").to_lowercase();
let path = format!("/tmp/{}__{:02x}_{:02x}_{}.dat", case_name,
edesc.id(), edesc.mask(), event_name);
let mut f = std::fs::OpenOptions::new()
.write(true) .create(true) .truncate(true)
.open(&path).unwrap();
println!("# Event {:03x}:{:02x} '{}'",
edesc.id(), edesc.mask(), edesc.name());
println!("writing to {}", path);
let minmax = event_results.local_minmax();
let avgs = event_results.local_avg_usize();
for ((input, avg), (min, max)) in event_results.inputs.iter()
.zip(avgs.iter()).zip(minmax.iter())
{
writeln!(f, "input={} min={} avg={} max={}", input, min, avg, max)
.unwrap();
println!("input={} min={} avg={} max={}", input, min, avg, max);
}
}
println!();
}
}
}
fn main() {
let mut harness = HarnessConfig::default_zen2()
.zero_strategy_fp(ZeroStrategyFp::Vzeroall)
.emit();
VectorPrfPressure::run(&mut harness);
}