Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: CSRAccessor.vr | |
4 | // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
5 | // 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
6 | // | |
7 | // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
8 | // | |
9 | // This program is free software; you can redistribute it and/or modify | |
10 | // it under the terms of the GNU General Public License as published by | |
11 | // the Free Software Foundation; version 2 of the License. | |
12 | // | |
13 | // This program is distributed in the hope that it will be useful, | |
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | // GNU General Public License for more details. | |
17 | // | |
18 | // You should have received a copy of the GNU General Public License | |
19 | // along with this program; if not, write to the Free Software | |
20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | // | |
22 | // For the avoidance of doubt, and except that if any non-GPL license | |
23 | // choice is available it will apply instead, Sun elects to use only | |
24 | // the General Public License version 2 (GPLv2) at this time for any | |
25 | // software where a choice of GPL license versions is made | |
26 | // available with the language indicating that GPLv2 or any later version | |
27 | // may be used, or where a choice of which version of the GPL is applied is | |
28 | // otherwise unspecified. | |
29 | // | |
30 | // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
31 | // CA 95054 USA or visit www.sun.com if you need additional information or | |
32 | // have any questions. | |
33 | // | |
34 | // ========== Copyright Header End ============================================ | |
35 | #include "report_macros.vri" | |
36 | ||
37 | class CSRAccessor extends AccessorBase { | |
38 | ||
39 | //================================================= | |
40 | // Constructor | |
41 | //================================================= | |
42 | ||
43 | task new ( CSRState ShadowState, | |
44 | bit [CSRT_ADDR_OFFSET_WIDTH-1:0] input_addr_offset , | |
45 | bit [CSRT_DATA_WIDTH-1:0] input_por_value , | |
46 | bit [CSRT_DATA_WIDTH-1:0] input_rmask , | |
47 | bit [CSRT_DATA_WIDTH-1:0] input_read_only_mask , | |
48 | bit [CSRT_DATA_WIDTH-1:0] input_write_mask , | |
49 | bit [CSRT_DATA_WIDTH-1:0] input_clear_mask , | |
50 | bit [CSRT_DATA_WIDTH-1:0] input_set_mask , | |
51 | bit [CSRT_DATA_WIDTH-1:0] input_toggle_mask , | |
52 | string input_name , | |
53 | integer input_num_fields , | |
54 | CSRAccessMethod input_access_methods[], | |
55 | integer input_access_level[], | |
56 | string input_access_name[], | |
57 | integer input_default_access_method | |
58 | ) { | |
59 | ||
60 | ||
61 | super.new ( ShadowState, | |
62 | input_addr_offset, | |
63 | input_por_value, | |
64 | input_rmask, | |
65 | input_read_only_mask, | |
66 | input_write_mask, | |
67 | input_clear_mask, | |
68 | input_set_mask, | |
69 | input_toggle_mask, | |
70 | input_name, | |
71 | input_num_fields); | |
72 | ||
73 | csr_check_enabled = CSRT_CHECK_ENABLED; | |
74 | ||
75 | set_method_array(input_access_methods, input_access_level, input_access_name); | |
76 | ||
77 | DefaultMethod = input_default_access_method; | |
78 | } // end task new | |
79 | ||
80 | ||
81 | //================================================= | |
82 | // Read function | |
83 | //================================================= | |
84 | function bit [CSRT_DATA_WIDTH-1:0] read (integer method = CSRT_USE_DEFAULT_METHOD){ | |
85 | ||
86 | if (method == CSRT_USE_DEFAULT_METHOD) | |
87 | method = DefaultMethod; | |
88 | ||
89 | ||
90 | QuickReport(CSRReport, RTYP_CSR_DEBUG_1,"CSRAccessor: %s read(): %s register: Addr %0h", | |
91 | get_method_name(method), | |
92 | get_name(), | |
93 | get_addr_offset()); | |
94 | ||
95 | ||
96 | check_method(method); | |
97 | ||
98 | if (method == CSRT_STUB) { | |
99 | QuickReport(CSRReport, RTYP_CSR_DEBUG_1,"CSRAccessor: Stub read of %s register: ", get_name()); | |
100 | } // end if CSRT_STUB | |
101 | else { | |
102 | read = access_methods[method].read(get_addr_offset()); | |
103 | } | |
104 | } // end function read | |
105 | ||
106 | ||
107 | //================================================= | |
108 | // Write task | |
109 | //================================================= | |
110 | task write (bit [CSRT_DATA_WIDTH-1:0] csr_data, integer method = CSRT_USE_DEFAULT_METHOD ){ | |
111 | ||
112 | if (method == CSRT_USE_DEFAULT_METHOD) | |
113 | method = DefaultMethod; | |
114 | ||
115 | QuickReport(CSRReport, RTYP_CSR_DEBUG_1,"CSRAccessor: %s write(): %s register: Addr %0h : data %0h", | |
116 | get_method_name(method), | |
117 | get_name(), | |
118 | get_addr_offset(), | |
119 | csr_data); | |
120 | ||
121 | check_method(method); | |
122 | ||
123 | // Ensure only one modifying transaction per register | |
124 | semaphore_get (WAIT, ShadowState.csr_write_trans_sem, 1); | |
125 | ||
126 | // Perform Hardware Write | |
127 | if (method != CSRT_STUB) | |
128 | access_methods[method].write(get_addr_offset(), csr_data); | |
129 | ||
130 | if (access_level[method] == CSRT_FULL_ACCESS || method == CSRT_OMNI) { | |
131 | update_shadow_data (csr_data); | |
132 | } | |
133 | else if (access_level[method] == CSRT_HW_ACCESS) { | |
134 | //Can not reliably update shadow state when register supports | |
135 | //HW access control. It is up to the user to use set_shadow_csr. | |
136 | //Setting X value will provide a trival match when comparing shadow state | |
137 | update_shadow_data (64'hx); | |
138 | } | |
139 | else | |
140 | QuickReport(CSRReport, RTYP_CSR_ALERT,"CSRAccessor::write: Unable to update shadow state for %s register using current access method ", | |
141 | get_name()); | |
142 | ||
143 | semaphore_put (ShadowState.csr_write_trans_sem, 1); | |
144 | ||
145 | QuickReport(CSRReport, RTYP_CSR_DEBUG_3,"%0d:CSRAccessor::write: %s register:\t%0h\n",get_cycle(),get_name(),csr_data); | |
146 | } // end task write | |
147 | ||
148 | ||
149 | //================================================= | |
150 | // Check Register Function | |
151 | //================================================= | |
152 | // The following change was made on 9/21/01 -RFT | |
153 | // This function should really be based on a wild card match, allowing | |
154 | // a don't care setting for the shadow data. This is necessary for registers | |
155 | // that don't have a specific POR value because they are not connected to | |
156 | // reset. | |
157 | // | |
158 | function integer check_register (integer method = CSRT_USE_DEFAULT_METHOD) { | |
159 | ||
160 | bit [CSRT_DATA_WIDTH-1:0] actual_data; | |
161 | bit [CSRT_DATA_WIDTH-1:0] expected_data; | |
162 | bit [CSRT_DATA_WIDTH-1:0] diff_vector = 64'h0; | |
163 | integer index = 0; | |
164 | bit success = 1; | |
165 | ||
166 | if (method == CSRT_USE_DEFAULT_METHOD) | |
167 | method = DefaultMethod; | |
168 | ||
169 | if (csr_check_enabled) { | |
170 | printf("inside csr_check_enabled \n"); | |
171 | actual_data = read(method); | |
172 | expected_data = get_shadow_data(); | |
173 | ||
174 | while (index < CSRT_DATA_WIDTH) { | |
175 | ||
176 | //If expected_data indicates a wildcard, then skip comparison | |
177 | if (expected_data[index] !== 1'bx) | |
178 | if (actual_data[index] !== expected_data[index]) { | |
179 | diff_vector[index] = 1'b1; | |
180 | success = 1'b0; | |
181 | } | |
182 | ||
183 | ++index; | |
184 | } | |
185 | // After the actual data is screened for X's it is okay to apply a wildcard | |
186 | // comparision. This allows expected data to contain the wildcards. | |
187 | if (!success) { | |
188 | ||
189 | //These are not report calls because there is no good way to print leading | |
190 | //zeros in data without printing 512 bits by default. | |
191 | QuickReport(CSRReport, RTYP_CSR_ERROR, "CSRAccessor::check_register:ERROR - %s REGISTER MISMATCHED.", | |
192 | get_name() ); | |
193 | printf("\tACTUAL = 64'h%h\n\tEXPECTED = 64'h%h\n\tDiff Vector = 64'h%h\n", | |
194 | actual_data, | |
195 | expected_data, | |
196 | diff_vector); | |
197 | ||
198 | check_register = CSRT_MISMATCH_RETURN_CODE; | |
199 | } | |
200 | else | |
201 | check_register = CSRT_SUCCESSFUL_RETURN_CODE; | |
202 | printf("Data match: \tACTUAL = 64'h%h\n\tEXPECTED = 64'h%h\n\t", | |
203 | actual_data, | |
204 | expected_data); | |
205 | } //check enabled | |
206 | ||
207 | else { | |
208 | QuickReport(CSRReport, RTYP_CSR_ALERT,"CSR %s REGISTER CHECKING DISABLED", get_name()); | |
209 | check_register = CSRT_SUCCESSFUL_RETURN_CODE; | |
210 | } | |
211 | } // end function check_register | |
212 | ||
213 | ||
214 | //================================================= | |
215 | // Reset Task | |
216 | //================================================= | |
217 | ||
218 | task reset () { | |
219 | ||
220 | QuickReport(CSRReport, RTYP_CSR_DEBUG_3,"%0d:CSRAccessor::reset: %s register\t%0h", | |
221 | get_cycle(),get_name(),get_por_value()); | |
222 | ||
223 | semaphore_get (WAIT, ShadowState.csr_write_trans_sem, 1); | |
224 | set_shadow_data(get_por_value()); | |
225 | semaphore_put (ShadowState.csr_write_trans_sem, 1); | |
226 | } // end task reset | |
227 | ||
228 | ||
229 | //================================================= | |
230 | // Read Field Function | |
231 | //================================================= | |
232 | function bit [CSRT_DATA_WIDTH-1:0] read_field ( integer field_id, | |
233 | integer method = CSRT_USE_DEFAULT_METHOD) { | |
234 | bit [CSRT_DATA_WIDTH-1:0] temp_data; | |
235 | ||
236 | if (method == CSRT_USE_DEFAULT_METHOD) | |
237 | method = DefaultMethod; | |
238 | ||
239 | if (field_id < get_max_num_fields()) { | |
240 | QuickReport(CSRReport, RTYP_CSR_DEBUG_3,"%0d:CSR read_field(): %s register %s field:\t%0h", | |
241 | get_cycle(),get_name(),reg_field[field_id].get_field_name(),read_field); | |
242 | ||
243 | temp_data = read(method); | |
244 | temp_data = temp_data & reg_field[field_id].get_field_mask(); | |
245 | temp_data = temp_data >> reg_field[field_id].get_field_position(); | |
246 | read_field = temp_data; | |
247 | } | |
248 | else { | |
249 | QuickReport(CSRReport, RTYP_CSR_ERROR, "CSRAccessor::read_field: Invalid field_id %0h", field_id); | |
250 | } | |
251 | } // end function read_field | |
252 | ||
253 | ||
254 | //================================================= | |
255 | // Write Field Task | |
256 | //================================================= | |
257 | task write_field ( integer field_id, | |
258 | bit [CSRT_DATA_WIDTH-1:0] field_data, | |
259 | integer method = CSRT_USE_DEFAULT_METHOD ) { | |
260 | ||
261 | bit [CSRT_DATA_WIDTH-1:0] curr_data; | |
262 | bit [CSRT_DATA_WIDTH-1:0] revised_data; | |
263 | bit [CSRT_DATA_WIDTH-1:0] field_positioned_data; | |
264 | bit [CSRT_DATA_WIDTH-1:0] zero_field_mask; | |
265 | bit [CSRT_DATA_WIDTH-1:0] refresh_bit_mask; | |
266 | ||
267 | if (method == CSRT_USE_DEFAULT_METHOD) | |
268 | method = DefaultMethod; | |
269 | ||
270 | if (field_id < get_max_num_fields()) { | |
271 | ||
272 | QuickReport(CSRReport, RTYP_CSR_DEBUG_3,"%0d:CSR write_field(): %s register %s field:\t%0h", | |
273 | get_cycle(),get_name(),reg_field[field_id].get_field_name(),field_data); | |
274 | ||
275 | ||
276 | semaphore_get (WAIT, ShadowState.csr_write_trans_sem, 1); | |
277 | ||
278 | field_positioned_data = reg_field[field_id].get_field_mask() & (field_data << reg_field[field_id].get_field_position()); | |
279 | curr_data = read(method); | |
280 | zero_field_mask = ~(reg_field[field_id].get_field_mask()); | |
281 | refresh_bit_mask = zero_field_mask & get_write_mask (); | |
282 | revised_data = (curr_data & refresh_bit_mask) | field_positioned_data; | |
283 | ||
284 | if (access_level[method] == CSRT_FULL_ACCESS || method == CSRT_OMNI) { | |
285 | update_shadow_data (revised_data); | |
286 | } | |
287 | else if (access_level[method] == CSRT_HW_ACCESS) { | |
288 | //Can not reliably update shadow state when register supports | |
289 | //HW access control. It is up to the user to use set_shadow_csr. | |
290 | //Setting X value will provide a trival match when comparing shadow state | |
291 | update_shadow_data (64'hx); | |
292 | } | |
293 | else | |
294 | QuickReport(CSRReport, RTYP_CSR_ALERT,"CSRAccessor::write_field: Unable to update shadow state for %s register using current access method ", | |
295 | get_name()); | |
296 | ||
297 | access_methods[method].write(get_addr_offset(), revised_data); | |
298 | ||
299 | semaphore_put (ShadowState.csr_write_trans_sem, 1); | |
300 | } | |
301 | else { | |
302 | QuickReport(CSRReport, RTYP_CSR_ERROR, "CSRAccessor::write_field: Invalid field_id %0h", field_id); | |
303 | } | |
304 | } // end task write_field | |
305 | ||
306 | ||
307 | //================================================= | |
308 | // Write Fields Task | |
309 | //================================================= | |
310 | task write_fields(CSRFieldAggregate field_aggregate, integer method = CSRT_USE_DEFAULT_METHOD, bit use_method_read = 0) { | |
311 | bit [CSRT_DATA_WIDTH-1:0] curr_data; | |
312 | bit [CSRT_DATA_WIDTH-1:0] revised_data; | |
313 | bit [CSRT_DATA_WIDTH-1:0] field_positioned_data = 0; | |
314 | bit [CSRT_DATA_WIDTH-1:0] zero_field_mask = 0; | |
315 | bit [CSRT_DATA_WIDTH-1:0] refresh_bit_mask = 0; | |
316 | ||
317 | CSRAggregateContainer field_container; | |
318 | ||
319 | zero_field_mask = ~zero_field_mask; | |
320 | ||
321 | if (method == CSRT_USE_DEFAULT_METHOD) | |
322 | method = DefaultMethod; | |
323 | ||
324 | semaphore_get (WAIT, ShadowState.csr_write_trans_sem, 1); | |
325 | ||
326 | if (use_method_read) | |
327 | curr_data = read(method); | |
328 | else | |
329 | curr_data = get_shadow_data(); | |
330 | ||
331 | field_container = field_aggregate.pop(); | |
332 | ||
333 | while (field_container != null) { | |
334 | if (field_container.field_id < get_max_num_fields()) { | |
335 | ||
336 | // CSRReport.report(RTYP_INFO,"%0d:CSR write_fields(): %s register %s field:\t%0h\n", get_cycle(), get_name(), | |
337 | // reg_field[field_container.field_id].get_field_name(), field_container.field_data); | |
338 | ||
339 | field_positioned_data |= (reg_field[field_container.field_id].get_field_mask() & | |
340 | (field_container.field_data << reg_field[field_container.field_id].get_field_position())); | |
341 | zero_field_mask &= ~(reg_field[field_container.field_id].get_field_mask()); | |
342 | refresh_bit_mask |= zero_field_mask & get_write_mask(); | |
343 | } else { | |
344 | QuickReport(CSRReport, RTYP_CSR_ERROR, "CSRAccessor::write_fields: Invalid field_id %0h", field_container.field_id); | |
345 | } | |
346 | field_container = field_aggregate.pop(); | |
347 | } | |
348 | ||
349 | revised_data = (curr_data & refresh_bit_mask) | field_positioned_data; | |
350 | ||
351 | if (access_level[method] == CSRT_FULL_ACCESS || method == CSRT_OMNI) { | |
352 | update_shadow_data (revised_data); | |
353 | } else if (access_level[method] == CSRT_HW_ACCESS) { | |
354 | //Can not reliably update shadow state when register supports HW access control. It is up to the user to use set_shadow_csr. | |
355 | //Setting X value will provide a trival match when comparing shadow state | |
356 | update_shadow_data (64'hx); | |
357 | } else | |
358 | QuickReport(CSRReport, RTYP_CSR_ALERT,"CSRAccessor: (write_fields) Unable to update shadow state for %s register using current access method", | |
359 | get_name()); | |
360 | ||
361 | if (curr_data !== revised_data) { | |
362 | QuickReport(CSRReport, RTYP_CSR_DEBUG_1,"CSRAccessor: %s write_fields(): %s register: Addr %0h : data %0h", get_method_name(method), get_name(), | |
363 | get_addr_offset(), revised_data); | |
364 | access_methods[method].write(get_addr_offset(), revised_data); | |
365 | } else { | |
366 | QuickReport(CSRReport, RTYP_CSR_DEBUG_1,"CSRAccessor: %s write_fields(): %s register: Addr %0h : data %0h %s", get_method_name(method), | |
367 | get_name(), get_addr_offset(), revised_data, " -- Not writing due to current_data == new_data"); | |
368 | } | |
369 | ||
370 | semaphore_put (ShadowState.csr_write_trans_sem, 1); | |
371 | } // end task write_fields | |
372 | ||
373 | ||
374 | //================================================= | |
375 | // Set Shadow CSR Task | |
376 | //================================================= | |
377 | task set_shadow_csr(bit [CSRT_DATA_WIDTH-1:0] new_data, integer field_id = -1) { | |
378 | bit [CSRT_DATA_WIDTH-1:0] curr_data; | |
379 | bit [CSRT_DATA_WIDTH-1:0] revised_data; | |
380 | bit [CSRT_DATA_WIDTH-1:0] field_positioned_data; | |
381 | bit [CSRT_DATA_WIDTH-1:0] zero_field_mask; | |
382 | ||
383 | semaphore_get (WAIT, ShadowState.csr_write_trans_sem, 1); | |
384 | ||
385 | QuickReport(CSRReport, RTYP_CSR_DEBUG_1, "CSRAccessor: set_shadow_csr(): %s register: Addr %0h : data %0h", | |
386 | get_name(), get_addr_offset(), new_data); | |
387 | ||
388 | if (field_id == -1) | |
389 | //No field specfied - set entire CSR | |
390 | set_shadow_data (new_data); | |
391 | else { | |
392 | if (field_id < get_max_num_fields()) { | |
393 | field_positioned_data = reg_field[field_id].get_field_mask() & (new_data << reg_field[field_id].get_field_position()); | |
394 | curr_data = get_shadow_data(); | |
395 | zero_field_mask = ~(reg_field[field_id].get_field_mask()); | |
396 | revised_data = (curr_data & zero_field_mask) | field_positioned_data; | |
397 | set_shadow_data (revised_data); | |
398 | } | |
399 | else | |
400 | QuickReport(CSRReport, RTYP_CSR_ALERT,"CSRAccessor::set_shadow_csr: Field ID out of range\n"); | |
401 | } | |
402 | ||
403 | semaphore_put (ShadowState.csr_write_trans_sem, 1); | |
404 | } // end task set_shadow_csr() | |
405 | ||
406 | ||
407 | //================================================= | |
408 | // Get Shadow CSR Function | |
409 | //================================================= | |
410 | function bit [CSRT_DATA_WIDTH-1:0] get_shadow_csr(integer field_id = -1) { | |
411 | bit [CSRT_DATA_WIDTH-1:0] temp_data; | |
412 | ||
413 | QuickReport(CSRReport, RTYP_CSR_DEBUG_1, "CSRAccessor: get_shadow_csr(): %s register: Addr %0h", get_name(), get_addr_offset()); | |
414 | ||
415 | if (field_id == -1) | |
416 | //No field specfied - return entire CSR | |
417 | get_shadow_csr = get_shadow_data(); | |
418 | else { | |
419 | temp_data = get_shadow_data(); | |
420 | temp_data = temp_data & reg_field[field_id].get_field_mask(); | |
421 | temp_data = temp_data >> reg_field[field_id].get_field_position(); | |
422 | get_shadow_csr = temp_data; | |
423 | } | |
424 | } // end function get_shadow_csr() | |
425 | ||
426 | } // end class CSRAccessor | |
427 | ||
428 | ||
429 |