-
-
Notifications
You must be signed in to change notification settings - Fork 108
/
Copy pathtvip_axi_item.svh
450 lines (394 loc) · 14.1 KB
/
tvip_axi_item.svh
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
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
`ifndef TVIP_AXI_ITEM_SVH
`define TVIP_AXI_ITEM_SVH
class tvip_axi_item extends tue_sequence_item #(
.CONFIGURATION (tvip_axi_configuration ),
.STATUS (tvip_axi_status )
);
rand tvip_axi_access_type access_type;
rand tvip_axi_id id;
rand tvip_axi_address address;
rand int burst_length;
rand int burst_size;
rand tvip_axi_burst_type burst_type;
rand tvip_axi_qos qos;
rand tvip_axi_data data[];
rand tvip_axi_strobe strobe[];
rand tvip_axi_response response[];
rand int start_delay;
rand int write_data_delay[];
rand int response_delay[];
rand int address_ready_delay;
rand int write_data_ready_delay[];
rand int response_ready_delay[];
uvm_event address_begin_event;
time address_begin_time;
uvm_event address_end_event;
time address_end_time;
uvm_event write_data_begin_event;
time write_data_begin_time;
uvm_event write_data_end_event;
time write_data_end_time;
uvm_event response_begin_event;
time response_begin_time;
uvm_event response_end_event;
time response_end_time;
rand bit need_response;
function new(string name = "tvip_axi_item");
super.new(name);
address_begin_event = get_event("address_begin");
address_end_event = get_event("address_end");
write_data_begin_event = get_event("write_data_begin");
write_data_end_event = get_event("write_data_end");
response_begin_event = get_event("response_begin");
response_end_event = get_event("response_end");
endfunction
function bit is_write();
return (access_type == TVIP_AXI_WRITE_ACCESS) ? '1 : '0;
endfunction
function bit is_read();
return (access_type == TVIP_AXI_READ_ACCESS) ? '1 : '0;
endfunction
function int get_burst_length();
if ((configuration != null) && (configuration.protocol == TVIP_AXI4LITE)) begin
return 1;
end
else begin
return burst_length;
end
endfunction
function tvip_axi_burst_length get_packed_burst_length();
return pack_burst_length(get_burst_length());
endfunction
function void set_packed_burst_length(tvip_axi_burst_length packed_burst_length);
if ((configuration != null) && (configuration.protocol == TVIP_AXI4LITE)) begin
burst_length = 1;
end
else begin
burst_length = unpack_burst_length(packed_burst_length);
end
endfunction
function int get_burst_size();
if ((configuration != null) && (configuration.protocol == TVIP_AXI4LITE)) begin
return configuration.data_width / 8;
end
else begin
return burst_size;
end
endfunction
function tvip_axi_burst_size get_packed_burst_size();
return pack_burst_size(get_burst_size());
endfunction
function void set_packed_burst_size(tvip_axi_burst_size packed_burst_size);
if ((configuration != null) && (configuration.protocol == TVIP_AXI4LITE)) begin
burst_size = configuration.data_width / 8;
end
else begin
burst_size = unpack_burst_size(packed_burst_size);
end
endfunction
function void put_data(const ref tvip_axi_data data[$]);
this.data = new[data.size()];
foreach (data[i]) begin
this.data[i] = data[i];
end
endfunction
function tvip_axi_data get_data(int index);
if (index < data.size()) begin
return data[index];
end
else begin
return '0;
end
endfunction
function void put_strobe(const ref tvip_axi_strobe strobe[$]);
this.strobe = new[strobe.size()];
foreach (strobe[i]) begin
this.strobe[i] = strobe[i];
end
endfunction
function tvip_axi_strobe get_strobe(int index);
if (index < strobe.size()) begin
return strobe[index];
end
else begin
return '0;
end
endfunction
function void put_response(const ref tvip_axi_response response[$]);
this.response = new[response.size()];
foreach (response[i]) begin
this.response[i] = response[i];
end
endfunction
function tvip_axi_response get_response(int index);
if (index < response.size()) begin
return response[index];
end
else begin
return TVIP_AXI_OKAY;
end
endfunction
`define tvip_axi_declare_begin_end_event_api(EVENT_TYPE) \
function void begin_``EVENT_TYPE``(time begin_time = 0); \
if (``EVENT_TYPE``_begin_event.is_off()) begin \
``EVENT_TYPE``_begin_time = (begin_time <= 0) ? $time : begin_time; \
``EVENT_TYPE``_begin_event.trigger(); \
end \
endfunction \
function void end_``EVENT_TYPE``(time end_time = 0); \
if (``EVENT_TYPE``_end_event.is_off()) begin \
``EVENT_TYPE``_end_time = (end_time <= 0) ? $time : end_time; \
``EVENT_TYPE``_end_event.trigger(); \
end \
endfunction \
function bit ``EVENT_TYPE``_began(); \
return ``EVENT_TYPE``_begin_event.is_on(); \
endfunction \
function bit ``EVENT_TYPE``_ended(); \
return ``EVENT_TYPE``_end_event.is_on(); \
endfunction
`tvip_axi_declare_begin_end_event_api(address )
`tvip_axi_declare_begin_end_event_api(write_data)
`tvip_axi_declare_begin_end_event_api(response )
`undef tvip_axi_declare_begin_end_event_api
function bit request_began();
return address_began();
endfunction
function bit request_ended();
if (is_write()) begin
return (address_ended() && write_data_ended()) ? 1 : 0;
end
else begin
return address_ended();
end
endfunction
task wait_for_done();
response_end_event.wait_on();
endtask
task wait_for_request_done();
address_end_event.wait_on();
if (is_write()) begin
write_data_end_event.wait_on();
end
endtask
//--------------------------------------------------------------
// Random constraints for request
//--------------------------------------------------------------
constraint c_valid_id {
(id >> this.configuration.id_width) == 0;
}
constraint c_valid_address {
(address >> this.configuration.address_width) == 0;
}
constraint c_valid_burst_length {
if (this.configuration.protocol == TVIP_AXI4) {
burst_length inside {[1:this.configuration.max_burst_length]};
}
else {
burst_length == 1;
}
}
constraint c_valid_burst_size {
if (this.configuration.protocol == TVIP_AXI4) {
burst_size inside {1, 2, 4, 8, 16, 32, 64, 128};
(8 * burst_size) <= this.configuration.data_width;
}
else {
(8 * burst_size) == this.configuration.data_width;
}
}
constraint c_4kb_boundary {
(
(address & `tvip_axi_4kb_boundary_mask(burst_size)) +
(burst_length * burst_size)
) <= 4096;
}
constraint c_valid_qos {
qos inside {[
this.configuration.qos_range[0]:
this.configuration.qos_range[1]
]};
}
constraint c_valid_write_data {
solve access_type before data;
solve burst_length before data;
(access_type == TVIP_AXI_WRITE_ACCESS) -> data.size() == burst_length;
(access_type == TVIP_AXI_READ_ACCESS ) -> data.size() == 0;
foreach (data[i]) {
(data[i] >> this.configuration.data_width) == 0;
}
}
constraint c_valid_strobe {
solve access_type before strobe;
solve burst_length before strobe;
(access_type == TVIP_AXI_WRITE_ACCESS) -> strobe.size() == burst_length;
(access_type == TVIP_AXI_READ_ACCESS ) -> strobe.size() == 0;
foreach (strobe[i]) {
(strobe[i] >> this.configuration.strobe_width) == 0;
}
}
constraint c_address_start_delay {
`tvip_delay_constraint(start_delay, this.configuration.request_start_delay)
}
constraint c_write_data_delay {
solve access_type, burst_length before write_data_delay;
if (access_type == TVIP_AXI_WRITE_ACCESS) {
write_data_delay.size() == burst_length;
}
else {
write_data_delay.size() == 0;
}
foreach (write_data_delay[i]) {
`tvip_delay_constraint(write_data_delay[i], this.configuration.write_data_delay)
}
}
constraint c_response_ready_delay {
solve access_type, burst_length before response_ready_delay;
if (access_type == TVIP_AXI_WRITE_ACCESS) {
response_ready_delay.size() == 1;
}
else {
response_ready_delay.size() == burst_length;
}
foreach (response_ready_delay[i]) {
if (access_type == TVIP_AXI_WRITE_ACCESS) {
`tvip_delay_constraint(response_ready_delay[i], this.configuration.bready_delay)
}
else {
`tvip_delay_constraint(response_ready_delay[i], this.configuration.rready_delay)
}
}
}
//--------------------------------------------------------------
// Random constraints for response
//--------------------------------------------------------------
constraint c_valid_read_data {
data.size() == burst_length;
foreach (data[i]) {
(data[i] >> this.configuration.data_width) == 0;
}
}
constraint c_valid_response {
(access_type == TVIP_AXI_WRITE_ACCESS) -> response.size() == 1;
(access_type == TVIP_AXI_READ_ACCESS ) -> response.size() == burst_length;
foreach (response[i]) {
response[i] dist {
TVIP_AXI_OKAY := this.configuration.response_weight_okay,
TVIP_AXI_EXOKAY := this.configuration.response_weight_exokay,
TVIP_AXI_SLAVE_ERROR := this.configuration.response_weight_slave_error,
TVIP_AXI_DECODE_ERROR := this.configuration.response_weight_decode_error
};
}
}
constraint c_address_ready_delay {
if (access_type == TVIP_AXI_WRITE_ACCESS) {
`tvip_delay_constraint(address_ready_delay, this.configuration.awready_delay)
}
else {
`tvip_delay_constraint(address_ready_delay, this.configuration.arready_delay)
}
}
constraint c_write_data_ready_delay {
if (access_type == TVIP_AXI_WRITE_ACCESS) {
write_data_ready_delay.size() == burst_length;
}
else {
write_data_ready_delay.size() == 0;
}
foreach (write_data_ready_delay[i]) {
`tvip_delay_constraint(write_data_ready_delay[i], this.configuration.wready_delay)
}
}
constraint c_response_start_delay {
`tvip_delay_constraint(start_delay, this.configuration.response_start_delay)
}
constraint c_response_delay {
if (access_type == TVIP_AXI_WRITE_ACCESS) {
response_delay.size() == 1;
}
else {
response_delay.size() == burst_length;
}
foreach (response_delay[i]) {
`tvip_delay_constraint(response_delay[i], this.configuration.response_delay)
}
}
`uvm_object_utils_begin(tvip_axi_item)
`uvm_field_enum(tvip_axi_access_type, access_type, UVM_DEFAULT)
`uvm_field_int(id, UVM_DEFAULT | UVM_HEX)
`uvm_field_int(address, UVM_DEFAULT | UVM_HEX)
`uvm_field_int(burst_length, UVM_DEFAULT | UVM_DEC)
`uvm_field_int(burst_size, UVM_DEFAULT | UVM_DEC)
`uvm_field_enum(tvip_axi_burst_type, burst_type, UVM_DEFAULT)
`uvm_field_int(qos, UVM_DEFAULT | UVM_DEC)
`uvm_field_array_int(data, UVM_DEFAULT | UVM_HEX)
`uvm_field_array_int(strobe, UVM_DEFAULT | UVM_HEX)
`uvm_field_array_enum(tvip_axi_response, response, UVM_DEFAULT)
`uvm_field_int(start_delay, UVM_DEFAULT | UVM_DEC | UVM_NOCOMPARE)
`uvm_field_array_int(write_data_delay, UVM_DEFAULT | UVM_DEC | UVM_NOCOMPARE)
`uvm_field_array_int(response_delay, UVM_DEFAULT | UVM_DEC | UVM_NOCOMPARE)
`uvm_field_int(address_ready_delay, UVM_DEFAULT | UVM_DEC | UVM_NOCOMPARE)
`uvm_field_array_int(write_data_ready_delay, UVM_DEFAULT | UVM_DEC | UVM_NOCOMPARE)
`uvm_field_array_int(response_ready_delay, UVM_DEFAULT | UVM_DEC | UVM_NOCOMPARE)
`uvm_field_int(address_begin_time, UVM_DEFAULT | UVM_TIME | UVM_NOCOMPARE)
`uvm_field_int(address_end_time, UVM_DEFAULT | UVM_TIME | UVM_NOCOMPARE)
`uvm_field_int(write_data_begin_time, UVM_DEFAULT | UVM_TIME | UVM_NOCOMPARE)
`uvm_field_int(write_data_end_time, UVM_DEFAULT | UVM_TIME | UVM_NOCOMPARE)
`uvm_field_int(response_begin_time, UVM_DEFAULT | UVM_TIME | UVM_NOCOMPARE)
`uvm_field_int(response_end_time, UVM_DEFAULT | UVM_TIME | UVM_NOCOMPARE)
`uvm_field_int(need_response, UVM_DEFAULT | UVM_NOCOMPARE | UVM_NOPRINT)
`uvm_object_utils_end
endclass
class tvip_axi_master_item extends tvip_axi_item;
constraint c_default_need_response {
soft need_response == 0;
}
function void pre_randomize();
super.pre_randomize();
response.rand_mode(0);
response_delay.rand_mode(0);
address_ready_delay.rand_mode(0);
write_data_ready_delay.rand_mode(0);
c_valid_read_data.constraint_mode(0);
c_valid_response.constraint_mode(0);
c_address_ready_delay.constraint_mode(0);
c_write_data_ready_delay.constraint_mode(0);
c_response_start_delay.constraint_mode(0);
c_response_delay.constraint_mode(0);
endfunction
`tue_object_default_constructor(tvip_axi_master_item)
`uvm_object_utils(tvip_axi_master_item)
endclass
class tvip_axi_slave_item extends tvip_axi_item;
constraint c_default_need_response {
soft need_response == 1;
}
function void pre_randomize();
super.pre_randomize();
access_type.rand_mode(0);
id.rand_mode(0);
address.rand_mode(0);
burst_length.rand_mode(0);
burst_size.rand_mode(0);
burst_type.rand_mode(0);
data.rand_mode(is_read());
strobe.rand_mode(0);
write_data_delay.rand_mode(0);
response_ready_delay.rand_mode(0);
c_valid_id.constraint_mode(0);
c_valid_address.constraint_mode(0);
c_valid_burst_length.constraint_mode(0);
c_valid_burst_size.constraint_mode(0);
c_4kb_boundary.constraint_mode(0);
c_valid_qos.constraint_mode(0);
c_valid_write_data.constraint_mode(0);
c_valid_read_data.constraint_mode(is_read());
c_valid_strobe.constraint_mode(0);
c_address_start_delay.constraint_mode(0);
c_write_data_delay.constraint_mode(0);
c_response_ready_delay.constraint_mode(0);
endfunction
`tue_object_default_constructor(tvip_axi_slave_item)
`uvm_object_utils(tvip_axi_slave_item)
endclass
`endif