forked from antonblanchard/microwatt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pmu.vhdl
369 lines (343 loc) · 14.1 KB
/
pmu.vhdl
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.common.all;
use work.decode_types.all;
entity pmu is
port (
clk : in std_ulogic;
rst : in std_ulogic;
p_in : in Execute1ToPMUType;
p_out : out PMUToExecute1Type
);
end entity pmu;
architecture behaviour of pmu is
-- MMCR0 bit numbers
constant MMCR0_FC : integer := 63 - 32;
constant MMCR0_FCS : integer := 63 - 33;
constant MMCR0_FCP : integer := 63 - 34;
constant MMCR0_FCM1 : integer := 63 - 35;
constant MMCR0_FCM0 : integer := 63 - 36;
constant MMCR0_PMAE : integer := 63 - 37;
constant MMCR0_FCECE : integer := 63 - 38;
constant MMCR0_TBSEL : integer := 63 - 40;
constant MMCR0_TBEE : integer := 63 - 41;
constant MMCR0_BHRBA : integer := 63 - 42;
constant MMCR0_EBE : integer := 63 - 43;
constant MMCR0_PMCC : integer := 63 - 45;
constant MMCR0_PMC1CE : integer := 63 - 48;
constant MMCR0_PMCjCE : integer := 63 - 49;
constant MMCR0_TRIGGER : integer := 63 - 50;
constant MMCR0_FCPC : integer := 63 - 51;
constant MMCR0_PMAQ : integer := 63 - 52;
constant MMCR0_PMCCEXT : integer := 63 - 54;
constant MMCR0_CC56RUN : integer := 63 - 55;
constant MMCR0_PMAO : integer := 63 - 56;
constant MMCR0_FC1_4 : integer := 63 - 58;
constant MMCR0_FC5_6 : integer := 63 - 59;
constant MMCR0_FC1_4W : integer := 63 - 62;
-- MMCR2 bit numbers
constant MMCR2_FC0S : integer := 63 - 0;
constant MMCR2_FC0P0 : integer := 63 - 1;
constant MMCR2_FC0M1 : integer := 63 - 3;
constant MMCR2_FC0M0 : integer := 63 - 4;
constant MMCR2_FC0WAIT : integer := 63 - 5;
constant MMCR2_FC1S : integer := 54 - 0;
constant MMCR2_FC1P0 : integer := 54 - 1;
constant MMCR2_FC1M1 : integer := 54 - 3;
constant MMCR2_FC1M0 : integer := 54 - 4;
constant MMCR2_FC1WAIT : integer := 54 - 5;
constant MMCR2_FC2S : integer := 45 - 0;
constant MMCR2_FC2P0 : integer := 45 - 1;
constant MMCR2_FC2M1 : integer := 45 - 3;
constant MMCR2_FC2M0 : integer := 45 - 4;
constant MMCR2_FC2WAIT : integer := 45 - 5;
constant MMCR2_FC3S : integer := 36 - 0;
constant MMCR2_FC3P0 : integer := 36 - 1;
constant MMCR2_FC3M1 : integer := 36 - 3;
constant MMCR2_FC3M0 : integer := 36 - 4;
constant MMCR2_FC3WAIT : integer := 36 - 5;
constant MMCR2_FC4S : integer := 27 - 0;
constant MMCR2_FC4P0 : integer := 27 - 1;
constant MMCR2_FC4M1 : integer := 27 - 3;
constant MMCR2_FC4M0 : integer := 27 - 4;
constant MMCR2_FC4WAIT : integer := 27 - 5;
constant MMCR2_FC5S : integer := 18 - 0;
constant MMCR2_FC5P0 : integer := 18 - 1;
constant MMCR2_FC5M1 : integer := 18 - 3;
constant MMCR2_FC5M0 : integer := 18 - 4;
constant MMCR2_FC5WAIT : integer := 18 - 5;
constant MMCR2_FC6S : integer := 9 - 0;
constant MMCR2_FC6P0 : integer := 9 - 1;
constant MMCR2_FC6M1 : integer := 9 - 3;
constant MMCR2_FC6M0 : integer := 9 - 4;
constant MMCR2_FC6WAIT : integer := 9 - 5;
-- MMCRA bit numbers
constant MMCRA_TECX : integer := 63 - 36;
constant MMCRA_TECM : integer := 63 - 44;
constant MMCRA_TECE : integer := 63 - 47;
constant MMCRA_TS : integer := 63 - 51;
constant MMCRA_TE : integer := 63 - 55;
constant MMCRA_ES : integer := 63 - 59;
constant MMCRA_SM : integer := 63 - 62;
constant MMCRA_SE : integer := 63 - 63;
-- SIER bit numbers
constant SIER_SAMPPR : integer := 63 - 38;
constant SIER_SIARV : integer := 63 - 41;
constant SIER_SDARV : integer := 63 - 42;
constant SIER_TE : integer := 63 - 43;
constant SIER_SITYPE : integer := 63 - 48;
constant SIER_SICACHE : integer := 63 - 51;
constant SIER_SITAKBR : integer := 63 - 52;
constant SIER_SIMISPR : integer := 63 - 53;
constant SIER_SIMISPRI : integer := 63 - 55;
constant SIER_SIDERAT : integer := 63 - 56;
constant SIER_SIDAXL : integer := 63 - 59;
constant SIER_SIDSAI : integer := 63 - 62;
constant SIER_SICMPL : integer := 63 - 63;
type pmc_array is array(1 to 6) of std_ulogic_vector(31 downto 0);
signal pmcs : pmc_array;
signal mmcr0 : std_ulogic_vector(31 downto 0);
signal mmcr1 : std_ulogic_vector(63 downto 0);
signal mmcr2 : std_ulogic_vector(63 downto 0);
signal mmcra : std_ulogic_vector(63 downto 0);
signal siar : std_ulogic_vector(63 downto 0);
signal sdar : std_ulogic_vector(63 downto 0);
signal sier : std_ulogic_vector(63 downto 0);
signal doinc : std_ulogic_vector(1 to 6);
signal doalert : std_ulogic;
signal doevent : std_ulogic;
signal prev_tb : std_ulogic_vector(3 downto 0);
begin
-- mfspr mux
with p_in.spr_num(3 downto 0) select p_out.spr_val <=
32x"0" & pmcs(1) when "0011",
32x"0" & pmcs(2) when "0100",
32x"0" & pmcs(3) when "0101",
32x"0" & pmcs(4) when "0110",
32x"0" & pmcs(5) when "0111",
32x"0" & pmcs(6) when "1000",
32x"0" & mmcr0 when "1011",
mmcr1 when "1110",
mmcr2 when "0001",
mmcra when "0010",
siar when "1100",
sdar when "1101",
sier when "0000",
64x"0" when others;
p_out.intr <= mmcr0(MMCR0_PMAO);
pmu_1: process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
mmcr0 <= 32x"80000000";
else
for i in 1 to 6 loop
if p_in.mtspr = '1' and to_integer(unsigned(p_in.spr_num(3 downto 0))) = i + 2 then
pmcs(i) <= p_in.spr_val(31 downto 0);
elsif doinc(i) = '1' then
pmcs(i) <= std_ulogic_vector(unsigned(pmcs(i)) + 1);
end if;
end loop;
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1011" then
mmcr0 <= p_in.spr_val(31 downto 0);
mmcr0(MMCR0_BHRBA) <= '0'; -- no BHRB yet
mmcr0(MMCR0_EBE) <= '0'; -- no EBBs yet
else
if doalert = '1' then
mmcr0(MMCR0_PMAE) <= '0';
mmcr0(MMCR0_PMAO) <= '1';
mmcr0(MMCR0_PMAQ) <= '0';
end if;
if doevent = '1' and mmcr0(MMCR0_FCECE) = '1' and mmcr0(MMCR0_TRIGGER) = '0' then
mmcr0(MMCR0_FC) <= '1';
end if;
if (doevent = '1' or pmcs(1)(31) = '1') and mmcr0(MMCR0_TRIGGER) = '1' then
mmcr0(MMCR0_TRIGGER) <= '0';
end if;
end if;
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1110" then
mmcr1 <= p_in.spr_val;
end if;
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "0001" then
mmcr2 <= p_in.spr_val;
end if;
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "0010" then
mmcra <= p_in.spr_val;
-- we don't support random sampling yet
mmcra(MMCRA_SE) <= '0';
end if;
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1100" then
siar <= p_in.spr_val;
elsif doalert = '1' then
siar <= p_in.nia;
end if;
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "1101" then
sdar <= p_in.spr_val;
elsif doalert = '1' then
sdar <= p_in.addr;
end if;
if p_in.mtspr = '1' and p_in.spr_num(3 downto 0) = "0000" then
sier <= p_in.spr_val;
elsif doalert = '1' then
sier <= (others => '0');
sier(SIER_SAMPPR) <= p_in.pr_msr;
sier(SIER_SIARV) <= '1';
sier(SIER_SDARV) <= p_in.addr_v;
end if;
end if;
prev_tb <= p_in.tbbits;
end if;
end process;
pmu_2: process(all)
variable tbdiff : std_ulogic_vector(3 downto 0);
variable tbbit : std_ulogic;
variable freeze : std_ulogic;
variable event : std_ulogic;
variable j : integer;
variable inc : std_ulogic_vector(1 to 6);
variable fc14wo : std_ulogic;
begin
event := '0';
-- Check for timebase events
tbdiff := p_in.tbbits and not prev_tb;
if is_X(mmcr0) then
tbbit := 'X';
else
tbbit := tbdiff(3 - to_integer(unsigned(mmcr0(MMCR0_TBSEL + 1 downto MMCR0_TBSEL))));
end if;
if tbbit = '1' and mmcr0(MMCR0_TBEE) = '1' then
event := '1';
end if;
-- Check for counter negative events
if mmcr0(MMCR0_PMC1CE) = '1' and pmcs(1)(31) = '1' then
event := '1';
end if;
if mmcr0(MMCR0_PMCjCE) = '1' and
(pmcs(2)(31) or pmcs(3)(31) or pmcs(4)(31)) = '1' then
event := '1';
end if;
if mmcr0(MMCR0_PMCjCE) = '1' and
mmcr0(MMCR0_PMCC + 1 downto MMCR0_PMCC) /= "11" and
(pmcs(5)(31) or pmcs(6)(31)) = '1' then
event := '1';
end if;
-- Event selection
inc := (others => '0');
fc14wo := '0';
case mmcr1(31 downto 24) is
when x"f0" =>
inc(1) := '1';
fc14wo := '1'; -- override MMCR0[FC1_4WAIT]
when x"f2" | x"fe" =>
inc(1) := p_in.occur.instr_complete;
when x"f4" =>
inc(1) := p_in.occur.fp_complete;
when x"f6" =>
inc(1) := p_in.occur.itlb_miss;
when x"f8" =>
inc(1) := p_in.occur.no_instr_avail;
when x"fa" =>
inc(1) := p_in.run;
when x"fc" =>
inc(1) := p_in.occur.ld_complete;
when others =>
end case;
case mmcr1(23 downto 16) is
when x"f0" =>
inc(2) := p_in.occur.st_complete;
when x"f2" =>
inc(2) := p_in.occur.dispatch;
when x"f4" =>
inc(2) := p_in.run;
when x"f6" =>
inc(2) := p_in.occur.dtlb_miss_resolved;
when x"f8" =>
inc(2) := p_in.occur.ext_interrupt;
when x"fa" =>
inc(2) := p_in.occur.br_taken_complete;
when x"fc" =>
inc(2) := p_in.occur.icache_miss;
when x"fe" =>
inc(2) := p_in.occur.dc_miss_resolved;
when others =>
end case;
case mmcr1(15 downto 8) is
when x"f0" =>
inc(3) := p_in.occur.dc_store_miss;
when x"f2" =>
inc(3) := p_in.occur.dispatch;
when x"f4" =>
inc(3) := p_in.occur.instr_complete and p_in.run;
when x"f6" =>
inc(3) := p_in.occur.dc_ld_miss_resolved;
when x"f8" =>
inc(3) := tbbit;
when x"fe" =>
inc(3) := p_in.occur.dtlb_miss;
when others =>
end case;
case mmcr1(7 downto 0) is
when x"f0" =>
inc(4) := p_in.occur.dc_load_miss;
when x"f2" =>
inc(4) := p_in.occur.dispatch;
when x"f4" =>
inc(4) := p_in.run;
when x"f6" =>
inc(4) := p_in.occur.br_mispredict;
when x"f8" =>
inc(4) := p_in.occur.ipref_discard;
when x"fa" =>
inc(4) := p_in.occur.instr_complete and p_in.run;
when x"fc" =>
inc(4) := p_in.occur.itlb_miss_resolved;
when x"fe" =>
inc(4) := p_in.occur.ld_miss_nocache;
when others =>
end case;
inc(5) := (mmcr0(MMCR0_CC56RUN) or p_in.run) and p_in.occur.instr_complete;
inc(6) := mmcr0(MMCR0_CC56RUN) or p_in.run;
-- Evaluate freeze conditions
freeze := mmcr0(MMCR0_FC) or
(mmcr0(MMCR0_FCS) and not p_in.pr_msr) or
(mmcr0(MMCR0_FCP) and not mmcr0(MMCR0_FCPC) and p_in.pr_msr) or
(not mmcr0(MMCR0_FCP) and mmcr0(MMCR0_FCPC) and p_in.pr_msr) or
(mmcr0(MMCR0_FCM1) and p_in.pmm_msr) or
(mmcr0(MMCR0_FCM0) and not p_in.pmm_msr);
if freeze = '1' or mmcr0(MMCR0_FC1_4) = '1' or
(mmcr0(MMCR0_FC1_4W) = '1' and p_in.run = '0' and fc14wo = '0') then
inc(1) := '0';
end if;
if freeze = '1' or mmcr0(MMCR0_FC1_4) = '1' or
(mmcr0(MMCR0_FC1_4W) = '1' and p_in.run = '0') then
inc(2 to 4) := "000";
end if;
if freeze = '1' or mmcr0(MMCR0_FC5_6) = '1' then
inc(5 to 6) := "00";
end if;
if mmcr0(MMCR0_TRIGGER) = '1' then
inc(2 to 6) := "00000";
end if;
for i in 1 to 6 loop
j := (i - 1) * 9;
if (mmcr2(MMCR2_FC0S - j) = '1' and p_in.pr_msr = '0') or
(mmcr2(MMCR2_FC0P0 - j) = '1' and p_in.pr_msr = '1') or
(mmcr2(MMCR2_FC0M1 - j) = '1' and p_in.pmm_msr = '1') or
(mmcr2(MMCR2_FC0M1 - j) = '1' and p_in.pmm_msr = '1') then
inc(i) := '0';
end if;
end loop;
-- When MMCR0[PMCC] = "11", PMC5 and PMC6 are not controlled by the
-- MMCRs and don't generate events, but do continue to count run
-- instructions and run cycles.
if mmcr0(MMCR0_PMCC + 1 downto MMCR0_PMCC) = "11" then
inc(5) := p_in.run and p_in.occur.instr_complete;
inc(6) := p_in.run;
end if;
doinc <= inc;
doevent <= event;
doalert <= event and mmcr0(MMCR0_PMAE);
end process;
end architecture behaviour;