forked from amiq-consulting/amiq_apb
/
amiq_apb_coverage.sv
307 lines (245 loc) · 10.7 KB
/
amiq_apb_coverage.sv
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
/******************************************************************************
* (C) Copyright 2014 AMIQ Consulting
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* MODULE: amiq_apb_coverage.sv
* PROJECT: amiq_apb
* Engineers: Andra Socianu (andra.socianu@amiq.com)
* Cristian Florin Slav (cristian.slav@amiq.com)
* Description: AMBA APB agent coverage collector
*******************************************************************************/
`ifndef AMIQ_APB_COVERAGE_SV
//protection against multiple includes
`define AMIQ_APB_COVERAGE_SV
//AMBA APB agent coverage collector
class amiq_apb_coverage extends cagt_coverage#(.VIRTUAL_INTF_TYPE(amiq_apb_vif_t), .MONITOR_ITEM(amiq_apb_mon_item));
`uvm_component_utils(amiq_apb_coverage)
//consecutive collected items
protected amiq_apb_mon_item collected_items[$];
//function for getting the delay between two consecutive transfers
//@return the delay between two consecutive transfers
protected function int unsigned get_delay_between_transfers();
AMIQ_APB_ALGORITHM_ERROR : assert (collected_items.size() == 2) else
`uvm_fatal("COVERAGE", $sformatf("Expecting collected_items.size() = 2 but found %0d", collected_items.size()))
return (((collected_items[1].start_time - collected_items[0].end_time) / collected_items[0].sys_clock_period) - 1);
endfunction
//Cover the current item
covergroup cover_item with function sample(amiq_apb_mon_item collected_item);
option.per_instance = 1;
//Cover the direction
direction : coverpoint collected_item.rw {
type_option.comment = "Direction of the APB access";
}
//Cover the transition for direction
trans_direction : coverpoint collected_item.rw {
bins direction_trans[] = (READ, WRITE => READ, WRITE);
type_option.comment = "Transitions of APB direction";
}
//Cover the first level of protection
first_level_protection : coverpoint collected_item.first_level_protection {
type_option.comment = "First level protection of APB access";
}
//Cover the transition for the first level of protection
trans_first_level_protection : coverpoint collected_item.first_level_protection {
bins trans_first_level_protection[] = (NORMAL_ACCESS, PRIVILEGED_ACCESS => NORMAL_ACCESS, PRIVILEGED_ACCESS);
type_option.comment = "Transitions of the first level protection of APB access";
}
//Cover the second level of protection
second_level_protection : coverpoint collected_item.second_level_protection {
type_option.comment = "Second level protection of APB access";
}
//Cover the transition for the second level of protection
trans_second_level_protection : coverpoint collected_item.second_level_protection {
bins trans_second_level_protection[] = (SECURE_ACCESS, NON_SECURE_ACCESS => SECURE_ACCESS, NON_SECURE_ACCESS);
type_option.comment = "Transitions of the second level protection of APB access";
}
//Cover the third level of protection
third_level_protection : coverpoint collected_item.third_level_protection {
type_option.comment = "Third level protection of APB access";
}
//Cover the transition for the third level of protection
trans_third_level_protection : coverpoint collected_item.third_level_protection {
bins trans_third_level_protection[] = (DATA_ACCESS, INSTRUCTION_ACCESS => DATA_ACCESS, INSTRUCTION_ACCESS);
type_option.comment = "Transitions of the third level protection of APB access";
}
//Cover the cross between the first level of protection and the direction
tr_first_level_protection_x_direction : cross first_level_protection, direction;
//Cover the cross between the second level of protection and the direction
tr_second_level_protection_x_direction : cross second_level_protection, direction;
//Cover the cross between the third level of protection and the direction
tr_third_level_protection_x_direction : cross third_level_protection, direction;
//Cover the fact that the transfer has or has not an error response
error_response : coverpoint collected_item.has_error {
type_option.comment = "Error response of APB access";
}
//Cover the transition for error response
trans_error_response : coverpoint collected_item.has_error {
bins error_response_trans[] = (NO_ERROR, WITH_ERROR => NO_ERROR, WITH_ERROR);
type_option.comment = "Transitions of error response of APB access";
}
//Cover the cross between the error response and the direction
error_response_x_direction : cross error_response, direction;
//Cover the strobe values
strobe : coverpoint collected_item.strobe {
type_option.comment = "Strobe of APB access";
}
//Cover the cross between the strobe and the direction
tr_strobe_x_direction : cross strobe, direction {
ignore_bins ig_values = binsof(strobe) intersect {[1:15]} && binsof(direction) intersect {READ};
}
//Cover the fact that the transfer has or has not wait-states
transfer_type : coverpoint collected_item.get_wait_state();
//Cover the transition for wait-states
trans_transfer_type : coverpoint collected_item.get_wait_state() {
bins transfer_type_trans[] = (WITHOUT_WAIT_STATE, WITH_WAIT_STATE => WITHOUT_WAIT_STATE, WITH_WAIT_STATE);
}
//Cover the cross between the transfer type (with or without wait-states) and the direction
transfer_type_x_direction : cross transfer_type, direction;
//Cover the wdata bits
`cvr_multiple_32_bits(wdata, collected_item.data, iff(collected_item.rw == WRITE))
//Cover the rdata bits
`cvr_multiple_32_bits(rdata, collected_item.data, iff((collected_item.rw == READ) && (collected_item.has_error == NO_ERROR)))
//Cover the addr bits
`cvr_multiple_32_bits(addr, collected_item.address, )
//Cover the wait-state duration
wait_state_length : coverpoint collected_item.get_wait_state_length() {
bins no_wait_state = {0};
bins small_wait_state_length[] = {[1:10]};
bins medium_wait_state_length[1] = {[11:50]};
bins big_wait_state_length[1] = {[51:$]};
}
//Cover the transfer length
transfer_length_units : coverpoint collected_item.get_transfer_length() {
bins small_transfer_length[] = {[2:12]};
bins medium_transfer_length[1] = {[13:52]};
bins big_transfer_length[1] = {[53:$]};
}
endgroup
//Cover the delay between two transfers
covergroup cover_delay_between_transfers;
option.per_instance = 1;
//Cover the delays between transfer
transfer_delay_units : coverpoint get_delay_between_transfers() {
bins back2back[] = {0};
bins small_delays[1] = {[1:10]};
bins medium_delays[1] = {[11:50]};
bins big_delays[1] = {[51:100]};
}
endgroup
//Cover how many clock cycle reset lasts
covergroup cover_reset_length with function sample(int unsigned reset_length);
option.per_instance = 1;
reset_time_units : coverpoint reset_length {
bins short[] = {[1:5]};
bins long[1] = {[6:$]};
}
endgroup
//function for getting the bus state at reset
//@return the bus state at reset
protected function amiq_apb_bus_state_t get_bus_state();
get_bus_state = IDLE;
if(collected_items.size() != 0) begin
amiq_apb_mon_item last_item = collected_items[collected_items.size() - 1];
if(last_item.end_time == 0) begin
if($time - last_item.start_time < (2 * last_item.sys_clock_period)) begin
get_bus_state = SETUP;
end
else begin
get_bus_state = ACCESS;
end
end
end
endfunction
covergroup cover_bus_state_at_reset;
option.per_instance = 1;
bus_state_on_reset : coverpoint get_bus_state();
endgroup
//constructor
//@param name - name of the component instance
//@param parent - parent of the component instance
function new(string name = "amiq_apb_coverage", uvm_component parent);
super.new(name, parent);
cover_item = new();
cover_item.set_inst_name($sformatf("%s_%s", get_full_name(), "cover_item"));
cover_reset_length = new();
cover_reset_length.set_inst_name($sformatf("%s_%s", get_full_name(), "cover_reset_length"));
cover_bus_state_at_reset = new();
cover_bus_state_at_reset.set_inst_name($sformatf("%s_%s", get_full_name(), "cover_bus_state_at_reset"));
cover_delay_between_transfers = new();
cover_delay_between_transfers.set_inst_name($sformatf("%s_%s", get_full_name(), "cover_delay_between_transfers"));
endfunction
//UVM build phase
//@param phase - current phase
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
//UVM run phase
//@param phase - current phase
task run_phase(uvm_phase phase);
fork
collect_reset_time_units();
join_none
endtask
//function for handling reset
virtual function void handle_reset();
super.handle_reset();
cover_bus_state_at_reset.sample();
while(collected_items.size() > 0) begin
void'(collected_items.pop_front());
end
endfunction
//Task used to collect how many clock cycles a reset lasts
task collect_reset_time_units();
amiq_apb_vif_t dut_vif = agent_config.get_dut_vif();
forever @(negedge dut_vif.reset_n)
begin
int unsigned reset_length = 0;
//Collect the reset_length
while(dut_vif.reset_n === 0) begin
reset_length = reset_length + 1;
@(posedge dut_vif.clk);
end
cover_reset_length.sample(reset_length);
end
endtask
//Overwrite the write method in order to cover the transfer item
//@param transfer APB item received from the monitor
function void write_item_from_mon(amiq_apb_mon_item transfer);
if(transfer.end_time != 0) begin
cover_item.sample(transfer);
begin
bit found_item = 0;
for(int i = 0; i < collected_items.size(); i++) begin
if(collected_items[i].start_time == transfer.start_time) begin
collected_items[i] = transfer;
found_item = 1;
break;
end
end
AMIQ_APB_ALGORITHM_ERROR : assert (found_item == 1) else
`uvm_fatal("COVERAGE", $sformatf("Did not found item in collected_items: %s", transfer.convert2string()));
end
end
else begin
collected_items.push_back(transfer);
while(collected_items.size() > 2) begin
void'(collected_items.pop_front());
end
if(collected_items.size() == 2) begin
cover_delay_between_transfers.sample();
end
end
endfunction
endclass
`endif