1 |
48 |
alirezamon |
/* ****************************************************************************
|
2 |
|
|
This Source Code Form is subject to the terms of the
|
3 |
|
|
Open Hardware Description License, v. 1.0. If a copy
|
4 |
|
|
of the OHDL was not distributed with this file, You
|
5 |
|
|
can obtain one at http://juliusbaxter.net/ohdl/ohdl.txt
|
6 |
|
|
|
7 |
|
|
Description: mor1kx Perfomance Counters Unit
|
8 |
|
|
|
9 |
|
|
Copyright (C) 2016 Authors
|
10 |
|
|
|
11 |
|
|
Author(s): Alexey Baturo <baturo.alexey@gmail.com>
|
12 |
|
|
|
13 |
|
|
***************************************************************************** */
|
14 |
|
|
|
15 |
|
|
`include "mor1kx-defines.v"
|
16 |
|
|
|
17 |
|
|
module mor1kx_pcu
|
18 |
|
|
#(
|
19 |
|
|
parameter OPTION_PERFCOUNTERS_NUM = 7
|
20 |
|
|
)
|
21 |
|
|
(
|
22 |
|
|
input clk,
|
23 |
|
|
input rst,
|
24 |
|
|
|
25 |
|
|
// SPR Bus interface
|
26 |
|
|
input spr_access_i,
|
27 |
|
|
input spr_we_i,
|
28 |
|
|
input spr_re_i,
|
29 |
|
|
input [15:0] spr_addr_i,
|
30 |
|
|
input [31:0] spr_dat_i,
|
31 |
|
|
output spr_bus_ack,
|
32 |
|
|
output [31:0] spr_dat_o,
|
33 |
|
|
|
34 |
|
|
// Current cpu mode: user/supervisor
|
35 |
|
|
input spr_sys_mode_i,
|
36 |
|
|
// Events that can occur
|
37 |
|
|
input pcu_event_load_i, // track load insn
|
38 |
|
|
input pcu_event_store_i, // track store insn
|
39 |
|
|
input pcu_event_ifetch_i, // track insn fetch
|
40 |
|
|
input pcu_event_dcache_miss_i, // track data cache miss
|
41 |
|
|
input pcu_event_icache_miss_i, // track insn cache miss
|
42 |
|
|
input pcu_event_ifetch_stall_i, // track SOME stall
|
43 |
|
|
input pcu_event_lsu_stall_i, // track LSU stall
|
44 |
|
|
input pcu_event_brn_stall_i, // track brn miss
|
45 |
|
|
input pcu_event_dtlb_miss_i, // track data tlb miss
|
46 |
|
|
input pcu_event_itlb_miss_i, // track insn tlb miss
|
47 |
|
|
input pcu_event_datadep_stall_i // track SOME stall
|
48 |
|
|
);
|
49 |
|
|
|
50 |
|
|
// Registers
|
51 |
|
|
reg [31:0] pcu_pccr[0:OPTION_PERFCOUNTERS_NUM];
|
52 |
|
|
reg [31:0] pcu_pcmr[0:OPTION_PERFCOUNTERS_NUM];
|
53 |
|
|
|
54 |
|
|
wire pcu_pccr_access;
|
55 |
|
|
wire pcu_pcmr_access;
|
56 |
|
|
|
57 |
|
|
// check if we access pcu
|
58 |
|
|
// TODO: generate this signals according to present units
|
59 |
|
|
assign pcu_pccr_access =
|
60 |
|
|
spr_access_i &
|
61 |
|
|
((`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR0_ADDR)) |
|
62 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR1_ADDR)) |
|
63 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR2_ADDR)) |
|
64 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR3_ADDR)) |
|
65 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR4_ADDR)) |
|
66 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR5_ADDR)) |
|
67 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR6_ADDR)) |
|
68 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR7_ADDR)));
|
69 |
|
|
|
70 |
|
|
assign pcu_pcmr_access =
|
71 |
|
|
spr_access_i &
|
72 |
|
|
((`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR0_ADDR)) |
|
73 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR1_ADDR)) |
|
74 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR2_ADDR)) |
|
75 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR3_ADDR)) |
|
76 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR4_ADDR)) |
|
77 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR5_ADDR)) |
|
78 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR6_ADDR)) |
|
79 |
|
|
(`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR7_ADDR)));
|
80 |
|
|
|
81 |
|
|
// put data on data bus
|
82 |
|
|
assign spr_bus_ack = spr_access_i;
|
83 |
|
|
assign spr_dat_o = (spr_access_i & pcu_pccr_access & spr_re_i) ? pcu_pccr[spr_addr_i[2:0]] :
|
84 |
|
|
(spr_access_i & pcu_pcmr_access & spr_re_i & spr_sys_mode_i) ? pcu_pcmr[spr_addr_i[2:0]] :
|
85 |
|
|
0;
|
86 |
|
|
genvar pcu_num;
|
87 |
|
|
generate
|
88 |
|
|
for(pcu_num = 0; pcu_num < OPTION_PERFCOUNTERS_NUM + 1; pcu_num = pcu_num + 1) begin: pcu_generate
|
89 |
|
|
wire [`OR1K_PCMR_DDS:`OR1K_PCMR_LA] pcu_events_active;
|
90 |
|
|
wire [`OR1K_PCMR_DDS:`OR1K_PCMR_LA] pcu_events_hit;
|
91 |
|
|
|
92 |
|
|
assign pcu_events_active =
|
93 |
|
|
(pcu_event_load_i << `OR1K_PCMR_LA) |
|
94 |
|
|
(pcu_event_store_i << `OR1K_PCMR_SA) |
|
95 |
|
|
(pcu_event_ifetch_i << `OR1K_PCMR_IF) |
|
96 |
|
|
(pcu_event_dcache_miss_i << `OR1K_PCMR_DCM) |
|
97 |
|
|
(pcu_event_icache_miss_i << `OR1K_PCMR_ICM) |
|
98 |
|
|
(pcu_event_ifetch_stall_i << `OR1K_PCMR_IFS) |
|
99 |
|
|
(pcu_event_lsu_stall_i << `OR1K_PCMR_LSUS) |
|
100 |
|
|
(pcu_event_brn_stall_i << `OR1K_PCMR_BS) |
|
101 |
|
|
(pcu_event_dtlb_miss_i << `OR1K_PCMR_DTLBM) |
|
102 |
|
|
(pcu_event_itlb_miss_i << `OR1K_PCMR_ITLBM) |
|
103 |
|
|
(pcu_event_datadep_stall_i << `OR1K_PCMR_DDS);
|
104 |
|
|
|
105 |
|
|
assign pcu_events_hit =
|
106 |
|
|
pcu_events_active & pcu_pcmr[pcu_num];
|
107 |
|
|
|
108 |
|
|
always @(posedge clk `OR_ASYNC_RST) begin
|
109 |
|
|
if (rst) begin
|
110 |
|
|
pcu_pccr[pcu_num] <= 32'd0;
|
111 |
|
|
pcu_pcmr[pcu_num] <= 32'd0 | 1 << `OR1K_PCMR_CP;
|
112 |
|
|
// we could write pcu registers only in system mode
|
113 |
|
|
end else if (spr_we_i && spr_sys_mode_i) begin
|
114 |
|
|
if (pcu_pccr_access & (spr_addr_i[2:0] == pcu_num))
|
115 |
|
|
pcu_pccr[pcu_num] <= spr_dat_i;
|
116 |
|
|
// WPE are not implemented, hence we do not update WPE part
|
117 |
|
|
if (pcu_pcmr_access && (spr_addr_i[2:0] == pcu_num)) begin
|
118 |
|
|
pcu_pcmr[pcu_num][`OR1K_PCMR_DDS:`OR1K_PCMR_CISM] <=
|
119 |
|
|
spr_dat_i[`OR1K_PCMR_DDS:`OR1K_PCMR_CISM];
|
120 |
|
|
end
|
121 |
|
|
end else if (((pcu_pcmr[pcu_num][`OR1K_PCMR_CISM] & spr_sys_mode_i) |
|
122 |
|
|
(pcu_pcmr[pcu_num][`OR1K_PCMR_CIUM] & ~spr_sys_mode_i))) begin
|
123 |
|
|
pcu_pccr[pcu_num] <= pcu_pccr[pcu_num] +
|
124 |
|
|
pcu_events_hit[`OR1K_PCMR_LA] +
|
125 |
|
|
pcu_events_hit[`OR1K_PCMR_SA] +
|
126 |
|
|
pcu_events_hit[`OR1K_PCMR_IF] +
|
127 |
|
|
pcu_events_hit[`OR1K_PCMR_DCM] +
|
128 |
|
|
pcu_events_hit[`OR1K_PCMR_ICM] +
|
129 |
|
|
pcu_events_hit[`OR1K_PCMR_IFS] +
|
130 |
|
|
pcu_events_hit[`OR1K_PCMR_LSUS] +
|
131 |
|
|
pcu_events_hit[`OR1K_PCMR_BS] +
|
132 |
|
|
pcu_events_hit[`OR1K_PCMR_DTLBM] +
|
133 |
|
|
pcu_events_hit[`OR1K_PCMR_ITLBM] +
|
134 |
|
|
pcu_events_hit[`OR1K_PCMR_DDS];
|
135 |
|
|
end
|
136 |
|
|
end
|
137 |
|
|
end
|
138 |
|
|
endgenerate
|
139 |
|
|
|
140 |
|
|
endmodule // mor1kx_pcu
|