Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / common / vera / classes / memArray.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: memArray.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 <vera_defines.vrh>
36#include "std_display_defines.vri"
37#include "std_display_class.vrh"
38#include <baseUtilsClass.vrh>
39
40
41//////////////////////////////////////////////////////
42// Stuff that Will change with data width
43//////////////////////////////////////////////////////
44
45#define BYTE_LANES 8
46
47// high order bits
48#define MEM_BM 7
49#define MEM_DATA 63
50#define MEM_ADDR 39
51#define MEM_ECC 7
52
53// low order bits
54// Array is 8 byte addressed, NOT byte addressed!!!
55#define MASK_EBW 64'hfffffffffffffff8
56#define MASK_128 64'hfffffffffffffff0
57#define MASK_512 64'hffffffffffffffc0
58
59#define RAND_DATA {urandom(),urandom()}
60//#define DEFAULT_DATA 64'ha5a5a5a5a5a5a5a5 // breaks sparc model since it uses 0
61#define DEFAULT_DATA 0
62
63#define STD_DISP dbg
64
65//#define MEMARRAY_DEBUG 1
66
67class MemArray {
68
69 local reg [MEM_DATA:0] mainMem[]; // Array is 8 byte addressed, NOT byte addressed!!!
70 local StandardDisplay dbg;
71 local reg returnRandom = 0; // return random data for uninitialized address
72 local reg shft;
73 // general lock
74 local integer semaLock;
75
76 task new (reg shift=0, StandardDisplay dbgin, reg retnRandom=0)
77 {
78 this.dbg = dbgin;
79 this.returnRandom = retnRandom;
80 this.shft = shift;
81 semaLock = alloc( SEMAPHORE, 0, 1, 1 );
82 }
83
84 //----------------------------------------------------------
85 // read mem.image and store them into mainMem
86
87 task loadMem (string mem_data, reg loadOnlyIOmem = 0,
88 reg hash_on = 0, BaseUtils utils = null)
89 {
90 integer fdi;
91 string line, val;
92 reg [63:0] addr;
93 reg [63:0] data;
94
95 PR_NORMAL("loadMainMem", MON_NORMAL,
96 psprintf("Loading mainMem from file = %s (loadOnlyIOmem=%0d)", mem_data, loadOnlyIOmem));
97 if (hash_on) {
98 PR_NORMAL("loadMainMem", MON_NORMAL,
99 psprintf("L2 Index Hash is ON"));
100 }
101 if (hash_on && utils == null) {
102 PR_ERROR("loadMainMem", MON_ERROR,
103 psprintf("L2 Index Hash is ON but BaseUtils handle is null! Need handle!"));
104 }
105
106 fdi = fopen (mem_data, "r");
107 if (fdi == 0) error ("Can't open input file\n");
108
109 while (1) {
110 line = freadstr (fdi, RAWIN); // NTB needs RAWIN
111 if (line == null) break;
112 if(line.match("^\s*$"))continue; // empty line
113 if(line.match("^\s*//.*"))continue; // 0 or more blanks then // (comment line)
114 if(line.match("^@(\w+)")){ // @ in first column
115 val = line.backref(0);
116 addr = val.atohex();
117 if (shft) addr = addr >> 3;
118 continue; // have address, now get data lines, if any
119 }
120 //while(line.match("\s*(\w+)")){
121 while(line.match("\s*([0-9a-fA-F]+)")){ // hex number
122 val = line.backref(0);
123 data = val.atohex();
124 if ((loadOnlyIOmem && addr[39]) || !loadOnlyIOmem) {
125 // I/O Address are not hashed
126 if (hash_on & (addr[39]==1'b0)) {
127 mainMem[utils.hashpa(addr)] = data;
128 PR_DEBUG("loadMainMem", MON_DEBUG,
129 psprintf("Loading %x into %x", data, utils.hashpa(addr)));
130 } else {
131 mainMem[addr] = data;
132 PR_DEBUG("loadMainMem", MON_DEBUG,
133 psprintf("Loading %x into %x", data, addr));
134 }
135
136 }
137 line = line.postmatch();
138 if(shft)addr++;
139 else addr += 8;
140 }
141 }
142 fclose (fdi);
143 printf("");
144 }
145
146 //----------------------------------------------------------
147 // Dump Memory contents to specified file
148 // (ported from N1)
149 //
150 task dump_mem(string filename, reg [MEM_ADDR:0] addr, integer num, reg shft)
151 {
152 integer fp, w_num;
153
154 addr = addr & MASK_EBW;
155
156 PR_NORMAL("dump_mem", MON_NORMAL,
157 psprintf("Dumping mainMem to file = %s ", filename));
158
159 if (shft) {
160 addr = addr >> 3;
161 }
162 fp = fopen (filename, "w");
163 w_num = 0;
164 fprintf(fp, "=============================\n");
165 fprintf(fp, " ADDRESS : DATA\n");
166 fprintf(fp, "=============================\n");
167 while(w_num < num){
168 fprintf(fp, "%x : %x\n", addr, mainMem[addr]);
169 if (shft) {
170 addr = addr + 1;
171 } else {
172 addr = addr + 8;
173 }
174 w_num += 8;
175 }
176 fclose(fp);
177 }
178
179 //----------------------------------------------------------
180 // Write 64 bit word to memory
181 task write_mem (reg [MEM_ADDR:0] addr, reg [MEM_DATA:0] data, integer id = 0) {
182 semaphore_get( WAIT, semaLock , 1 );
183 addr = addr & MASK_EBW;
184 mainMem[addr] = data;
185#ifdef MEMARRAY_DEBUG
186 printf("%0d MemArray::write_mem [%0d] addr=%h, data=%h\n",get_cycle(),id,addr,data);
187 dumpMem({addr[MEM_ADDR:6],6'b000000},8); // L2 block size
188#endif
189 semaphore_put( semaLock , 1 );
190 }
191
192
193 //----------------------------------------------------------
194 // Masked write
195 task writeBM(bit [MEM_ADDR:0] addr,
196 bit [MEM_DATA:0] data,
197 bit [MEM_BM:0] byteMask,
198 integer id = 0) {
199
200 bit [MEM_DATA:0] tmpData, mem_out, memMask, tmp;
201 integer i;
202
203 semaphore_get( WAIT, semaLock , 1 );
204 addr = addr & MASK_EBW;
205
206 // build up a mask as wide as the data.
207 // if mask is "all bytes" then call the faster write() task.
208 if (byteMask == ~0)
209 {
210 semaphore_put( semaLock , 1 );
211 this.write_mem(addr,data,id);
212 return;
213 }
214 else
215 {
216 memMask = 0;
217 for (i = MEM_BM ; i >= 0 ; i--)
218 {
219 if (byteMask[i] == 1) memMask = {memMask, 8'hFF};
220 else memMask = {memMask, 8'h00};
221 }
222 }
223
224 if (assoc_index(CHECK,mainMem,addr))
225 {
226 tmp = mainMem[addr];
227 mem_out = tmp[MEM_DATA:0];
228 }
229 else // adress never written
230 {
231 if (returnRandom) mem_out = RAND_DATA;
232 else mem_out = 64'h0;
233 }
234
235 // merge in selected data bytes
236 tmpData = ( mem_out & ~memMask ) | ( data & memMask ) ;
237 // update array
238 mainMem[ addr ] = tmpData;
239#ifdef MEMARRAY_DEBUG
240 printf("%0d MemArray::writeBM [%0d] addr=%h, data=%h, mask=%h\n",get_cycle(),id,addr,data,byteMask);
241 dumpMem({addr[MEM_ADDR:6],6'b000000},8); // L2 block size
242#endif
243
244 semaphore_put( semaLock , 1 );
245
246 }
247
248 //----------------------------------------------------------
249 // Write 512 bit block to memory
250 task write512(reg [MEM_ADDR:0] addr, reg [511:0] data, integer id=0, reg revEndian=0) {
251 integer i,j;
252
253 addr = addr & MASK_512;
254
255 if (revEndian) {
256 for (i=0,j=7;i<8;i++,j--) {
257 mainMem[addr+(i*8)] = data[(j*64)+63:j*64];
258 }
259 } else {
260 for (i=0;i<8;i++) {
261 mainMem[addr+(i*8)] = data[(i*64)+63:i*64];
262 }
263 }
264#ifdef MEMARRAY_DEBUG
265 printf("%0d MemArray::write512 [%0d] addr=%h, data=%h, revEndian=%0b\n",get_cycle(),id,addr,data,revEndian);
266 dumpMem({addr[MEM_ADDR:6],6'b000000},8); // L2 block size
267#endif
268
269 }
270
271 //----------------------------------------------------------
272 // Write 128 bit block to memory
273 task write128(reg [MEM_ADDR:0] addr, reg [127:0] data, integer id=0, reg revEndian=0) {
274 integer i,j;
275
276 addr = addr & MASK_128;
277
278 if (revEndian) {
279 for (i=0,j=1;i<2;i++,j--) {
280 mainMem[addr+(i*8)] = data[(j*64)+63:j*64];
281 }
282 } else {
283 for (i=0;i<2;i++) {
284 mainMem[addr+(i*8)] = data[(i*64)+63:i*64];
285 }
286 }
287#ifdef MEMARRAY_DEBUG
288 printf("%0d MemArray::write128 [%0d] addr=%h, data=%h, revEndian=%0b\n",get_cycle(),id,addr,data,revEndian);
289 dumpMem({addr[MEM_ADDR:6],6'b000000},8); // L2 block size
290#endif
291
292 }
293
294
295 //----------------------------------------------------------
296 // Read 64 bit word from memory
297 function reg [MEM_DATA:0] read_mem (reg [MEM_ADDR:0] addr,integer id=0, reg uninitWarn=0) {
298
299 addr = addr & MASK_EBW;
300
301 // If memory location has not been initialized,
302 // return all 0's or random data
303 if (assoc_index(CHECK,mainMem,addr)) {
304 read_mem = mainMem[addr];
305 } else {
306 if (returnRandom) read_mem = RAND_DATA;
307 else read_mem = DEFAULT_DATA;
308// if (! addr[39]) PR_INFO("memArray", MON_INFO,
309// psprintf("WARNING - Access to uninitialized address(%h) in L2 memory ",addr));
310 }
311
312#ifdef MEMARRAY_DEBUG
313 printf("%0d MemArray::read_mem [%0d] addr=%h, data=%h\n",get_cycle(),id,addr,read_mem);
314 dumpMem({addr[MEM_ADDR:6],6'b000000},8); // L2 block size
315#endif
316
317 }
318
319 // Read 512 bit block from memory
320 function reg [511:0] read512 (reg [MEM_ADDR:0] addr, integer id=0, reg revEndian=0, reg uninitWarn=0) {
321 integer i,j;
322 read512 = 0;
323
324 addr = addr & MASK_512;
325
326 if (revEndian) {
327 for (i=0,j=7;i<8;i++,j--) {
328 if (assoc_index(CHECK,mainMem,addr+(i*8))) {
329 read512[(j*64)+63:j*64] = mainMem[addr+(i*8)];
330 } else {
331 if (returnRandom) read512[(j*64)+63:j*64] = RAND_DATA;
332 else read512[(j*64)+63:j*64] = DEFAULT_DATA;
333// if (! addr[39]) PR_INFO("memArray", MON_INFO,
334// psprintf("WARNING - Access to uninitialized address(%h) in L2 memory ",addr));
335 }
336 }
337 } else {
338 for (i=0;i<8;i++) {
339 if (assoc_index(CHECK,mainMem,addr+(i*8))) {
340 read512[(i*64)+63:i*64] = mainMem[addr+(i*8)];
341 } else {
342 if (returnRandom) read512[(i*64)+63:i*64] = RAND_DATA;
343 else read512[(i*64)+63:i*64] = DEFAULT_DATA;
344// if (! addr[39]) PR_INFO("memArray", MON_INFO,
345// psprintf("WARNING - Access to uninitialized address(%h) in L2 memory ",addr));
346 }
347 }
348 }
349#ifdef MEMARRAY_DEBUG
350 printf("%0d MemArray::read512 [%0d] addr=%h, data=%h, revEndian=%0b\n",get_cycle(),id,addr,read512,revEndian);
351 dumpMem({addr[MEM_ADDR:6],6'b000000},8); // L2 block size
352#endif
353 }
354
355 // Read 128 bit block from memory
356 function reg [127:0] read128 (reg [MEM_ADDR:0] addr, integer id=0, reg revEndian=0, reg uninitWarn=0) {
357 integer i,j;
358 read128 = 0;
359
360 addr = addr & MASK_128;
361
362 if (revEndian) {
363 for (i=0,j=1;i<2;i++,j--) {
364 if (assoc_index(CHECK,mainMem,addr+(i*8))) {
365 read128[(j*64)+63:j*64] = mainMem[addr+(i*8)];
366 } else {
367 if (returnRandom) read128[(j*64)+63:j*64] = RAND_DATA;
368 else read128[(j*64)+63:j*64] = DEFAULT_DATA;
369// if (! addr[39]) PR_INFO("memArray", MON_INFO,
370// psprintf("WARNING - Access to uninitialized address(%h) in L2 memory ",addr));
371 }
372 }
373 } else {
374 for (i=0;i<2;i++) {
375 if (assoc_index(CHECK,mainMem,addr+(i*8))) {
376 read128[(i*64)+63:i*64] = mainMem[addr+(i*8)];
377 } else {
378 if (returnRandom) read128[(i*64)+63:i*64] = RAND_DATA;
379 else read128[(i*64)+63:i*64] = DEFAULT_DATA;
380// if (! addr[39]) PR_INFO("memArray", MON_INFO,
381// psprintf("WARNING - Access to uninitialized address(%h) in L2 memory ",addr));
382 }
383 }
384 }
385#ifdef MEMARRAY_DEBUG
386 printf("%0d MemArray::read128 [%0d] addr=%h, data=%h, revEndian=%0b\n",get_cycle(),id,addr,read128,revEndian);
387 dumpMem({addr[MEM_ADDR:6],6'b000000},8); // L2 block size
388#endif
389 }
390
391
392
393 // free contents. Use either start & end address OR
394 // start address and amount. Amount is number of BYTES
395 task freeMem(bit [MEM_ADDR:0] start,
396 bit [MEM_ADDR:0] ending=0,
397 integer amount=0)
398 {
399
400 integer success;
401 integer remaining;
402 bit [MEM_ADDR:0] tmpaddr, index;
403
404
405 semaphore_get( WAIT, semaLock , 1 );
406 start = start & MASK_EBW;
407 ending = ending & MASK_EBW;
408
409 if (amount & ending)
410 {
411 error("ERROR - freeMem was used incorrectly!!!\n");
412 }
413
414 if (amount) {
415 // adjust amount in bytes to be amount in "memory array width" lines.
416 amount = amount + start[2:0]; // take offset into account 8 byte word based
417 if (amount % BYTE_LANES) amount = amount/BYTE_LANES + 1;
418 else amount = amount/BYTE_LANES;
419
420 index = start;
421 remaining = amount;
422 while (remaining)
423 {
424 assoc_index (DELETE, mainMem, index);
425 success = assoc_index (NEXT, mainMem, index);
426 if (success == 0 || index >= start+amount) break;
427 remaining--;
428 }
429
430 } else { // user gave ending address
431 index = start;
432 ending = ending;
433 while (index <= ending)
434 {
435 assoc_index (DELETE, mainMem, index);
436 success = assoc_index (NEXT, mainMem, index);
437 // if unsuccessful we need to break out
438 if (success == 0 || index >= ending) break;
439 }
440 }
441 semaphore_put( semaLock , 1 );
442 }
443
444
445 // Dump a range of memory.
446 // amount is in array widths/elements.
447 task dumpMem(bit [MEM_ADDR:0] addr,
448 integer amount)
449
450 {
451 bit [MEM_DATA:0] data;
452 integer i,tmp;
453 bit [MEM_ADDR:0] word_size_mask=BYTE_LANES-1; // 4-1=3
454
455 addr = addr & MASK_EBW;
456
457 printf("%0d dumpMem: dumping memory at 0x%h for %0d Addresses :\n",get_cycle(), addr,amount);
458
459 // adjust amount in bytes to be amount in "memory array width" lines.
460 //amount = amount + start[2:0];
461 //if (amount % 8) amount = amount/8 + 1;
462 //else amount = amount/8;
463
464
465 for (i = 1 ; i <= amount ; i++) {
466 if (assoc_index(CHECK,mainMem,addr))
467 printf(" Addr = 0x%h, Data = 0x%h\n",addr,mainMem[addr]);
468 else
469 printf(" Addr = 0x%h, Data = uninitialized addr\n",addr);
470 addr += BYTE_LANES;
471 }
472
473 printf("%0d dumpMem: finished dumping memory.\n\n",get_cycle());
474
475 }
476
477 // for debug only
478 task dumpArray()
479 {
480
481 bit [MEM_ADDR:0] index=0;
482
483 printf("\n");
484 printf("%0d dumpArray: \n", get_cycle());
485
486 if ( assoc_index(FIRST, mainMem, index))
487 printf(" index=0x%h, data=0x%h \n", index, mainMem[index]);
488 else return;
489
490 while ( assoc_index(NEXT, mainMem, index) )
491 printf(" index=0x%h, data=0x%h \n", index, mainMem[index]);
492
493 printf("\n");
494 }
495
496}