Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / model / verilog / niu / sparse_mem_model / pli / src / ext_sys_mem.cc
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: ext_sys_mem.cc
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// Copyright 2001 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
36//
37// This software and any related documentation (the "Materials") are the
38// confidential proprietary information of AMD. Unless otherwise provided
39// in an agreement specifically licensing the Materials, the Materials are
40// provided in confidence and may not to be used, distributed, modified, or
41// reproduced in whole or in part by any means.
42//
43// LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY
44// EXPRESS OR IMPLIED WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO
45// WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY
46// PARTICULAR PURPOSE, OR WARRANTIES ARISING FORM CONDUCT, COURSE OF
47// DEALING, OR USAGE OF TRADE. IN NO EVENT SHALL AMD OR ITS LICENSORS BE
48// LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION,
49// DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, OR LOSS OF
50// INFORMATION) ARISING OUT OF THE USE OF OR INABILITY TO USE THE
51// MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
52// DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR
53// LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE
54// ABOVE LIMITATION MAY NOT APPLY TO YOU.
55//
56// AMD does not assume any responsibility for any errors which may appear
57// in the Materials nor any responsibility to support or update the
58// Materials. AMD retains the right to modify the Materials at any time,
59// without notice, and is not obligated to provide such modified Materials
60// to you.
61//
62// NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make
63// any further information, software, technical information, know-how, or
64// show-how available to you.
65//
66// U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
67// "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government
68// is subject to the restrictions as set forth in FAR 52.227-14 and DFAR
69// 252.227-7013, et seq., or its successor. Use of the Materials by the
70// Government constitutes acknowledgement of AMD's proprietary rights in
71// them.
72//
73////////////////////////////////////////////////////////////////////////////////
74
75/*****************************************************************************
76 *
77 * $RCSfile: ext_sys_mem.cc,v $
78 *
79 * $Revision: 1.3 $
80 * $Date: 2008/02/21 09:51:16 $
81 * $Author: nhussain $
82 * $State: Exp $
83 * $Locker: $
84 *
85 * Copyright (c) 1997 by Advanced Micro Devices, Inc.
86 *
87 * This file is protected by Federal Copyright Law, with all rights
88 * reserved. No part of this file may be reproduced, stored in a
89 * retrieval system, translated, transcribed, or transmitted, in any
90 * form, or by any means manual, electric, electronic, mechanical,
91 * electro-magnetic, chemical, optical, or otherwise, without prior
92 * explicit written permission from Advanced Micro Devices, Inc.
93 *
94 ****************************************************************************/
95#include <iostream>
96#include <stdlib.h>
97#include <stdio.h>
98#include "ext_sys_mem.h"
99#include "vcsuser.h"
100
101////////////////////////////////////////////////////////////////////////////////
102//
103// System Memory Model
104//
105// Author: Ron Herzer x52085
106//
107// Function:
108// Implements a 64-Gig memory with 64-bit reads, and 64-bit writes that are
109// byte-wise granular. Dynamically allocates memory in 512 byte chunks
110// as needed.
111//
112// Data structures:
113// Uses a 1024 entry hash table for first lookup step for quick access.
114// Uses binary tree for storing multiple hits to the same hash table index.
115// Keeps track of last tree node hit for each hash table index for
116// quick subsequent accesses to the same chunk.
117//
118////////////////////////////////////////////////////////////////////////////////
119
120// Constructor clears all valid bits in hash table.
121SYS_MEM::SYS_MEM () {
122 int i;
123 _ClrMemVal = 0xffffffff;
124 iUseRandom = 0;
125 for (i=0; i<SYS_HTBL_SIZE; i++) htable[i].valid=0;
126 debug = 0;
127}
128
129void SYS_MEM::SetDefaultMemRandom() {
130 iUseRandom = 1;
131}
132
133void SYS_MEM::SetDefaultMemVal(uint val) {
134 iUseRandom = 0;
135 val &= 0xff;
136 io_printf("SYS_MEM::Setting default memory to 0x%02x\n", val);
137 val = val << 8 | val;
138 val = val << 16 | val;
139 _ClrMemVal = val;
140}
141
142
143void SYS_MEM::dump (char *FileName) {
144MEMCHUNK *CurK7Block;
145HTABLE_ENTRY *K7MemTable;
146HTABLE_ENTRY *NextTableEntry;
147FILE *memfile;
148
149 if (0==strcmp(FileName, "-")) {
150 memfile = stdout;
151 } else {
152 memfile = fopen(FileName, "w");
153 }
154
155 if (!memfile) {
156 io_printf("SYS_MEM::error - unable to open output file: %s", FileName);
157 } else {
158 io_printf("SYS_MEM::dump dumping memory to %s\n", FileName);
159 }
160
161 assert(memfile);
162 K7MemTable = (HTABLE_ENTRY *) ReturnHTable();
163 for (int idx = 0; idx < SYS_HTBL_SIZE; idx++) {
164 NextTableEntry = (HTABLE_ENTRY*) ((int)(K7MemTable) + (idx*(sizeof(HTABLE_ENTRY))));
165 if (NextTableEntry->valid) {
166 CurK7Block = NextTableEntry->headPtr;
167 dumpMemTree(memfile, CurK7Block, idx);
168 }
169 }
170 fclose(memfile);
171}
172
173
174void SYS_MEM::dumpMemTree(FILE *memfile, MEMCHUNK *K7Block, int Index) {
175 uint PrintNice;
176 unsigned char K7Data;
177 uint AddrHi, AddrLo;
178
179 if (K7Block->right)
180 dumpMemTree(memfile, K7Block->right, Index);
181 if (K7Block->left)
182 dumpMemTree(memfile, K7Block->left, Index);
183
184 AddrLo = uint(K7Block->tag & 0xffffffffllu) | ((Index & 0x3ff) << 9);
185 AddrHi = uint(K7Block->tag >> 32);
186
187 if (AddrHi)
188 fprintf(memfile, "@%02x_%08x\n", AddrHi, AddrLo);
189 else
190 fprintf(memfile, "@%08x\n", AddrLo);
191
192 for(int idx = 0; idx < SYS_CHUNK_SIZE; idx++) {
193 PrintNice = (idx + 1) % 16;
194 K7Data = read(AddrHi, AddrLo+idx);
195 if (PrintNice && (idx < (SYS_CHUNK_SIZE - 1)))
196 fprintf(memfile, "%02x ", (K7Data & 0xff));
197 else
198 fprintf(memfile, "%02x\n", (K7Data & 0xff));
199 }
200}
201
202
203// ***************************************************************************
204// Get upto a 64 bit address from the given string (Note: '_' are
205// allowed as delimiters within the address field).
206// ***************************************************************************
207int SYS_MEM::GetAddressFromString(char *InputBuffer, unsigned int *Addr) {
208 static char AddrBufferHi[128]; // May hold 64bit address + delimiters
209 static char AddrBufferLo[8+1]; // Only ever hold 4GB of address
210 bool retVal = true;
211 bool FoundNonZero = false;
212
213 char *destptr = AddrBufferHi; // strip out '_'s, strip off leading '0's
214 for (char *srcptr = InputBuffer; srcptr && *srcptr; srcptr++) {
215 switch (*srcptr) {
216 case '_': continue;
217 case '0': if (!FoundNonZero) continue; break;
218 default: FoundNonZero = true; break;
219 }
220 if (!isxdigit(*srcptr)) retVal = false;
221 *destptr = *srcptr;
222 destptr++;
223 }
224 *destptr = '\0';
225 assert(strlen(AddrBufferHi) <= 16);
226 if (strlen(AddrBufferHi) <= 8) { // defined AddrHi, AddrLo
227 strcpy(AddrBufferLo, strlen(AddrBufferHi) ? AddrBufferHi : "0"); // Were only zeroes there?
228 strcpy(AddrBufferHi, "0");
229 } else {
230 strcpy(AddrBufferLo, AddrBufferHi + (strlen(AddrBufferHi) - 8));
231 *(AddrBufferHi + (strlen(AddrBufferHi) - 8)) = '\0';
232 }
233 // scan them in
234 retVal &= (sscanf(AddrBufferHi, "%x", Addr + 1)) ? true : false;
235 retVal &= (sscanf(AddrBufferLo, "%x", Addr )) ? true : false;
236 return retVal;
237}
238
239
240// Load memory from .vram or .sim file.
241// Should only be called once at the beginning of simulation.
242// There is no function to deallocate any existing chunks.
243
244// ***************************************************************************
245void SYS_MEM::load (FILE *memfile, char *Filename,
246 long long unsigned int addrLimitLow, long long unsigned int addrLimitHigh) {
247 const uint bufferSize = 0x100;
248 char line[bufferSize << 1]; // buffer is 2x since worst case bufferSize chars could be sneaked
249 char word[bufferSize];
250 char *lptr, *wptr;
251 char *chkptr;
252 char *filename = const_cast<char *>(Filename ? Filename : "<RAM FILE>");
253 char overFlow = '\n';
254 uint SkipOverFlow = 0;
255 uint overFlowCount;
256 uint CommentActive = 0x0; // Needed for comments that exceed the bufferSize
257 // 0x0 - Not active
258 // 0x1 - Starting this line
259 // 0x2 - Continuing
260 // 0x4 - Ending this line
261 dword address[2] = {0,0}; // assumes address starts at 0 if first @address not specified.
262 dword data1,data0, dat;
263 static uint ErrorCnt = 0; // Retain the knowledge that were already dead if multiple images are loaded
264 uint ErrorCntLimit = 0xffffffff;
265 uint Done = ErrorCnt;
266 uint LineNum = 0;
267 byte be;
268 uint linechkDone = 0, linechkErr;
269 uint FoundAddr = ErrorCnt; // Only flag first instance (if there's another error)...
270 uint FoundData = ErrorCnt; // Only flag first instance (if there's another error)...
271
272 rewind (memfile); // Rewind the file in case this was previously loaded
273
274 // load data in vram or sim file. - memfile should always be valid
275 if (!memfile) {
276 io_printf("SYS_MEM load error! Could not open memory file, %s, for reading.\n", filename);
277 }
278
279 // specifically check for NULL characters since some sim files
280 // (randomly generated) have been noted to have NULL in file
281 for (char prechk = fgetc(memfile); (prechk != EOF) && !Done; prechk = fgetc(memfile)) {
282 if (prechk == 0) {
283 io_printf("SYS_MEM::error - .sim load error: Found Null character in memory file, %s, at position: %u\n",
284 filename, ftell(memfile));
285 //Rc->Finish();
286 ErrorCnt++;
287 if (ErrorCnt >= ErrorCntLimit)
288 Done++;
289 }
290 }
291 rewind(memfile); // Reset the file pointer
292
293 while ((fgets(line, bufferSize, memfile)) && !Done) {
294 if (SkipOverFlow && (CommentActive & 0x1))
295 CommentActive = 0; // This was a comment that started and ended on the same line...
296
297 SkipOverFlow = 0;
298 linechkDone = 0;
299
300 lptr = line; // pointer to line
301
302 // Initialize here so overFlow is done once per buffer read...
303 overFlowCount = 0;
304 for (chkptr = line; chkptr && *chkptr; chkptr++) {
305 overFlowCount++;
306 overFlow = *chkptr;
307 }
308 overFlowCount--;
309 if (chkptr && (overFlow == '\n'))
310 SkipOverFlow = 1;
311
312 if (CommentActive & 0x4)
313 CommentActive = 0; // Continued comment ended last line
314
315 if (overFlow == '\n') {
316 if (CommentActive & 0x3)
317 CommentActive = 0x4; // Continuing comment ending this line
318 else
319 CommentActive = 0;
320 LineNum++;
321 }
322 else if (CommentActive & 0x3)
323 CommentActive = 0x2; // Comment continuing
324
325 if (!(CommentActive & 0x6)) {
326 for (chkptr = line; chkptr && *chkptr && !linechkDone; chkptr++) {
327 linechkErr = 0;
328 if (*chkptr == '/') {
329 if (!(*(chkptr + 1))) linechkErr = 1; // not quite a Comment
330 else if (*(chkptr + 1) == '/') {
331 linechkDone = 1; // Comment for rest of line...
332 CommentActive = 0x1;
333 }
334 } else {
335 // In general, overFlowCount should never get larger than one since a byte will typically be
336 // split -- don't forget about the possibility of a split address.
337 if (!SkipOverFlow) {
338 while (*line && (overFlowCount < ((bufferSize << 1)-1)) && (!isspace(line[overFlowCount]))) {
339 overFlow = fgetc(memfile);
340 //io_printf("Found line[%u] '%c', Line %4u sneaking char '%c' from stream",
341 // overFlowCount, line[overFlowCount], LineNum, overFlow);
342 if (overFlow == EOF)
343 overFlow = '\n';
344 else if (overFlow == '\n') {
345 ungetc(overFlow, memfile);
346 LineNum++;
347 }
348 ++overFlowCount;
349 line[overFlowCount] = overFlow;
350 if (!overFlow) // Null terminates string and overflow search...
351 overFlowCount = (bufferSize << 1);
352 }
353 assert(overFlowCount < (bufferSize << 1));
354 line[overFlowCount+1] = '\0';
355 }
356
357 if (!( isxdigit(*chkptr)
358 || isspace(*chkptr)
359 || (*chkptr == '_') // Allow '_' delimiters in addresses...
360 || (*chkptr == '@')
361 )) linechkErr = 1;
362
363 }
364
365 if (linechkErr) {
366 io_printf("SYS_MEM::error - .sim load error: found illegal character '%c' in non-commented fields on line %u.\n",*chkptr, LineNum);
367 //Rc->Finish();
368 ErrorCnt++;
369 if (ErrorCnt >= ErrorCntLimit)
370 linechkDone = 1; // already exceeded error limit
371 }
372 }
373 }
374
375#ifdef DEBUG_COMMENTS
376 if (CommentActive & 0x4)
377 io_printf("Line %4u is a ending comment -%s-\n", LineNum-1, line);
378 else if (CommentActive & 0x2)
379 io_printf("Line %4u is a continuing comment -%s-\n", LineNum, line);
380 else if (CommentActive & 0x1)
381 io_printf("Line %4u is a new comment -%s-\n", LineNum, line);
382 else
383 io_printf("Line %4u is not a comment -%s-\n", LineNum, line);
384#endif
385
386 while ((lptr && *lptr && (*lptr != '\n') && (sscanf(lptr,"%s",word)==1)) && !Done)
387 { // get the next word on the line
388 if (ErrorCnt >= ErrorCntLimit) {
389 io_printf("SYS_MEM::Error Limit exceeded: run with --assertions_warnings_only if a complete list is needed\n");
390 Done++;
391 }
392
393 wptr = word;
394 // skip comment lines (or comments at end of line) -- Note: already checked that '/' equates to '//'
395 if (!(CommentActive & 0x6) && (*wptr != '/')) {
396 if (*wptr=='@') { // found new address
397 FoundAddr++;
398 ++wptr;
399 if (!GetAddressFromString(wptr, address)) {
400 io_printf("SYS_MEM::Error while reading .sim file, %s:%u, unable to determine address from %s\n",
401 filename, LineNum, wptr);
402 //Rc->Finish();
403 ErrorCnt++;
404 }
405 } else { // write byte
406 if (!sscanf(wptr,"%x",&dat)) {
407 io_printf("SYS_MEM:: .sim load error: At %x%08x, Data '%s' is not a hex number at %s:%u\n",
408 address[1], address[0], wptr, filename, LineNum);
409 //Rc->Finish();
410 ErrorCnt++;
411 } else if (dat > 0xff) {
412 io_printf("SYS_MEM:: .sim load error: Detected byte data '0x%02x' at %s:%u\n",
413 dat, filename, LineNum);
414 //Rc->Finish();
415 ErrorCnt++;
416 }
417 FoundData++;
418 data1 = dat<<8*3&0xff000000 | dat<<8*2&0xff0000 | dat<<8*1&0xff00 | dat&0xff;
419 data0 = data1;
420 // decode byte enables & write byte to memory
421 be=0x1<<((address[0])&0x7);
422
423 long long unsigned int addressLong = ((long long unsigned int)(address[1]) << 32) | (long long unsigned int)address[0];
424 if (!(addrLimitLow || addrLimitHigh) || // Limits not enabled
425 ((addrLimitLow <= addressLong) && (addressLong <= addrLimitHigh))) {
426 // DEBUG PRINT
427 // printf("load %s: Addr: %02x_%08x (%02x) %02x\n", filename, address[1], address[0], (be & 0x000000ff), data0);
428 write(address[1],address[0],be,data1,data0);
429 }
430
431 address[0]++;
432 if (!address[0]) address[1]++; // increment addr[63:32] on wrap around of addr[31:0].
433 }
434 }
435 else lptr=NULL; // forget everything after comment
436 // look for next space
437 while(lptr && (*lptr != '\0') && isspace(*lptr)) lptr++; // skip whitespace within string
438 // lptr=strstr(lptr," "); // note: returns null if not found
439 while(lptr && (*lptr != '\0') && !isspace(*lptr)) lptr++; // skip whitespace
440 }
441 }
442 if (!FoundAddr)
443 io_printf("SYS_MEM::No address specifier in .sim file, %s. The assembler/user must know exactly what's going on...\n", filename);
444 if (!FoundData) {
445 io_printf("SYS_MEM:: No data bytes found in .sim file, %s\n", filename);
446 //Rc->Finish(); // Stop (this will be at the beginning of time...
447 }
448}
449
450
451// ***************************************************************************
452// Specific check for NULL characters since some sim files (randomly generated
453// ones) have been noted to have NULL characters in the file.
454// ***************************************************************************
455int SYS_MEM::PreCheckError(FILE *memfile, char *filename) {
456 bool Done = false;
457 rewind (memfile); // Rewind the file in case this was previously loaded
458 for (char prechk = fgetc(memfile); (prechk != EOF) && !Done; prechk = fgetc(memfile)) {
459 if (prechk == '\0') {
460 io_printf("SYS_MEM:: .sim load error: Found Null character in memory file, %s, at position: %u\n",
461 filename, ftell(memfile));
462 //Rc->Finish();
463 Done |= true;
464 }
465 }
466 rewind(memfile); // Reset the file pointer
467 return (Done);
468}
469
470
471// ***************************************************************************
472// Memory Read QW
473// Maximum address size = 64 bits. Aligned to QW boundary. (A[2:0] not used)
474// Always returns a QW in {data1,data0}.
475
476void SYS_MEM::read (dword addrh, dword addrl, dword *data1, dword *data0)
477{
478 long long unsigned int addr;
479 long long unsigned int tag;
480 uint idx;
481 uint offset;
482 MEMCHUNK* current;
483 uint randh;
484 uint randl;
485 uint _RandomClrMemVal1;
486 uint _RandomClrMemVal0;
487
488 addr = (((long long unsigned int)addrh)<<32) | addrl;
489 tag = addr & ~0x7ffffllu; // tag = addr[63:SYS_CHUNK_BITS]
490
491 // extract hash table index addr[18:9], and chunk offset addr[8:3]:
492 idx = addrl>>9 & 0x3ff;
493 offset = addrl>>2 & 0x7e; // note: zero out bit 2
494
495 // see if valid entry exists in hash table:
496 if (htable[idx].valid) {
497
498 // look for tag match (first check most recent access):
499 if (htable[idx].mraPtr->tag==tag) { // most common case!
500 *data1=htable[idx].mraPtr->data[offset+1];
501 *data0=htable[idx].mraPtr->data[offset];
502
503 } else { // find chunk in tree
504 current = htable[idx].headPtr;
505 while (current && current->tag!=tag) {
506 if (tag > current->tag) {
507 current = current->right;
508 } else {
509 current = current->left;
510 }
511 }
512 if (current) {
513 *data1=current->data[offset+1];
514 *data0=current->data[offset];
515 htable[idx].mraPtr=current;
516 } else { // not in chunk tree
517 if (iUseRandom) {
518 randh = rand();
519 randl = rand();
520 randh = randh << 16;
521 _RandomClrMemVal1 = randh | randl;
522 *data1 = _RandomClrMemVal1;
523 randh = rand();
524 randl = rand();
525 randh = randh << 16;
526 _RandomClrMemVal0 = randh | randl;
527 *data0 = _RandomClrMemVal0;
528 // create memory location with this random data
529 write(addrh,addrl,0xff,_RandomClrMemVal1,_RandomClrMemVal0);
530 } else {
531 *data1=_ClrMemVal;
532 *data0=_ClrMemVal;
533 }
534 }
535 }
536
537 } else { // hash table entry not valid
538 if (iUseRandom) {
539 randh = rand();
540 randl = rand();
541 randh = randh << 16;
542 _RandomClrMemVal1 = randh | randl;
543 *data1 = _RandomClrMemVal1;
544 randh = rand();
545 randl = rand();
546 randh = randh << 16;
547 _RandomClrMemVal0 = randh | randl;
548 *data0 = _RandomClrMemVal0;
549 // create memory location with this random data
550 write(addrh,addrl,0xff,_RandomClrMemVal1,_RandomClrMemVal0);
551 } else {
552 *data1=_ClrMemVal;
553 *data0=_ClrMemVal;
554 }
555 }
556}
557
558
559// ***************************************************************************
560// Memory Read QW - long long version
561// Maximum address size = 64 bits. Aligned to DW boundary. (A[1:0] not used)
562// Always returns a QW in {data}.
563long long unsigned int SYS_MEM::read (long long unsigned int addr, long long unsigned int *data) {
564 uint data1, data0;
565 uint addr1 = uint(addr >> 32);
566 uint addr0 = uint(addr & 0xffffffff);
567
568 read (addr1, addr0, &data1, &data0);
569 *data = ((long long unsigned int)(data1) << 32) | (long long unsigned int)data0;
570 return *data;
571}
572
573
574// ***************************************************************************
575// Memory Read DW
576// Maximum address size = 64 bits. Aligned to DW boundary. (A[1:0] not used)
577// Always returns a DW in {data}.
578uint SYS_MEM::read (dword addrh, dword addr, dword *data) {
579 uint data1, data0;
580
581 read (addrh, addr, &data1, &data0);
582 if (addr & 0x4) *data = data1;
583 else *data = data0;
584 return *data;
585}
586
587
588// ***************************************************************************
589// Memory Read Byte
590// Maximum address size = 64 bits.
591unsigned char SYS_MEM::read (dword addrh, dword addr)
592{
593 uint data;
594
595 read (addrh, addr, &data);
596 data = (data >> ((addr & 0x3)*8)) & 0xff;
597 return ((unsigned char) (data));
598}
599
600
601// ***************************************************************************
602// Memory Read - arbitrary Size
603unsigned char * SYS_MEM::read (dword addrh, dword addr, uint Size) {
604 unsigned char * retVal = NULL;
605 if (!Size)
606 io_printf("Error: Zero size passed to SYS_MEM::read(...)\n");
607 else {
608 retVal = new unsigned char [Size];
609 for (unsigned int idx = 0; idx < Size; idx++)
610 retVal[idx] = '\0';
611 for (uint idx = 0; idx < Size; idx++) {
612 retVal[idx] = read(addrh, addr);
613 if (addr == ~uint(0x0)) // Generate carry for upper address
614 addrh++;
615 addr++;
616 }
617 }
618 return (retVal);
619}
620
621
622// ***************************************************************************
623// Memory Read (one Bit)
624// Maximum address size = 64 bits. Aligned to DW boundary. (A[1:0] not used)
625// returns a bit
626uint SYS_MEM::readBit (dword addrh, dword addr, dword bitField) {
627 uint retVal;
628
629 //if (!bitField) Rc->Assertion(bitField, "bitField must be defined in readBit()\n");
630 read (addrh, addr, &retVal);
631 return (retVal & bitField);
632}
633
634
635// ***************************************************************************
636// Memory Write Byte
637void SYS_MEM::write (dword addrh, dword addr, byte data) {
638 byte be = 0x1 << (addr & 0x3);
639 write(addrh, (addr & ~0x3), be, dword(data));
640}
641
642
643// ***************************************************************************
644// Memory Write QW - long long version
645// Aligned to QW boundary. (A[2:0] not used). Always uses a QW in {data}.
646void SYS_MEM::write (long long unsigned int addr, byte be, long long unsigned int data) {
647 uint addr1 = uint(addr >> 32);
648 uint addr0 = uint(addr & 0xffffffff);
649 uint data1 = uint(data >> 32);
650 uint data0 = uint(data & 0xffffffff);
651 write (addr1, addr0, be, data1, data0);
652}
653
654
655// ***************************************************************************
656// Memory Write DW
657// Aligned to DW boundary. (A[1:0] not used). Always uses a DW in {data}.
658void SYS_MEM::write (dword addrh, dword addr, byte be, dword data) {
659 if (be > 0xf)
660 printf("SYS_MEM::write(dWord), inappropriate byte enables (%u) sent\n", be);
661 be &= 0xf;
662 if (addr & 0x4)
663 be = be << 4;
664 write (addrh, addr, be, data, data);
665}
666
667
668// ***************************************************************************
669// Memory Write
670// Maximum address size = 64 bits. Aligned to QW boundary. (A[2:0] not used)
671// Uses the QW in {data1,data0} and updates bytes whose byte enable (be[7:0]) is set.
672
673void SYS_MEM::write (dword addrh, dword addrl, byte be, dword data1, dword data0)
674{
675 long long unsigned int addr;
676 long long unsigned int tag;
677 uint idx;
678 uint offset;
679 MEMCHUNK* current;
680 dword temp1, temp0;
681 byte byte7,byte6,byte5,byte4,byte3,byte2,byte1,byte0;
682 int cont;
683 int i;
684 int added_chunk;
685 uint randh;
686 uint randl;
687 uint _RandomClrMemVal;
688
689 addr = (((long long unsigned int)addrh)<<32) | addrl;
690 tag = addr & ~0x7ffffllu; // tag = addr[63:SYS_CHUNK_BITS]
691 cont = 1;
692 added_chunk = 0;
693
694 // extract hash table index addr[18:9], and chunk offset addr[8:3]:
695 idx = addrl>>9 & 0x3ff;
696 offset = addrl>>2 & 0x7e; // note: zero out bit 2
697
698 // see if valid entry exists in hash table:
699 if (htable[idx].valid) {
700 // look for tag match (first check most recent access):
701 if (htable[idx].mraPtr->tag==tag) { // most common case!
702 current=htable[idx].mraPtr;
703 }
704 else { // find chunk in tree
705 current = htable[idx].headPtr;
706 while(current && current->tag!=tag && cont) {
707 if (tag>current->tag && current->right) { current = current->right; }
708 else if (tag<=current->tag && current->left) { current = current->left; }
709 else { cont=0; }
710 }
711 if (current && current->tag!=tag) { // not in chunk tree
712 // add entry to chunk tree
713 if (tag>current->tag) {
714 current->right= (MEMCHUNK *) malloc(sizeof(MEMCHUNK));
715 if (current) { current=current->right; added_chunk=1;}
716 }
717 else {
718 current->left= (MEMCHUNK *) malloc(sizeof(MEMCHUNK));
719 if (current) { current=current->left; added_chunk=1;}
720 }
721 }
722 }
723 }
724 else { // hash table entry not valid
725 // add entry into hash table
726 htable[idx].headPtr= (MEMCHUNK *) malloc(sizeof(MEMCHUNK));
727 htable[idx].valid=1;
728 current=htable[idx].headPtr;
729 added_chunk=1;
730 }
731
732 if (current) { // write data
733 if (added_chunk) {
734 current->right=NULL;
735 current->left=NULL;
736 current->tag=tag;
737 for (i=0; i<SYS_CHUNK_SIZE/4; i++) {
738 if (iUseRandom) {
739 randh = rand();
740 randl = rand();
741 randh = randh << 16;
742 _RandomClrMemVal = randh | randl;
743 current->data[i] = _RandomClrMemVal;
744 } else {
745 current->data[i] = _ClrMemVal;
746 }
747 }
748 }
749 temp1=current->data[offset+1];
750 temp0=current->data[offset];
751 byte7= (be&0x80) ? (data1>>3*8) : (temp1>>3*8);
752 byte6= (be&0x40) ? (data1>>2*8) : (temp1>>2*8);
753 byte5= (be&0x20) ? (data1>>1*8) : (temp1>>1*8);
754 byte4= (be&0x10) ? (data1) : (temp1);
755 byte3= (be&0x08) ? (data0>>3*8) : (temp0>>3*8);
756 byte2= (be&0x04) ? (data0>>2*8) : (temp0>>2*8);
757 byte1= (be&0x02) ? (data0>>1*8) : (temp0>>1*8);
758 byte0= (be&0x01) ? (data0) : (temp0);
759 current->data[offset+1]= byte7<<3*8&0xff000000 | byte6<<2*8&0xff0000 | byte5<<1*8&0xff00 | byte4&0xff;
760 current->data[offset] = byte3<<3*8&0xff000000 | byte2<<2*8&0xff0000 | byte1<<1*8&0xff00 | byte0&0xff;
761 htable[idx].mraPtr=current;
762 }
763 else io_printf("SYS_MEM write error! Could not allocate memory...\n");
764}