/**************************************************************************** Copyright (C) 1987-2005 by Jeffery P. Hansen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ****************************************************************************/ #include #include #include #include "gsim.h" #define STRMAX 1024 /* root | v +---+MemNode | | +---+ +---+MemNode | *-+----->| | +---+ +---+ | | | | +---+ +---+ +---+MemNode | | | *-+----->| | +---+ +---+ +---+ | | | | +---+ +---+ | | +---+ +---+MemPage | *-+----->| D | +---+ +---+ | D | +---+ | D | +---+ | D | +---+ */ #define MEMORY_TEST 0 static MemPage *new_MemPage(unsigned base,int bpw) { MemPage *P = (MemPage *) malloc(sizeof(MemPage)); int n = (bpw<< MEM_BYTEBITS); int i; #if 0 sendMsg("comment create page @ %x",base); #endif P->motype = MEM_PAGE; P->baseAddr = base; P->data1 = (char*)malloc(n); P->datax = (char*)malloc(n); for (i = 0;i < n;i++) { P->data1[i] = 0; P->datax[i] = MEM_BYTEMASK; } return P; } static void delete_MemPage(MemPage *P) { free(P->data1); free(P->datax); free(P); } static MemNode *new_MemNode() { int i; MemNode *N = (MemNode *) malloc(sizeof(MemNode)); #if 0 sendMsg("comment create node"); #endif N->motype = MEM_NODE; for (i = 0;i < MEM_BYTEMAX;i++) N->ptr[i] = 0; return N; } static void delete_MemNode(MemNode *N) { int i; for (i = 0;i < MEM_BYTEMAX;i++) { if (N->ptr[i]) { MemBase *C = (MemBase *) N->ptr[i]; if (C->motype == MEM_NODE) delete_MemNode((MemNode*)C); else if (C->motype == MEM_PAGE) delete_MemPage((MemPage*)C); } } free (N); } Memory *new_Memory(int abits,int dbits) { Memory *M = (Memory*) malloc(sizeof(Memory)); int i,n; for (i = 0,n = 1;n < dbits;n <<= 1,i++); M->byte_shift = (i >= 3) ? (i-3) : 0; M->bpw = n; M->nbytes = (n+7)/8; M->root = new_MemNode(); return M; } static MemPage *Memory_getPage(Memory *M,unsigned A) { int addr[4]; MemNode *N; int i; addr[0] = (A >> 24) & MEM_BYTEMASK; addr[1] = (A >> 16) & MEM_BYTEMASK; addr[2] = (A >> 8) & MEM_BYTEMASK; addr[3] = (A ) & MEM_BYTEMASK; N = M->root; for (i = 0;i < 2;i++) { if (!N->ptr[addr[i]]) N->ptr[addr[i]] = new_MemNode(); N = (MemNode*)N->ptr[addr[i]]; } if (!N->ptr[addr[2]]) N->ptr[addr[2]] = new_MemPage(A&~MEM_BYTEMASK,M->bpw); return (MemPage*)N->ptr[addr[2]]; } void Memory_lookup(Memory *M,unsigned A,unsigned char **D,unsigned char **U) { MemPage *P = Memory_getPage(M,A); unsigned w = (A&MEM_BYTEMASK); unsigned b = w << M->byte_shift; *D = P->data1 + b; *U = P->datax + w; } void Memory_flush(Memory *M) { delete_MemNode(M->root); M->root = new_MemNode(); } /* Stores a line containing an address and values into a memory. Example line: "1000/ 10 4e 9a 23 8e" */ int Memory_putLine(Memory *M,char *line) { char buf[STRMAX]; unsigned addr,word; char *T; unsigned char *d,*u; int i; if (sscanf(line,"%x / %[^\n]",&addr,buf) != 2) { if (sscanf(line,"%s",buf) == 1 && *buf != '#') return 1; return 0; } Memory_lookup(M,addr,&d,&u); for (T = strtok(buf," \t");T;T = strtok(0," \t")) { if (sscanf(T,"%x",&word) != 1) return 1; for (i = 0;i < M->nbytes;i++) d[i] = 0xff & (word >> (i<<3)); *u++ = 0; d += M->nbytes; addr++; if (!(addr & MEM_BYTEMASK)) Memory_lookup(M,addr,&d,&u); } return 0; } /* */ int Memory_readFile(Memory *M,const char *fileName) { FILE *f; char buf[STRMAX]; if (!(f = openInPath(fileName))) return -1; while (fgets(buf,STRMAX,f)) { int r = Memory_putLine(M,buf); if (r != 0) return r; } return 0; } int MemPage_dump(MemPage *P,Memory *M,unsigned base,FILE *f) { int i; int need_addr = 1; int num_on_line = 0; for (i = 0;i < MEM_BYTEMAX;i++) { unsigned A = base|i; unsigned w = (A&MEM_BYTEMASK); unsigned b = w << M->byte_shift; unsigned char *D,*U; unsigned V; int j; if (i && !(i & 0x7)) { if (num_on_line) fprintf(f,"\n"); num_on_line = 0; need_addr = 1; } D = P->data1 + b; U = P->datax + w; V = 0; for (j = 0;j < M->nbytes;j++) V |= D[j] << (j<<3); if (!*U) { if (need_addr) { fprintf(f,"%x/",A); need_addr = 0; } fprintf(f," %x",V); num_on_line++; } else need_addr = 1; } if (num_on_line) fprintf(f,"\n"); return 0; } void MemNode_dump(MemNode *N,Memory *M,unsigned base,FILE *f) { int i; if (N->motype == MEM_PAGE) { MemPage_dump((MemPage*)N,M,base,f); return; } for (i = 0;i < MEM_BYTEMAX;i++) if (N->ptr[i]) MemNode_dump((MemNode*)N->ptr[i],M,(base|i)<<8,f); } void Memory_dump(Memory *M,FILE *f) { if (M->root) MemNode_dump(M->root,M,0x0,f); } int Memory_writeFile(Memory *M,const char *fileName) { FILE *f; if (!(f = fopen(fileName,"w"))) return -1; Memory_dump(M,f); fclose(f); return 0; } #if MEMORY_TEST main() { Memory *M = new_Memory(32,32); char buf[1024]; unsigned addr,data; unsigned char *d,*u; while (printf(">>> "),fgets(buf,1024,stdin)) { if (sscanf(buf,"g %x",&addr)) { Memory_lookup(M,addr,&d,&u); if (*u) printf("data = ?\n"); else printf("data = %x\n",*(unsigned*)d); } else if (sscanf(buf,"s %x %x",&addr,&data)) { Memory_lookup(M,addr,&d,&u); *(unsigned*)d = data; *(unsigned*)u = 0; } else if (sscanf(buf,"l %s",buf)) { Memory_readFile(M,buf); } } } #endif