00001 /* 00002 * memory.h - flat memory space interfaces 00003 * 00004 * This file is a part of the SimpleScalar tool suite written by 00005 * Todd M. Austin as a part of the Multiscalar Research Project. 00006 * 00007 * The tool suite is currently maintained by Doug Burger and Todd M. Austin. 00008 * 00009 * Copyright (C) 1994, 1995, 1996, 1997, 1998 by Todd M. Austin 00010 * 00011 * This source file is distributed "as is" in the hope that it will be 00012 * useful. The tool set comes with no warranty, and no author or 00013 * distributor accepts any responsibility for the consequences of its 00014 * use. 00015 * 00016 * Everyone is granted permission to copy, modify and redistribute 00017 * this tool set under the following conditions: 00018 * 00019 * This source code is distributed for non-commercial use only. 00020 * Please contact the maintainer for restrictions applying to 00021 * commercial use. 00022 * 00023 * Permission is granted to anyone to make or distribute copies 00024 * of this source code, either as received or modified, in any 00025 * medium, provided that all copyright notices, permission and 00026 * nonwarranty notices are preserved, and that the distributor 00027 * grants the recipient permission for further redistribution as 00028 * permitted by this document. 00029 * 00030 * Permission is granted to distribute this file in compiled 00031 * or executable form under the same conditions that apply for 00032 * source code, provided that either: 00033 * 00034 * A. it is accompanied by the corresponding machine-readable 00035 * source code, 00036 * B. it is accompanied by a written offer, with no time limit, 00037 * to give anyone a machine-readable copy of the corresponding 00038 * source code in return for reimbursement of the cost of 00039 * distribution. This written offer must permit verbatim 00040 * duplication by anyone, or 00041 * C. it is distributed by someone who received only the 00042 * executable form, and is accompanied by a copy of the 00043 * written offer of source code that they received concurrently. 00044 * 00045 * In other words, you are welcome to use, share and improve this 00046 * source file. You are forbidden to forbid anyone else to use, share 00047 * and improve what you give them. 00048 * 00049 * INTERNET: dburger@cs.wisc.edu 00050 * US Mail: 1210 W. Dayton Street, Madison, WI 53706 00051 * 00052 * $Id: memory.h,v 1.1.1.1 2003/09/18 00:57:54 panalyzer Exp $ 00053 * 00054 * $Log: memory.h,v $ 00055 * Revision 1.1.1.1 2003/09/18 00:57:54 panalyzer 00056 * 00057 * 00058 * Revision 1.1.1.1 2003/09/18 00:18:43 panalyzer 00059 * 00060 * 00061 * Revision 1.1.1.1 2003/09/16 18:48:14 gdm 00062 * 00063 * 00064 * Revision 1.1.1.1 2000/11/29 14:53:54 cu-cs 00065 * Grand unification of arm sources. 00066 * 00067 * 00068 * Revision 1.1.1.1 2000/05/26 15:18:58 taustin 00069 * SimpleScalar Tool Set 00070 * 00071 * 00072 * Revision 1.8 1999/12/31 18:38:54 taustin 00073 * cross-endian execution support added 00074 * quad_t naming conflicts removed 00075 * 00076 * Revision 1.7 1999/12/13 18:43:54 taustin 00077 * cross endian execution support added 00078 * 00079 * Revision 1.6 1998/08/27 15:39:47 taustin 00080 * implemented host interface description in host.h 00081 * added target interface support 00082 * memory module updated to support 64/32 bit address spaces on 64/32 00083 * bit machines, now implemented with a dynamically optimized hashed 00084 * page table 00085 * added support for qword's 00086 * added fault support 00087 * added support for register and memory contexts 00088 * 00089 * Revision 1.5 1997/03/11 01:16:23 taustin 00090 * updated copyright 00091 * long/int tweaks made for ALPHA target support 00092 * major macro reorganization to support CC portability 00093 * mem_valid() added, indicates if an address is bogus, used by DLite! 00094 * 00095 * Revision 1.4 1997/01/06 16:01:24 taustin 00096 * HIDE_MEM_TABLE_DEF added to help with sim-fast.c compilation 00097 * 00098 * Revision 1.3 1996/12/27 15:53:15 taustin 00099 * updated comments 00100 * 00101 * Revision 1.1 1996/12/05 18:50:23 taustin 00102 * Initial revision 00103 * 00104 * 00105 */ 00106 00107 #ifndef MEMORY_H 00108 #define MEMORY_H 00109 00110 #include <stdio.h> 00111 00112 #include "host.h" 00113 #include "misc.h" 00114 #include "machine.h" 00115 #include "options.h" 00116 #include "stats.h" 00117 00118 /* number of entries in page translation hash table (must be power-of-two) */ 00119 #define MEM_PTAB_SIZE (32*1024) 00120 #define MEM_LOG_PTAB_SIZE 15 00121 00122 /* page table entry */ 00123 struct mem_pte_t { 00124 struct mem_pte_t *next; /* next translation in this bucket */ 00125 md_addr_t tag; /* virtual page number tag */ 00126 byte_t *page; /* page pointer */ 00127 }; 00128 00129 /* memory object */ 00130 struct mem_t { 00131 /* memory object state */ 00132 char *name; /* name of this memory space */ 00133 struct mem_pte_t *ptab[MEM_PTAB_SIZE];/* inverted page table */ 00134 00135 /* memory object stats */ 00136 counter_t page_count; /* total number of pages allocated */ 00137 counter_t ptab_misses; /* total first level page tbl misses */ 00138 counter_t ptab_accesses; /* total page table accesses */ 00139 }; 00140 00141 /* memory access command */ 00142 enum mem_cmd { 00143 Read, /* read memory from target (simulated prog) to host */ 00144 Write /* write memory from host (simulator) to target */ 00145 }; 00146 00147 /* memory access function type, this is a generic function exported for the 00148 purpose of access the simulated vitual memory space */ 00149 typedef enum md_fault_type 00150 (*mem_access_fn)(struct mem_t *mem, /* memory space to access */ 00151 enum mem_cmd cmd, /* Read or Write */ 00152 md_addr_t addr, /* target memory address to access */ 00153 void *p, /* where to copy to/from */ 00154 int nbytes); /* transfer length in bytes */ 00155 00156 /* 00157 * virtual to host page translation macros 00158 */ 00159 00160 /* compute page table set */ 00161 #define MEM_PTAB_SET(ADDR) \ 00162 (((ADDR) >> MD_LOG_PAGE_SIZE) & (MEM_PTAB_SIZE - 1)) 00163 00164 /* compute page table tag */ 00165 #define MEM_PTAB_TAG(ADDR) \ 00166 ((ADDR) >> (MD_LOG_PAGE_SIZE + MEM_LOG_PTAB_SIZE)) 00167 00168 /* convert a pte entry at idx to a block address */ 00169 #define MEM_PTE_ADDR(PTE, IDX) \ 00170 (((PTE)->tag << (MD_LOG_PAGE_SIZE + MEM_LOG_PTAB_SIZE)) \ 00171 | ((IDX) << MD_LOG_PAGE_SIZE)) 00172 00173 /* locate host page for virtual address ADDR, returns NULL if unallocated */ 00174 #define MEM_PAGE(MEM, ADDR) \ 00175 (/* first attempt to hit in first entry, otherwise call xlation fn */ \ 00176 ((MEM)->ptab[MEM_PTAB_SET(ADDR)] \ 00177 && (MEM)->ptab[MEM_PTAB_SET(ADDR)]->tag == MEM_PTAB_TAG(ADDR)) \ 00178 ? (/* hit - return the page address on host */ \ 00179 (MEM)->ptab_accesses++, \ 00180 (MEM)->ptab[MEM_PTAB_SET(ADDR)]->page) \ 00181 : (/* first level miss - call the translation helper function */ \ 00182 mem_translate((MEM), (ADDR)))) 00183 00184 /* compute address of access within a host page */ 00185 #define MEM_OFFSET(ADDR) ((ADDR) & (MD_PAGE_SIZE - 1)) 00186 00187 /* memory tickle function, allocates pages when they are first written */ 00188 #define MEM_TICKLE(MEM, ADDR) \ 00189 (!MEM_PAGE(MEM, ADDR) \ 00190 ? (/* allocate page at address ADDR */ \ 00191 mem_newpage(MEM, ADDR)) \ 00192 : (/* nada... */ (void)0)) 00193 00194 /* memory page iterator */ 00195 #define MEM_FORALL(MEM, ITER, PTE) \ 00196 for ((ITER)=0; (ITER) < MEM_PTAB_SIZE; (ITER)++) \ 00197 for ((PTE)=(MEM)->ptab[i]; (PTE) != NULL; (PTE)=(PTE)->next) 00198 00199 00200 /* 00201 * memory accessors macros, fast but difficult to debug... 00202 */ 00203 00204 /* safe version, works only with scalar types */ 00205 /* FIXME: write a more efficient GNU C expression for this... */ 00206 #define MEM_READ(MEM, ADDR, TYPE) \ 00207 (MEM_PAGE(MEM, (md_addr_t)(ADDR)) \ 00208 ? *((TYPE *)(MEM_PAGE(MEM, (md_addr_t)(ADDR)) + MEM_OFFSET(ADDR))) \ 00209 : /* page not yet allocated, return zero value */ 0) 00210 00211 /* unsafe version, works with any type */ 00212 #define __UNCHK_MEM_READ(MEM, ADDR, TYPE) \ 00213 (*((TYPE *)(MEM_PAGE(MEM, (md_addr_t)(ADDR)) + MEM_OFFSET(ADDR)))) 00214 00215 /* safe version, works only with scalar types */ 00216 /* FIXME: write a more efficient GNU C expression for this... */ 00217 #define MEM_WRITE(MEM, ADDR, TYPE, VAL) \ 00218 (MEM_TICKLE(MEM, (md_addr_t)(ADDR)), \ 00219 *((TYPE *)(MEM_PAGE(MEM, (md_addr_t)(ADDR)) + MEM_OFFSET(ADDR))) = (VAL)) 00220 00221 /* unsafe version, works with any type */ 00222 #define __UNCHK_MEM_WRITE(MEM, ADDR, TYPE, VAL) \ 00223 (*((TYPE *)(MEM_PAGE(MEM, (md_addr_t)(ADDR)) + MEM_OFFSET(ADDR))) = (VAL)) 00224 00225 00226 /* fast memory accessor macros, typed versions */ 00227 #define MEM_READ_BYTE(MEM, ADDR) MEM_READ(MEM, ADDR, byte_t) 00228 #define MEM_READ_SBYTE(MEM, ADDR) MEM_READ(MEM, ADDR, sbyte_t) 00229 #define MEM_READ_HALF(MEM, ADDR) MD_SWAPH(MEM_READ(MEM, ADDR, half_t)) 00230 #define MEM_READ_SHALF(MEM, ADDR) MD_SWAPH(MEM_READ(MEM, ADDR, shalf_t)) 00231 #define MEM_READ_WORD(MEM, ADDR) MD_SWAPW(MEM_READ(MEM, ADDR, word_t)) 00232 #define MEM_READ_SWORD(MEM, ADDR) MD_SWAPW(MEM_READ(MEM, ADDR, sword_t)) 00233 00234 #ifdef HOST_HAS_QWORD 00235 #define MEM_READ_QWORD(MEM, ADDR) MD_SWAPQ(MEM_READ(MEM, ADDR, qword_t)) 00236 #define MEM_READ_SQWORD(MEM, ADDR) MD_SWAPQ(MEM_READ(MEM, ADDR, sqword_t)) 00237 #endif /* HOST_HAS_QWORD */ 00238 00239 #define MEM_WRITE_BYTE(MEM, ADDR, VAL) MEM_WRITE(MEM, ADDR, byte_t, VAL) 00240 #define MEM_WRITE_SBYTE(MEM, ADDR, VAL) MEM_WRITE(MEM, ADDR, sbyte_t, VAL) 00241 #define MEM_WRITE_HALF(MEM, ADDR, VAL) \ 00242 MEM_WRITE(MEM, ADDR, half_t, MD_SWAPH(VAL)) 00243 #define MEM_WRITE_SHALF(MEM, ADDR, VAL) \ 00244 MEM_WRITE(MEM, ADDR, shalf_t, MD_SWAPH(VAL)) 00245 #define MEM_WRITE_WORD(MEM, ADDR, VAL) \ 00246 MEM_WRITE(MEM, ADDR, word_t, MD_SWAPW(VAL)) 00247 #define MEM_WRITE_SWORD(MEM, ADDR, VAL) \ 00248 MEM_WRITE(MEM, ADDR, sword_t, MD_SWAPW(VAL)) 00249 #define MEM_WRITE_SFLOAT(MEM, ADDR, VAL) \ 00250 MEM_WRITE(MEM, ADDR, sfloat_t, MD_SWAPW(VAL)) 00251 #define MEM_WRITE_DFLOAT(MEM, ADDR, VAL) \ 00252 MEM_WRITE(MEM, ADDR, dfloat_t, MD_SWAPQ(VAL)) 00253 00254 #ifdef HOST_HAS_QWORD 00255 #define MEM_WRITE_QWORD(MEM, ADDR, VAL) \ 00256 MEM_WRITE(MEM, ADDR, qword_t, MD_SWAPQ(VAL)) 00257 #define MEM_WRITE_SQWORD(MEM, ADDR, VAL) \ 00258 MEM_WRITE(MEM, ADDR, sqword_t, MD_SWAPQ(VAL)) 00259 #endif /* HOST_HAS_QWORD */ 00260 00261 00262 /* create a flat memory space */ 00263 struct mem_t * 00264 mem_create(char *name); /* name of the memory space */ 00265 00266 /* translate address ADDR in memory space MEM, returns pointer to host page */ 00267 byte_t * 00268 mem_translate(struct mem_t *mem, /* memory space to access */ 00269 md_addr_t addr); /* virtual address to translate */ 00270 00271 /* allocate a memory page */ 00272 void 00273 mem_newpage(struct mem_t *mem, /* memory space to allocate in */ 00274 md_addr_t addr); /* virtual address to allocate */ 00275 00276 /* generic memory access function, it's safe because alignments and permissions 00277 are checked, handles any natural transfer sizes; note, faults out if nbytes 00278 is not a power-of-two or larger then MD_PAGE_SIZE */ 00279 enum md_fault_type 00280 mem_access(struct mem_t *mem, /* memory space to access */ 00281 enum mem_cmd cmd, /* Read (from sim mem) or Write */ 00282 md_addr_t addr, /* target address to access */ 00283 void *vp, /* host memory address to access */ 00284 int nbytes); /* number of bytes to access */ 00285 00286 /* register memory system-specific statistics */ 00287 void 00288 mem_reg_stats(struct mem_t *mem, /* memory space to declare */ 00289 struct stat_sdb_t *sdb); /* stats data base */ 00290 00291 /* initialize memory system, call before loader.c */ 00292 void 00293 mem_init(struct mem_t *mem); /* memory space to initialize */ 00294 00295 /* dump a block of memory, returns any faults encountered */ 00296 enum md_fault_type 00297 mem_dump(struct mem_t *mem, /* memory space to display */ 00298 md_addr_t addr, /* target address to dump */ 00299 int len, /* number bytes to dump */ 00300 FILE *stream); /* output stream */ 00301 00302 00303 /* 00304 * memory accessor routines, these routines require a memory access function 00305 * definition to access memory, the memory access function provides a "hook" 00306 * for programs to instrument memory accesses, this is used by various 00307 * simulators for various reasons; for the default operation - direct access 00308 * to the memory system, pass mem_access() as the memory access function 00309 */ 00310 00311 /* copy a '\0' terminated string to/from simulated memory space, returns 00312 the number of bytes copied, returns any fault encountered */ 00313 enum md_fault_type 00314 mem_strcpy(mem_access_fn mem_fn, /* user-specified memory accessor */ 00315 struct mem_t *mem, /* memory space to access */ 00316 enum mem_cmd cmd, /* Read (from sim mem) or Write */ 00317 md_addr_t addr, /* target address to access */ 00318 char *s); /* host memory string buffer */ 00319 00320 /* copy NBYTES to/from simulated memory space, returns any faults */ 00321 enum md_fault_type 00322 mem_bcopy(mem_access_fn mem_fn, /* user-specified memory accessor */ 00323 struct mem_t *mem, /* memory space to access */ 00324 enum mem_cmd cmd, /* Read (from sim mem) or Write */ 00325 md_addr_t addr, /* target address to access */ 00326 void *vp, /* host memory address to access */ 00327 int nbytes); /* number of bytes to access */ 00328 00329 /* copy NBYTES to/from simulated memory space, NBYTES must be a multiple 00330 of 4 bytes, this function is faster than mem_bcopy(), returns any 00331 faults encountered */ 00332 enum md_fault_type 00333 mem_bcopy4(mem_access_fn mem_fn, /* user-specified memory accessor */ 00334 struct mem_t *mem, /* memory space to access */ 00335 enum mem_cmd cmd, /* Read (from sim mem) or Write */ 00336 md_addr_t addr, /* target address to access */ 00337 void *vp, /* host memory address to access */ 00338 int nbytes); /* number of bytes to access */ 00339 00340 /* zero out NBYTES of simulated memory, returns any faults encountered */ 00341 enum md_fault_type 00342 mem_bzero(mem_access_fn mem_fn, /* user-specified memory accessor */ 00343 struct mem_t *mem, /* memory space to access */ 00344 md_addr_t addr, /* target address to access */ 00345 int nbytes); /* number of bytes to clear */ 00346 00347 #endif /* MEMORY_H */