1 |
16 |
HanySalah |
//
|
2 |
|
|
// -------------------------------------------------------------
|
3 |
|
|
// Copyright 2010-2011 Mentor Graphics Corporation
|
4 |
|
|
// All Rights Reserved Worldwide
|
5 |
|
|
//
|
6 |
|
|
// Licensed under the Apache License, Version 2.0 (the
|
7 |
|
|
// "License"); you may not use this file except in
|
8 |
|
|
// compliance with the License. You may obtain a copy of
|
9 |
|
|
// the License at
|
10 |
|
|
//
|
11 |
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
12 |
|
|
//
|
13 |
|
|
// Unless required by applicable law or agreed to in
|
14 |
|
|
// writing, software distributed under the License is
|
15 |
|
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
16 |
|
|
// CONDITIONS OF ANY KIND, either express or implied. See
|
17 |
|
|
// the License for the specific language governing
|
18 |
|
|
// permissions and limitations under the License.
|
19 |
|
|
// -------------------------------------------------------------
|
20 |
|
|
//
|
21 |
|
|
|
22 |
|
|
|
23 |
|
|
//------------------------------------------------------------------------------
|
24 |
|
|
// Class: uvm_reg_fifo
|
25 |
|
|
//
|
26 |
|
|
// This special register models a DUT FIFO accessed via write/read,
|
27 |
|
|
// where writes push to the FIFO and reads pop from it.
|
28 |
|
|
//
|
29 |
|
|
// Backdoor access is not enabled, as it is not yet possible to force
|
30 |
|
|
// complete FIFO state, i.e. the write and read indexes used to access
|
31 |
|
|
// the FIFO data.
|
32 |
|
|
//
|
33 |
|
|
//------------------------------------------------------------------------------
|
34 |
|
|
|
35 |
|
|
class uvm_reg_fifo extends uvm_reg;
|
36 |
|
|
|
37 |
|
|
local uvm_reg_field value;
|
38 |
|
|
local int m_set_cnt;
|
39 |
|
|
local int unsigned m_size;
|
40 |
|
|
|
41 |
|
|
// Variable: fifo
|
42 |
|
|
//
|
43 |
|
|
// The abstract representation of the FIFO. Constrained
|
44 |
|
|
// to be no larger than the size parameter. It is public
|
45 |
|
|
// to enable subtypes to add constraints on it and randomize.
|
46 |
|
|
//
|
47 |
|
|
rand uvm_reg_data_t fifo[$];
|
48 |
|
|
|
49 |
|
|
constraint valid_fifo_size {
|
50 |
|
|
fifo.size() <= m_size;
|
51 |
|
|
}
|
52 |
|
|
|
53 |
|
|
|
54 |
|
|
//----------------------
|
55 |
|
|
// Group: Initialization
|
56 |
|
|
//----------------------
|
57 |
|
|
|
58 |
|
|
// Function: new
|
59 |
|
|
//
|
60 |
|
|
// Creates an instance of a FIFO register having ~size~ elements of
|
61 |
|
|
// ~n_bits~ each.
|
62 |
|
|
//
|
63 |
|
|
function new(string name = "reg_fifo",
|
64 |
|
|
int unsigned size,
|
65 |
|
|
int unsigned n_bits,
|
66 |
|
|
int has_cover);
|
67 |
|
|
super.new(name,n_bits,has_cover);
|
68 |
|
|
m_size = size;
|
69 |
|
|
endfunction
|
70 |
|
|
|
71 |
|
|
|
72 |
|
|
// Funtion: build
|
73 |
|
|
//
|
74 |
|
|
// Builds the abstract FIFO register object. Called by
|
75 |
|
|
// the instantiating block, a subtype.
|
76 |
|
|
//
|
77 |
|
|
virtual function void build();
|
78 |
|
|
value = uvm_reg_field::type_id::create("value");
|
79 |
|
|
value.configure(this, get_n_bits(), 0, "RW", 0, 32'h0, 1, 0, 1);
|
80 |
|
|
endfunction
|
81 |
|
|
|
82 |
|
|
|
83 |
|
|
// Function: set_compare
|
84 |
|
|
//
|
85 |
|
|
// Sets the compare policy during a mirror (read) of the DUT FIFO.
|
86 |
|
|
// The DUT read value is checked against its mirror only when both the
|
87 |
|
|
// ~check~ argument in the call and the compare policy
|
88 |
|
|
// for the field is .
|
89 |
|
|
//
|
90 |
|
|
function void set_compare(uvm_check_e check=UVM_CHECK);
|
91 |
|
|
value.set_compare(check);
|
92 |
|
|
endfunction
|
93 |
|
|
|
94 |
|
|
|
95 |
|
|
//---------------------
|
96 |
|
|
// Group: Introspection
|
97 |
|
|
//---------------------
|
98 |
|
|
|
99 |
|
|
// Function: size
|
100 |
|
|
//
|
101 |
|
|
// The number of entries currently in the FIFO.
|
102 |
|
|
//
|
103 |
|
|
function int unsigned size();
|
104 |
|
|
return fifo.size();
|
105 |
|
|
endfunction
|
106 |
|
|
|
107 |
|
|
|
108 |
|
|
// Function: capacity
|
109 |
|
|
//
|
110 |
|
|
// The maximum number of entries, or depth, of the FIFO.
|
111 |
|
|
|
112 |
|
|
function int unsigned capacity();
|
113 |
|
|
return m_size;
|
114 |
|
|
endfunction
|
115 |
|
|
|
116 |
|
|
|
117 |
|
|
//--------------
|
118 |
|
|
// Group: Access
|
119 |
|
|
//--------------
|
120 |
|
|
|
121 |
|
|
// Function: write
|
122 |
|
|
//
|
123 |
|
|
// Pushes the given value to the DUT FIFO. If auto-prediction is enabled,
|
124 |
|
|
// the written value is also pushed to the abstract FIFO before the
|
125 |
|
|
// call returns. If auto-prediction is not enabled (via
|
126 |
|
|
// ), the value is pushed to abstract
|
127 |
|
|
// FIFO only when the write operation is observed on the target bus.
|
128 |
|
|
// This mode requires using the class.
|
129 |
|
|
// If the write is via an operation, the abstract FIFO
|
130 |
|
|
// already contains the written value and is thus not affected by
|
131 |
|
|
// either prediction mode.
|
132 |
|
|
|
133 |
|
|
|
134 |
|
|
// Function: read
|
135 |
|
|
//
|
136 |
|
|
// Reads the next value out of the DUT FIFO. If auto-prediction is
|
137 |
|
|
// enabled, the frontmost value in abstract FIFO is popped.
|
138 |
|
|
|
139 |
|
|
|
140 |
|
|
// Function: set
|
141 |
|
|
//
|
142 |
|
|
// Pushes the given value to the abstract FIFO. You may call this
|
143 |
|
|
// method several times before an as a means of preloading
|
144 |
|
|
// the DUT FIFO. Calls to ~set()~ to a full FIFO are ignored. You
|
145 |
|
|
// must call to update the DUT FIFO with your set values.
|
146 |
|
|
//
|
147 |
|
|
virtual function void set(uvm_reg_data_t value,
|
148 |
|
|
string fname = "",
|
149 |
|
|
int lineno = 0);
|
150 |
|
|
// emulate write, with intention of update
|
151 |
|
|
value &= ((1 << get_n_bits())-1);
|
152 |
|
|
if (fifo.size() == m_size) begin
|
153 |
|
|
return;
|
154 |
|
|
end
|
155 |
|
|
super.set(value,fname,lineno);
|
156 |
|
|
m_set_cnt++;
|
157 |
|
|
fifo.push_back(this.value.value);
|
158 |
|
|
endfunction
|
159 |
|
|
|
160 |
|
|
|
161 |
|
|
// Function: update
|
162 |
|
|
//
|
163 |
|
|
// Pushes (writes) all values preloaded using to the DUT.
|
164 |
|
|
// You must ~update~ after ~set~ before any blocking statements,
|
165 |
|
|
// else other reads/writes to the DUT FIFO may cause the mirror to
|
166 |
|
|
// become out of sync with the DUT.
|
167 |
|
|
//
|
168 |
|
|
virtual task update(output uvm_status_e status,
|
169 |
|
|
input uvm_path_e path = UVM_DEFAULT_PATH,
|
170 |
|
|
input uvm_reg_map map = null,
|
171 |
|
|
input uvm_sequence_base parent = null,
|
172 |
|
|
input int prior = -1,
|
173 |
|
|
input uvm_object extension = null,
|
174 |
|
|
input string fname = "",
|
175 |
|
|
input int lineno = 0);
|
176 |
|
|
uvm_reg_data_t upd;
|
177 |
|
|
if (!m_set_cnt || fifo.size() == 0)
|
178 |
|
|
return;
|
179 |
|
|
m_update_in_progress = 1;
|
180 |
|
|
for (int i=fifo.size()-m_set_cnt; m_set_cnt > 0; i++, m_set_cnt--) begin
|
181 |
|
|
if (i >= 0) begin
|
182 |
|
|
//uvm_reg_data_t val = get();
|
183 |
|
|
//super.update(status,path,map,parent,prior,extension,fname,lineno);
|
184 |
|
|
write(status,fifo[i],path,map,parent,prior,extension,fname,lineno);
|
185 |
|
|
end
|
186 |
|
|
end
|
187 |
|
|
m_update_in_progress = 0;
|
188 |
|
|
endtask
|
189 |
|
|
|
190 |
|
|
|
191 |
|
|
// Function: mirror
|
192 |
|
|
//
|
193 |
|
|
// Reads the next value out of the DUT FIFO. If auto-prediction is
|
194 |
|
|
// enabled, the frontmost value in abstract FIFO is popped. If
|
195 |
|
|
// the ~check~ argument is set and comparison is enabled with
|
196 |
|
|
// .
|
197 |
|
|
|
198 |
|
|
|
199 |
|
|
// Function: get
|
200 |
|
|
//
|
201 |
|
|
// Returns the next value from the abstract FIFO, but does not pop it.
|
202 |
|
|
// Used to get the expected value in a operation.
|
203 |
|
|
//
|
204 |
|
|
virtual function uvm_reg_data_t get(string fname="", int lineno=0);
|
205 |
|
|
//return fifo.pop_front();
|
206 |
|
|
return fifo[0];
|
207 |
|
|
endfunction
|
208 |
|
|
|
209 |
|
|
|
210 |
|
|
// Function: do_predict
|
211 |
|
|
//
|
212 |
|
|
// Updates the abstract (mirror) FIFO based on and
|
213 |
|
|
// operations. When auto-prediction is on, this method
|
214 |
|
|
// is called before each read, write, peek, or poke operation returns.
|
215 |
|
|
// When auto-prediction is off, this method is called by a
|
216 |
|
|
// upon receipt and conversion of an observed bus
|
217 |
|
|
// operation to this register.
|
218 |
|
|
//
|
219 |
|
|
// If a write prediction, the observed
|
220 |
|
|
// write value is pushed to the abstract FIFO as long as it is
|
221 |
|
|
// not full and the operation did not originate from an .
|
222 |
|
|
// If a read prediction, the observed read value is compared
|
223 |
|
|
// with the frontmost value in the abstract FIFO if
|
224 |
|
|
// enabled comparison and the FIFO is not empty.
|
225 |
|
|
//
|
226 |
|
|
virtual function void do_predict(uvm_reg_item rw,
|
227 |
|
|
uvm_predict_e kind = UVM_PREDICT_DIRECT,
|
228 |
|
|
uvm_reg_byte_en_t be = -1);
|
229 |
|
|
|
230 |
|
|
super.do_predict(rw,kind,be);
|
231 |
|
|
|
232 |
|
|
if (rw.status == UVM_NOT_OK)
|
233 |
|
|
return;
|
234 |
|
|
|
235 |
|
|
case (kind)
|
236 |
|
|
|
237 |
|
|
UVM_PREDICT_WRITE,
|
238 |
|
|
UVM_PREDICT_DIRECT:
|
239 |
|
|
begin
|
240 |
|
|
if (fifo.size() != m_size && !m_update_in_progress)
|
241 |
|
|
fifo.push_back(this.value.value);
|
242 |
|
|
end
|
243 |
|
|
|
244 |
|
|
UVM_PREDICT_READ:
|
245 |
|
|
begin
|
246 |
|
|
uvm_reg_data_t value = rw.value[0] & ((1 << get_n_bits())-1);
|
247 |
|
|
uvm_reg_data_t mirror_val;
|
248 |
|
|
if (fifo.size() == 0) begin
|
249 |
|
|
return;
|
250 |
|
|
end
|
251 |
|
|
mirror_val = fifo.pop_front();
|
252 |
|
|
if (this.value.get_compare() == UVM_CHECK && mirror_val != value) begin
|
253 |
|
|
`uvm_warning("MIRROR_MISMATCH",
|
254 |
|
|
$sformatf("Observed DUT read value 'h%0h != mirror value 'h%0h",value,mirror_val))
|
255 |
|
|
end
|
256 |
|
|
end
|
257 |
|
|
|
258 |
|
|
endcase
|
259 |
|
|
|
260 |
|
|
endfunction
|
261 |
|
|
|
262 |
|
|
|
263 |
|
|
// Group: Special Overrides
|
264 |
|
|
|
265 |
|
|
// Task: pre_write
|
266 |
|
|
//
|
267 |
|
|
// Special pre-processing for a or .
|
268 |
|
|
// Called as a result of a or . It is an error to
|
269 |
|
|
// attempt a write to a full FIFO or a write while an update is still
|
270 |
|
|
// pending. An update is pending after one or more calls to .
|
271 |
|
|
// If in your application the DUT allows writes to a full FIFO, you
|
272 |
|
|
// must override ~pre_write~ as appropriate.
|
273 |
|
|
//
|
274 |
|
|
virtual task pre_write(uvm_reg_item rw);
|
275 |
|
|
if (m_set_cnt && !m_update_in_progress) begin
|
276 |
|
|
`uvm_error("Needs Update","Must call update() after set() and before write()")
|
277 |
|
|
rw.status = UVM_NOT_OK;
|
278 |
|
|
return;
|
279 |
|
|
end
|
280 |
|
|
if (fifo.size() >= m_size && !m_update_in_progress) begin
|
281 |
|
|
`uvm_error("FIFO Full","Write to full FIFO ignored")
|
282 |
|
|
rw.status = UVM_NOT_OK;
|
283 |
|
|
return;
|
284 |
|
|
end
|
285 |
|
|
endtask
|
286 |
|
|
|
287 |
|
|
|
288 |
|
|
// Task: pre_read
|
289 |
|
|
//
|
290 |
|
|
// Special post-processing for a or .
|
291 |
|
|
// Aborts the operation if the internal FIFO is empty. If in your application
|
292 |
|
|
// the DUT does not behave this way, you must override ~pre_write~ as
|
293 |
|
|
// appropriate.
|
294 |
|
|
//
|
295 |
|
|
//
|
296 |
|
|
virtual task pre_read(uvm_reg_item rw);
|
297 |
|
|
// abort if fifo empty
|
298 |
|
|
if (fifo.size() == 0) begin
|
299 |
|
|
rw.status = UVM_NOT_OK;
|
300 |
|
|
return;
|
301 |
|
|
end
|
302 |
|
|
endtask
|
303 |
|
|
|
304 |
|
|
|
305 |
|
|
function void post_randomize();
|
306 |
|
|
m_set_cnt = 0;
|
307 |
|
|
endfunction
|
308 |
|
|
|
309 |
|
|
endclass
|
310 |
|
|
|