From: Steve Reinhardt Date: Fri, 10 Oct 2003 16:57:26 +0000 (-0700) Subject: File moves for the reorg. Tree is in broken state until I commit the makefile and X-Git-Tag: m5_1.0_beta1~58 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=52b31ea0a6a15b4a88530cfe411224d750e37899;p=gem5.git File moves for the reorg. Tree is in broken state until I commit the makefile and #include changes. --HG-- rename : sim/cache/lzss_compression.cc => base/compression/lzss_compression.cc rename : sim/cache/lzss_compression.hh => base/compression/lzss_compression.hh rename : sim/cache/null_compression.hh => base/compression/null_compression.hh rename : sim/hybrid_pred.cc => base/hybrid_pred.cc rename : sim/hybrid_pred.hh => base/hybrid_pred.hh rename : base/aout_object.cc => base/loader/aout_object.cc rename : base/aout_object.hh => base/loader/aout_object.hh rename : base/coff_sym.h => base/loader/coff_sym.h rename : base/coff_symconst.h => base/loader/coff_symconst.h rename : base/ecoff_object.cc => base/loader/ecoff_object.cc rename : base/ecoff_object.hh => base/loader/ecoff_object.hh rename : base/elf_object.cc => base/loader/elf_object.cc rename : base/elf_object.hh => base/loader/elf_object.hh rename : base/exec_aout.h => base/loader/exec_aout.h rename : base/exec_ecoff.h => base/loader/exec_ecoff.h rename : base/object_file.cc => base/loader/object_file.cc rename : base/object_file.hh => base/loader/object_file.hh rename : base/symtab.cc => base/loader/symtab.cc rename : base/symtab.hh => base/loader/symtab.hh rename : sim/predictor.hh => base/predictor.hh rename : sim/sat_counter.cc => base/sat_counter.cc rename : sim/sat_counter.hh => base/sat_counter.hh rename : sim/base_cpu.cc => cpu/base_cpu.cc rename : sim/base_cpu.hh => cpu/base_cpu.hh rename : sim/exec_context.cc => cpu/exec_context.cc rename : sim/exec_context.hh => cpu/exec_context.hh rename : sim/exetrace.cc => cpu/exetrace.cc rename : sim/exetrace.hh => cpu/exetrace.hh rename : sim/op_class.hh => cpu/full_cpu/op_class.hh rename : sim/smt.hh => cpu/full_cpu/smt.hh rename : sim/inst_seq.hh => cpu/inst_seq.hh rename : sim/intr_control.cc => cpu/intr_control.cc rename : sim/intr_control.hh => cpu/intr_control.hh rename : sim/memtest.cc => cpu/memtest/memtest.cc rename : sim/memtest.hh => cpu/memtest/memtest.hh rename : sim/pc_event.cc => cpu/pc_event.cc rename : sim/pc_event.hh => cpu/pc_event.hh rename : sim/simple_cpu.cc => cpu/simple_cpu/simple_cpu.cc rename : sim/simple_cpu.hh => cpu/simple_cpu/simple_cpu.hh rename : sim/static_inst.cc => cpu/static_inst.cc rename : sim/static_inst.hh => cpu/static_inst.hh extra : convert_revision : 05bd41acb2a424f1a38609fd4ac6df681bb479d6 --- diff --git a/base/aout_object.cc b/base/aout_object.cc deleted file mode 100644 index c0f43a687..000000000 --- a/base/aout_object.cc +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "aout_object.hh" - -#include "functional_memory.hh" -#include "symtab.hh" - -#include "trace.hh" // for DPRINTF - -#include "exec_aout.h" - -using namespace std; - -ObjectFile * -AoutObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) -{ - if (!N_BADMAG(*(aout_exechdr *)data)) { - return new AoutObject(fname, fd, len, data); - } - else { - return NULL; - } -} - - -AoutObject::AoutObject(const string &_filename, int _fd, - size_t _len, uint8_t *_data) - : ObjectFile(_filename, _fd, _len, _data) -{ - execHdr = (aout_exechdr *)fileData; - - entry = execHdr->entry; - - text.baseAddr = N_TXTADDR(*execHdr); - text.size = execHdr->tsize; - - data.baseAddr = N_DATADDR(*execHdr); - data.size = execHdr->dsize; - - bss.baseAddr = N_BSSADDR(*execHdr); - bss.size = execHdr->bsize; - - DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", - text.baseAddr, text.size, data.baseAddr, data.size, - bss.baseAddr, bss.size); -} - - -bool -AoutObject::loadSections(FunctionalMemory *mem, bool loadPhys) -{ - Addr textAddr = text.baseAddr; - Addr dataAddr = data.baseAddr; - - if (loadPhys) { - textAddr &= (ULL(1) << 40) - 1; - dataAddr &= (ULL(1) << 40) - 1; - } - - // Since we don't really have an MMU and all memory is - // zero-filled, there's no need to set up the BSS segment. - if (text.size != 0) - mem->prot_write(textAddr, fileData + N_TXTOFF(*execHdr), text.size); - if (data.size != 0) - mem->prot_write(dataAddr, fileData + N_DATOFF(*execHdr), data.size); - - return true; -} - - -bool -AoutObject::loadGlobalSymbols(SymbolTable *symtab) -{ - // a.out symbols not supported yet - return false; -} - -bool -AoutObject::loadLocalSymbols(SymbolTable *symtab) -{ - // a.out symbols not supported yet - return false; -} diff --git a/base/aout_object.hh b/base/aout_object.hh deleted file mode 100644 index baa8904a8..000000000 --- a/base/aout_object.hh +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __AOUT_OBJECT_HH__ -#define __AOUT_OBJECT_HH__ - -#include "object_file.hh" - -// forward decls: avoid including exec_aout.h here -struct aout_exechdr; - -class AoutObject : public ObjectFile -{ - protected: - aout_exechdr *execHdr; - - AoutObject(const std::string &_filename, int _fd, - size_t _len, uint8_t *_data); - - public: - virtual ~AoutObject() {} - - virtual bool loadSections(FunctionalMemory *mem, - bool loadPhys = false); - virtual bool loadGlobalSymbols(SymbolTable *symtab); - virtual bool loadLocalSymbols(SymbolTable *symtab); - - static ObjectFile *tryFile(const std::string &fname, int fd, - size_t len, uint8_t *data); -}; - -#endif // __AOUT_OBJECT_HH__ diff --git a/base/coff_sym.h b/base/coff_sym.h deleted file mode 100644 index dae9d8590..000000000 --- a/base/coff_sym.h +++ /dev/null @@ -1,491 +0,0 @@ -/* $Id$ */ - -/* - * Taken from binutils-2.14.90.0.5 include/coff/sym.h - */ - -/* Declarations of internal format of MIPS ECOFF symbols. - Originally contributed by MIPS Computer Systems and Third Eye Software. - Changes contributed by Cygnus Support are in the public domain. - - This file is just aggregated with the files that make up the GNU - release; it is not considered part of GAS, GDB, or other GNU - programs. */ - -/* - * |-----------------------------------------------------------| - * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.| - * | MIPS Computer Systems, Inc. grants reproduction and use | - * | rights to all parties, PROVIDED that this comment is | - * | maintained in the copy. | - * |-----------------------------------------------------------| - */ -#ifndef _SYM_H -#define _SYM_H - -/* (C) Copyright 1984 by Third Eye Software, Inc. - * - * Third Eye Software, Inc. grants reproduction and use rights to - * all parties, PROVIDED that this comment is maintained in the copy. - * - * Third Eye makes no claims about the applicability of this - * symbol table to a particular use. - */ - -/* - * This file contains the definition of the Third Eye Symbol Table. - * - * Symbols are assumed to be in 'encounter order' - i.e. the order that - * the things they represent were encountered by the compiler/assembler/loader. - * EXCEPT for globals! These are assumed to be bunched together, - * probably right after the last 'normal' symbol. Globals ARE sorted - * in ascending order. - * - * ----------------------------------------------------------------------- - * A brief word about Third Eye naming/use conventions: - * - * All arrays and index's are 0 based. - * All "ifooMax" values are the highest legal value PLUS ONE. This makes - * them good for allocating arrays, etc. All checks are "ifoo < ifooMax". - * - * "isym" Index into the SYMbol table. - * "ipd" Index into the Procedure Descriptor array. - * "ifd" Index into the File Descriptor array. - * "iss" Index into String Space. - * "cb" Count of Bytes. - * "rgPd" array whose domain is "0..ipdMax-1" and RanGe is PDR. - * "rgFd" array whose domain is "0..ifdMax-1" and RanGe is FDR. - */ - - -/* - * Symbolic Header (HDR) structure. - * As long as all the pointers are set correctly, - * we don't care WHAT order the various sections come out in! - * - * A file produced solely for the use of CDB will probably NOT have - * any instructions or data areas in it, as these are available - * in the original. - */ - -typedef struct ecoff_symhdr { - coff_short magic; /* to verify validity of the table */ - coff_short vstamp; /* version stamp */ - coff_int ilineMax; /* number of line number entries */ - coff_int idnMax; /* max index into dense number table */ - coff_int ipdMax; /* number of procedures */ - coff_int isymMax; /* number of local symbols */ - coff_int ioptMax; /* max index into optimization symbol entries */ - coff_int iauxMax; /* number of auxillary symbol entries */ - coff_int issMax; /* max index into local strings */ - coff_int issExtMax; /* max index into external strings */ - coff_int ifdMax; /* number of file descriptor entries */ - coff_int crfd; /* number of relative file descriptor entries */ - coff_int iextMax; /* max index into external symbols */ - coff_addr cbLine; /* number of bytes for line number entries */ - coff_addr cbLineOffset; /* offset to start of line number entries*/ - coff_addr cbDnOffset; /* offset to start dense number table */ - coff_addr cbPdOffset; /* offset to procedure descriptor table */ - coff_addr cbSymOffset; /* offset to start of local symbols*/ - coff_addr cbOptOffset; /* offset to optimization symbol entries */ - coff_addr cbAuxOffset; /* offset to start of auxillary symbol entries*/ - coff_addr cbSsOffset; /* offset to start of local strings */ - coff_addr cbSsExtOffset; /* offset to start of external strings */ - coff_addr cbFdOffset; /* offset to file descriptor table */ - coff_addr cbRfdOffset; /* offset to relative file descriptor table */ - coff_addr cbExtOffset; /* offset to start of external symbol entries*/ - /* If you add machine dependent fields, add them here */ -} HDRR, *pHDRR; -#define cbHDRR sizeof(HDRR) -#define hdrNil ((pHDRR)0) - -/* - * The FDR and PDR structures speed mapping of address <-> name. - * They are sorted in ascending memory order and are kept in - * memory by CDB at runtime. - */ - -/* - * File Descriptor - * - * There is one of these for EVERY FILE, whether compiled with - * full debugging symbols or not. The name of a file should be - * the path name given to the compiler. This allows the user - * to simply specify the names of the directories where the COMPILES - * were done, and we will be able to find their files. - * A field whose comment starts with "R - " indicates that it will be - * setup at runtime. - */ -typedef struct ecoff_fdr { - coff_addr adr; /* memory address of beginning of file */ - coff_addr cbLineOffset; /* byte offset from header for this file ln's */ - coff_addr cbLine; /* size of lines for this file */ - coff_addr cbSs; /* number of bytes in the ss */ - coff_int rss; /* file name (of source, if known) */ - coff_int issBase; /* file's string space */ - coff_int isymBase; /* beginning of symbols */ - coff_int csym; /* count file's of symbols */ - coff_int ilineBase; /* file's line symbols */ - coff_int cline; /* count of file's line symbols */ - coff_int ioptBase; /* file's optimization entries */ - coff_int copt; /* count of file's optimization entries */ - coff_int ipdFirst; /* start of procedures for this file */ - coff_int cpd; /* count of procedures for this file */ - coff_int iauxBase; /* file's auxiliary entries */ - coff_int caux; /* count of file's auxiliary entries */ - coff_int rfdBase; /* index into the file indirect table */ - coff_int crfd; /* count file indirect entries */ - unsigned lang: 5; /* language for this file */ - unsigned fMerge : 1; /* whether this file can be merged */ - unsigned fReadin : 1; /* true if it was read in (not just created) */ - unsigned fBigendian : 1;/* if set, was compiled on big endian machine */ - /* aux's will be in compile host's sex */ - unsigned glevel : 2; /* level this file was compiled with */ - unsigned reserved : 22; /* reserved for future use */ - coff_uint reserved2; -} FDR, *pFDR; -#define cbFDR sizeof(FDR) -#define fdNil ((pFDR)0) -#define ifdNil -1 -#define ifdTemp 0 -#define ilnNil -1 - - -/* - * Procedure Descriptor - * - * There is one of these for EVERY TEXT LABEL. - * If a procedure is in a file with full symbols, then isym - * will point to the PROC symbols, else it will point to the - * global symbol for the label. - */ - -typedef struct pdr { - coff_addr adr; /* memory address of start of procedure */ - coff_addr cbLineOffset; /* byte offset for this procedure from the fd base */ - coff_int isym; /* start of local symbol entries */ - coff_int iline; /* start of line number entries*/ - coff_uint regmask; /* save register mask */ - coff_int regoffset; /* save register offset */ - coff_int iopt; /* start of optimization symbol entries*/ - coff_uint fregmask; /* save floating point register mask */ - coff_int fregoffset; /* save floating point register offset */ - coff_int frameoffset; /* frame size */ - coff_int lnLow; /* lowest line in the procedure */ - coff_int lnHigh; /* highest line in the procedure */ - /* These fields are new for 64 bit ECOFF. */ - unsigned gp_prologue : 8; /* byte size of GP prologue */ - unsigned gp_used : 1; /* true if the procedure uses GP */ - unsigned reg_frame : 1; /* true if register frame procedure */ - unsigned prof : 1; /* true if compiled with -pg */ - unsigned reserved : 13; /* reserved: must be zero */ - unsigned localoff : 8; /* offset of local variables from vfp */ - coff_short framereg; /* frame pointer register */ - coff_short pcreg; /* offset or reg of return pc */ -} PDR, *pPDR; -#define cbPDR sizeof(PDR) -#define pdNil ((pPDR) 0) -#define ipdNil -1 - -/* - * The structure of the runtime procedure descriptor created by the loader - * for use by the static exception system. - */ -/* - * If 0'd out because exception_info chokes Visual C++ and because there - * don't seem to be any references to this structure elsewhere in gdb. - */ -#if 0 -typedef struct runtime_pdr { - coff_addr adr; /* memory address of start of procedure */ - coff_uint regmask; /* save register mask */ - coff_int regoffset; /* save register offset */ - coff_uint fregmask; /* save floating point register mask */ - coff_int fregoffset; /* save floating point register offset */ - coff_int frameoffset; /* frame size */ - coff_ushort framereg; /* frame pointer register */ - coff_ushort pcreg; /* offset or reg of return pc */ - coff_int irpss; /* index into the runtime string table */ - coff_uint reserved; - struct exception_info *exception_info;/* pointer to exception array */ -} RPDR, *pRPDR; -#define cbRPDR sizeof(RPDR) -#define rpdNil ((pRPDR) 0) -#endif - -/* - * Line Numbers - * - * Line Numbers are segregated from the normal symbols because they - * are [1] smaller , [2] are of no interest to your - * average loader, and [3] are never needed in the middle of normal - * scanning and therefore slow things down. - * - * By definition, the first LINER for any given procedure will have - * the first line of a procedure and represent the first address. - */ - -typedef coff_int LINER, *pLINER; -#define lineNil ((pLINER)0) -#define cbLINER sizeof(LINER) -#define ilineNil -1 - - - -/* - * The Symbol Structure (GFW, to those who Know!) - */ - -typedef struct ecoff_sym { - coff_long value; /* value of symbol */ - coff_int iss; /* index into String Space of name */ - unsigned st : 6; /* symbol type */ - unsigned sc : 5; /* storage class - text, data, etc */ - unsigned reserved : 1; /* reserved */ - unsigned index : 20; /* index into sym/aux table */ -} SYMR, *pSYMR; -#define symNil ((pSYMR)0) -#define cbSYMR sizeof(SYMR) -#define isymNil -1 -#define indexNil 0xfffff -#define issNil -1 -#define issNull 0 - - -/* The following converts a memory resident string to an iss. - * This hack is recognized in SbFIss, in sym.c of the debugger. - */ -#define IssFSb(sb) (0x80000000 | ((coff_ulong)(sb))) - -/* E X T E R N A L S Y M B O L R E C O R D - * - * Same as the SYMR except it contains file context to determine where - * the index is. - */ -typedef struct ecoff_extsym { - SYMR asym; /* symbol for the external */ - unsigned jmptbl:1; /* symbol is a jump table entry for shlibs */ - unsigned cobol_main:1; /* symbol is a cobol main procedure */ - unsigned weakext:1; /* symbol is weak external */ - unsigned reserved:29; /* reserved for future use */ - coff_int ifd; /* where the iss and index fields point into */ -} EXTR, *pEXTR; -#define extNil ((pEXTR)0) -#define cbEXTR sizeof(EXTR) - - -/* A U X I L L A R Y T Y P E I N F O R M A T I O N */ - -/* - * Type Information Record - */ -typedef struct { - unsigned fBitfield : 1; /* set if bit width is specified */ - unsigned continued : 1; /* indicates additional TQ info in next AUX */ - unsigned bt : 6; /* basic type */ - unsigned tq4 : 4; - unsigned tq5 : 4; - /* ---- 16 bit boundary ---- */ - unsigned tq0 : 4; - unsigned tq1 : 4; /* 6 type qualifiers - tqPtr, etc. */ - unsigned tq2 : 4; - unsigned tq3 : 4; -} TIR, *pTIR; -#define cbTIR sizeof(TIR) -#define tiNil ((pTIR)0) -#define itqMax 6 - -/* - * Relative symbol record - * - * If the rfd field is 4095, the index field indexes into the global symbol - * table. - */ - -typedef struct { - unsigned rfd : 12; /* index into the file indirect table */ - unsigned index : 20; /* index int sym/aux/iss tables */ -} RNDXR, *pRNDXR; -#define cbRNDXR sizeof(RNDXR) -#define rndxNil ((pRNDXR)0) - -/* dense numbers or sometimes called block numbers are stored in this type, - * a rfd of 0xffffffff is an index into the global table. - */ -typedef struct { - coff_uint rfd; /* index into the file table */ - coff_uint index; /* index int sym/aux/iss tables */ -} DNR, *pDNR; -#define cbDNR sizeof(DNR) -#define dnNil ((pDNR)0) - - - -/* - * Auxillary information occurs only if needed. - * It ALWAYS occurs in this order when present. - - isymMac used by stProc only - TIR type info - TIR additional TQ info (if first TIR was not enough) - rndx if (bt == btStruct,btUnion,btEnum,btSet,btRange, - btTypedef): - rsym.index == iaux for btSet or btRange - else rsym.index == isym - dimLow btRange, btSet - dimMac btRange, btSet - rndx0 As many as there are tq arrays - dimLow0 - dimHigh0 - ... - rndxMax-1 - dimLowMax-1 - dimHighMax-1 - width in bits if (bit field), width in bits. - */ -#define cAuxMax (6 + (idimMax*3)) - -/* a union of all possible info in the AUX universe */ -typedef union { - TIR ti; /* type information record */ - RNDXR rndx; /* relative index into symbol table */ - coff_int dnLow; /* low dimension */ - coff_int dnHigh; /* high dimension */ - coff_int isym; /* symbol table index (end of proc) */ - coff_int iss; /* index into string space (not used) */ - coff_int width; /* width for non-default sized struc fields */ - coff_int count; /* count of ranges for variant arm */ -} AUXU, *pAUXU; -#define cbAUXU sizeof(AUXU) -#define auxNil ((pAUXU)0) -#define iauxNil -1 - - -/* - * Optimization symbols - * - * Optimization symbols contain some overlap information with the normal - * symbol table. In particular, the proc information - * is somewhat redundant but necessary to easily find the other information - * present. - * - * All of the offsets are relative to the beginning of the last otProc - */ - -typedef struct { - unsigned ot: 8; /* optimization type */ - unsigned value: 24; /* address where we are moving it to */ - RNDXR rndx; /* points to a symbol or opt entry */ - coff_ulong offset; /* relative offset this occured */ -} OPTR, *pOPTR; -#define optNil ((pOPTR) 0) -#define cbOPTR sizeof(OPTR) -#define ioptNil -1 - -/* - * File Indirect - * - * When a symbol is referenced across files the following procedure is used: - * 1) use the file index to get the File indirect entry. - * 2) use the file indirect entry to get the File descriptor. - * 3) add the sym index to the base of that file's sym table - * - */ - -typedef coff_long RFDT, *pRFDT; -#define cbRFDT sizeof(RFDT) -#define rfdNil -1 - -/* - * The file indirect table in the mips loader is known as an array of FITs. - * This is done to keep the code in the loader readable in the area where - * these tables are merged. Note this is only a name change. - */ -typedef coff_int FIT, *pFIT; -#define cbFIT sizeof(FIT) -#define ifiNil -1 -#define fiNil ((pFIT) 0) - -#ifdef _LANGUAGE_PASCAL -#define ifdNil -1 -#define ilnNil -1 -#define ipdNil -1 -#define ilineNil -1 -#define isymNil -1 -#define indexNil 16#fffff -#define issNil -1 -#define issNull 0 -#define itqMax 6 -#define iauxNil -1 -#define ioptNil -1 -#define rfdNil -1 -#define ifiNil -1 -#endif /* _LANGUAGE_PASCAL */ - - -/* Dense numbers - * - * Rather than use file index, symbol index pairs to represent symbols - * and globals, we use dense number so that they can be easily embeded - * in intermediate code and the programs that process them can - * use direct access tabls instead of hash table (which would be - * necesary otherwise because of the sparse name space caused by - * file index, symbol index pairs. Dense number are represented - * by RNDXRs. - */ - -/* - * The following table defines the meaning of each SYM field as - * a function of the "st". (scD/B == scData OR scBss) - * - * Note: the value "isymMac" is used by symbols that have the concept - * of enclosing a block of related information. This value is the - * isym of the first symbol AFTER the end associated with the primary - * symbol. For example if a procedure was at isym==90 and had an - * isymMac==155, the associated end would be at isym==154, and the - * symbol at 155 would probably (although not necessarily) be the - * symbol for the next procedure. This allows rapid skipping over - * internal information of various sorts. "stEnd"s ALWAYS have the - * isym of the primary symbol that started the block. - * - -ST SC VALUE INDEX --------- ------ -------- ------ -stFile scText address isymMac -stLabel scText address --- -stGlobal scD/B address iaux -stStatic scD/B address iaux -stParam scAbs offset iaux -stLocal scAbs offset iaux -stProc scText address iaux (isymMac is first AUX) -stStaticProc scText address iaux (isymMac is first AUX) - -stMember scNil ordinal --- (if member of enum) - (mipsread thinks the case below has a bit, not byte, offset.) -stMember scNil byte offset iaux (if member of struct/union) -stMember scBits bit offset iaux (bit field spec) - -stBlock scText address isymMac (text block) - (the code seems to think that rather than scNil, we see scInfo for - the two cases below.) -stBlock scNil cb isymMac (struct/union member define) -stBlock scNil cMembers isymMac (enum member define) - - (New types added by SGI to simplify things:) -stStruct scInfo cb isymMac (struct type define) -stUnion scInfo cb isymMac (union type define) -stEnum scInfo cMembers isymMac (enum type define) - -stEnd scText address isymStart -stEnd scNil ------- isymStart (struct/union/enum) - -stTypedef scNil ------- iaux -stRegReloc sc??? value old register number -stForward sc??? new address isym to original symbol - -stConstant scInfo value --- (scalar) -stConstant scInfo iss --- (complex, e.g. string) - - * - */ -#endif diff --git a/base/coff_symconst.h b/base/coff_symconst.h deleted file mode 100644 index caed413c2..000000000 --- a/base/coff_symconst.h +++ /dev/null @@ -1,172 +0,0 @@ -/* $Id$ */ - -/* - * Taken from binutils-2.14.90.0.5 include/coff/symconst.h - */ - -/* Declarations of constants for internal format of MIPS ECOFF symbols. - Originally contributed by MIPS Computer Systems and Third Eye Software. - Changes contributed by Cygnus Support are in the public domain. - - This file is just aggregated with the files that make up the GNU - release; it is not considered part of GAS, GDB, or other GNU - programs. */ - -/* - * |-----------------------------------------------------------| - * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.| - * | MIPS Computer Systems, Inc. grants reproduction and use | - * | rights to all parties, PROVIDED that this comment is | - * | maintained in the copy. | - * |-----------------------------------------------------------| - */ - -/* (C) Copyright 1984 by Third Eye Software, Inc. - * - * Third Eye Software, Inc. grants reproduction and use rights to - * all parties, PROVIDED that this comment is maintained in the copy. - * - * Third Eye makes no claims about the applicability of this - * symbol table to a particular use. - */ - -/* glevels for field in FDR */ -#define GLEVEL_0 2 -#define GLEVEL_1 1 -#define GLEVEL_2 0 /* for upward compat reasons. */ -#define GLEVEL_3 3 - -/* magic number fo symheader */ -#define magicSym 0x7009 -/* The Alpha uses this value instead, for some reason. */ -#define magicSym2 0x1992 - -/* Language codes */ -#define langC 0 -#define langPascal 1 -#define langFortran 2 -#define langAssembler 3 /* one Assembley inst might map to many mach */ -#define langMachine 4 -#define langNil 5 -#define langAda 6 -#define langPl1 7 -#define langCobol 8 -#define langStdc 9 /* FIXME: Collides with SGI langCplusplus */ -#define langCplusplus 9 /* FIXME: Collides with langStdc */ -#define langCplusplusV2 10 /* SGI addition */ -#define langMax 11 /* maximun allowed 32 -- 5 bits */ - -/* The following are value definitions for the fields in the SYMR */ - -/* - * Storage Classes - */ - -#define scNil 0 -#define scText 1 /* text symbol */ -#define scData 2 /* initialized data symbol */ -#define scBss 3 /* un-initialized data symbol */ -#define scRegister 4 /* value of symbol is register number */ -#define scAbs 5 /* value of symbol is absolute */ -#define scUndefined 6 /* who knows? */ -#define scCdbLocal 7 /* variable's value is IN se->va.?? */ -#define scBits 8 /* this is a bit field */ -#define scCdbSystem 9 /* variable's value is IN CDB's address space */ -#define scDbx 9 /* overlap dbx internal use */ -#define scRegImage 10 /* register value saved on stack */ -#define scInfo 11 /* symbol contains debugger information */ -#define scUserStruct 12 /* address in struct user for current process */ -#define scSData 13 /* load time only small data */ -#define scSBss 14 /* load time only small common */ -#define scRData 15 /* load time only read only data */ -#define scVar 16 /* Var parameter (fortran,pascal) */ -#define scCommon 17 /* common variable */ -#define scSCommon 18 /* small common */ -#define scVarRegister 19 /* Var parameter in a register */ -#define scVariant 20 /* Variant record */ -#define scSUndefined 21 /* small undefined(external) data */ -#define scInit 22 /* .init section symbol */ -#define scBasedVar 23 /* Fortran or PL/1 ptr based var */ -#define scXData 24 /* exception handling data */ -#define scPData 25 /* Procedure section */ -#define scFini 26 /* .fini section */ -#define scRConst 27 /* .rconst section */ -#define scMax 32 - - -/* - * Symbol Types - */ - -#define stNil 0 /* Nuthin' special */ -#define stGlobal 1 /* external symbol */ -#define stStatic 2 /* static */ -#define stParam 3 /* procedure argument */ -#define stLocal 4 /* local variable */ -#define stLabel 5 /* label */ -#define stProc 6 /* " " Procedure */ -#define stBlock 7 /* beginnning of block */ -#define stEnd 8 /* end (of anything) */ -#define stMember 9 /* member (of anything - struct/union/enum */ -#define stTypedef 10 /* type definition */ -#define stFile 11 /* file name */ -#define stRegReloc 12 /* register relocation */ -#define stForward 13 /* forwarding address */ -#define stStaticProc 14 /* load time only static procs */ -#define stConstant 15 /* const */ -#define stStaParam 16 /* Fortran static parameters */ - /* These new symbol types have been recently added to SGI machines. */ -#define stStruct 26 /* Beginning of block defining a struct type */ -#define stUnion 27 /* Beginning of block defining a union type */ -#define stEnum 28 /* Beginning of block defining an enum type */ -#define stIndirect 34 /* Indirect type specification */ - /* Pseudo-symbols - internal to debugger */ -#define stStr 60 /* string */ -#define stNumber 61 /* pure number (ie. 4 NOR 2+2) */ -#define stExpr 62 /* 2+2 vs. 4 */ -#define stType 63 /* post-coersion SER */ -#define stMax 64 - -/* definitions for fields in TIR */ - -/* type qualifiers for ti.tq0 -> ti.(itqMax-1) */ -#define tqNil 0 /* bt is what you see */ -#define tqPtr 1 /* pointer */ -#define tqProc 2 /* procedure */ -#define tqArray 3 /* duh */ -#define tqFar 4 /* longer addressing - 8086/8 land */ -#define tqVol 5 /* volatile */ -#define tqConst 6 /* const */ -#define tqMax 8 - -/* basic types as seen in ti.bt */ -#define btNil 0 /* undefined (also, enum members) */ -#define btAdr 1 /* address - integer same size as pointer */ -#define btChar 2 /* character */ -#define btUChar 3 /* unsigned character */ -#define btShort 4 /* short */ -#define btUShort 5 /* unsigned short */ -#define btInt 6 /* int */ -#define btUInt 7 /* unsigned int */ -#define btLong 8 /* long */ -#define btULong 9 /* unsigned long */ -#define btFloat 10 /* float (real) */ -#define btDouble 11 /* Double (real) */ -#define btStruct 12 /* Structure (Record) */ -#define btUnion 13 /* Union (variant) */ -#define btEnum 14 /* Enumerated */ -#define btTypedef 15 /* defined via a typedef, isymRef points */ -#define btRange 16 /* subrange of int */ -#define btSet 17 /* pascal sets */ -#define btComplex 18 /* fortran complex */ -#define btDComplex 19 /* fortran double complex */ -#define btIndirect 20 /* forward or unnamed typedef */ -#define btFixedDec 21 /* Fixed Decimal */ -#define btFloatDec 22 /* Float Decimal */ -#define btString 23 /* Varying Length Character String */ -#define btBit 24 /* Aligned Bit String */ -#define btPicture 25 /* Picture */ -#define btVoid 26 /* void */ -#define btLongLong 27 /* long long */ -#define btULongLong 28 /* unsigned long long */ -#define btMax 64 diff --git a/base/compression/lzss_compression.cc b/base/compression/lzss_compression.cc new file mode 100644 index 000000000..a1933215a --- /dev/null +++ b/base/compression/lzss_compression.cc @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** @file + * LZSSCompression definitions. + */ + +#include + +#include "lzss_compression.hh" + +#include "misc.hh" //for fatal + +int +LZSSCompression::findSubString(uint8_t *src, int front, int back, int size) +{ + int subSize = 0; + int max_length = 2048; + if (size - back < max_length) { + max_length = size - back; + } + for (int i = 0; i < max_length; ++i) { + if (src[front+i] != src[back+i]) { + return subSize; + } + ++subSize; + } + return subSize; +} + +int +LZSSCompression::emitByte(uint8_t *dest, uint8_t byte) +{ + if ((byte >> 5 & 0x7) == 0 || (byte >> 5 & 0x7) == 7) { + // If the top 3 bits are the same, emit 00<6bits> + dest[0] = byte & 0x3f; + return 1; + } else { + // emit 01XXXXXX <8 bits> + dest[0] = 0x40; + dest[1] = byte; + return 2; + } +} + +void +LZSSCompression::emitString(uint8_t *dest, uint16_t P, uint16_t L) +{ + // Emit 1<7P> <5P><3L> <8L> + dest[0] = 1<<7 | (P >> 5 & 0x7f); + dest[1] = ((P & 0x1f) << 3) | (L>>8 & 0x3); + dest[2] = L & 0xFF; +} + +int +LZSSCompression::compress(uint8_t *dest, uint8_t *src, int size) +{ + if (size > 4096) { + fatal("Compression can only handle block sizes of 4096 bytes or less"); + } + + // Encode the first byte. + int dest_index = emitByte(dest, src[0]); + int i = 1; + // A 11 bit field + uint16_t L; + // A 12 bit field + uint16_t P = 0; + + while (i < size && dest_index < size) { + L = 0; + + if (dest_index+3 >= size) { + dest_index = size; + continue; + } + + if (i == size - 1) { + // Output the character + dest_index += emitByte(&dest[dest_index], src[i]); + ++i; + continue; + } + for (int j = 0; j < i; ++j) { + int sub_size = findSubString(src, j, i, size); + if (sub_size >= L) { + L = sub_size; + P = j; + } + } + if (L > 1) { + // Output the string reference + emitString(&dest[dest_index], P, L); + dest_index += 3; + i = i+L; + } else { + // Output the character + dest_index += emitByte(&dest[dest_index], src[i]); + ++i; + } + } + + if (dest_index >= size) { + // Have expansion instead of compression, just copy. + memcpy(dest,src,size); + return size; + } + return dest_index; +} + +int +LZSSCompression::uncompress(uint8_t *dest, uint8_t *src, int size) +{ + int index = 0; + int i = 0; + while (i < size) { + if (src[i] & 1<<7 ) { + // We have a string + // Extract P + int start = (src[i] & 0x3f)<<5 | ((src[i+1] >> 3) & 0x1f); + // Extract L + int len = (src[i+1] & 0x07)<<8 | src[i+2]; + i += 3; + for (int j = start; j < start+len; ++j) { + dest[index++] = dest[j]; + } + } else { + // We have a character + if (src[i] & 1<<6) { + // Value is in the next byte + dest[index++] = src[i+1]; + i += 2; + } else { + // just extend the lower 6 bits + dest[index++] = (src[i] & 0x3f) | ((src[i] & 1<<5) ? 0xC0 : 0); + ++i; + } + } + } + return index; +} diff --git a/base/compression/lzss_compression.hh b/base/compression/lzss_compression.hh new file mode 100644 index 000000000..5fb47d3f1 --- /dev/null +++ b/base/compression/lzss_compression.hh @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LZSS_COMPRESSION_HH__ +#define __LZSS_COMPRESSION_HH__ + +/** @file + * LZSSCompression declarations. + */ + +#include "host.hh" // for uint8_t + +/** + * Simple LZSS compression scheme. + */ +class LZSSCompression +{ + /** + * Finds the longest substrings that start at the given offsets. + * @param src The source block that we search for substrings. + * @param front The smaller offset. + * @param back The larger offset. + * @param size The size of the source block. + * @return The size of the longest substring. + */ + int findSubString(uint8_t *src, int front, int back, int size); + + /** + * Emit an encoded byte to the compressed data array. If the 2 high + * order bits can be signed extended, use 1 byte encoding, if not use 2 + * bytes. + * @param dest The compressed data. + * @param byte The byte to emit. + * @return The number of bytes used to encode. + */ + int emitByte(uint8_t *dest, uint8_t byte); + + /** + * Emit a string reference to the compressed data array. A string reference + * always uses 3 bytes. 1 flag bit, 12 bits for the starting position, and + * 11 bits for the length of the string. This allows compression of 4096 + * byte blocks with string lengths of up to 2048 bytes. + * @param dest The compressed data. + * @param P The starting position in the uncompressed data. + * @param L The length in bytes of the string. + */ + void emitString(uint8_t *dest, uint16_t P, uint16_t L); + + public: + /** + * Compresses the source block and stores it in the destination block. If + * the compressed block grows to larger than the source block, it aborts + * and just performs a copy. + * @param dest The destination block. + * @param src The block to be compressed. + * @param size The size of the source block. + * @return The size of the compressed block. + * + * @pre Destination has enough storage to hold the compressed block. + */ + int compress(uint8_t *dest, uint8_t *src, int size); + + /** + * Unompresses the source block and stores it in the destination block. + * @param dest The destination block. + * @param src The block to be uncompressed. + * @param size The size of the source block. + * @return The size of the uncompressed block. + * + * @pre Destination has enough storage to hold the uncompressed block. + */ + int uncompress(uint8_t *dest, uint8_t *src, int size); +}; + +#endif //__LZSS_COMPRESSION_HH__ diff --git a/base/compression/null_compression.hh b/base/compression/null_compression.hh new file mode 100644 index 000000000..d2bc76eef --- /dev/null +++ b/base/compression/null_compression.hh @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __NULL_COMPRESSION_HH__ +#define __NULL_COMPRESSION_HH__ + +/** + * @file + * This file defines a doNothing compression algorithm. + */ + +/** + * A dummy compression class to use when no data compression is desired. + */ +class NullCompression +{ + public: + /** + * Uncompress the data, causes a fatal since no data should be compressed. + * @param dest The output buffer. + * @param src The compressed data. + * @param size The number of bytes in src. + * + * @retval The size of the uncompressed data. + */ + static int uncompress(uint8_t * dest, uint8_t *src, int size) + { + fatal("Can't uncompress data"); + } + + /** + * Compress the data, just returns the source data. + * @param dest The output buffer. + * @param src The data to be compressed. + * @param size The number of bytes in src. + * + * @retval The size of the compressed data. + */ + + static int compress(uint8_t *dest, uint8_t *src, int size) + { + memcpy(dest,src,size); + return size; + } +}; + +#endif //__NULL_COMPRESSION_HH__ diff --git a/base/ecoff_object.cc b/base/ecoff_object.cc deleted file mode 100644 index 87ad6fdca..000000000 --- a/base/ecoff_object.cc +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ecoff_object.hh" - -#include "functional_memory.hh" -#include "symtab.hh" - -#include "trace.hh" // for DPRINTF - -#include "exec_ecoff.h" -#include "coff_sym.h" -#include "coff_symconst.h" - -using namespace std; - -ObjectFile * -EcoffObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) -{ - if (((ecoff_filehdr *)data)->f_magic == ECOFF_MAGIC_ALPHA) { - // it's Alpha ECOFF - return new EcoffObject(fname, fd, len, data); - } - else { - return NULL; - } -} - - -EcoffObject::EcoffObject(const string &_filename, int _fd, - size_t _len, uint8_t *_data) - : ObjectFile(_filename, _fd, _len, _data) -{ - execHdr = (ecoff_exechdr *)fileData; - fileHdr = &(execHdr->f); - aoutHdr = &(execHdr->a); - - entry = aoutHdr->entry; - - text.baseAddr = aoutHdr->text_start; - text.size = aoutHdr->tsize; - - data.baseAddr = aoutHdr->data_start; - data.size = aoutHdr->dsize; - - bss.baseAddr = aoutHdr->bss_start; - bss.size = aoutHdr->bsize; - - DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", - text.baseAddr, text.size, data.baseAddr, data.size, - bss.baseAddr, bss.size); -} - - -bool -EcoffObject::loadSections(FunctionalMemory *mem, bool loadPhys) -{ - Addr textAddr = text.baseAddr; - Addr dataAddr = data.baseAddr; - - if (loadPhys) { - textAddr &= (ULL(1) << 40) - 1; - dataAddr &= (ULL(1) << 40) - 1; - } - - // Since we don't really have an MMU and all memory is - // zero-filled, there's no need to set up the BSS segment. - mem->prot_write(textAddr, fileData + ECOFF_TXTOFF(execHdr), text.size); - mem->prot_write(dataAddr, fileData + ECOFF_DATOFF(execHdr), data.size); - - return true; -} - - -bool -EcoffObject::loadGlobalSymbols(SymbolTable *symtab) -{ - if (!symtab) - return false; - - if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) { - cprintf("wrong magic\n"); - return false; - } - - ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr); - if (syms->magic != magicSym2) { - cprintf("bad symbol header magic\n"); - exit(1); - } - - ecoff_extsym *ext_syms = (ecoff_extsym *)(fileData + syms->cbExtOffset); - - char *ext_strings = (char *)(fileData + syms->cbSsExtOffset); - for (int i = 0; i < syms->iextMax; i++) { - ecoff_sym *entry = &(ext_syms[i].asym); - if (entry->iss != -1) - symtab->insert(entry->value, ext_strings + entry->iss); - } - - return true; -} - -bool -EcoffObject::loadLocalSymbols(SymbolTable *symtab) -{ - if (!symtab) - return false; - - if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) { - cprintf("wrong magic\n"); - return false; - } - - ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr); - if (syms->magic != magicSym2) { - cprintf("bad symbol header magic\n"); - exit(1); - } - - ecoff_sym *local_syms = (ecoff_sym *)(fileData + syms->cbSymOffset); - char *local_strings = (char *)(fileData + syms->cbSsOffset); - ecoff_fdr *fdesc = (ecoff_fdr *)(fileData + syms->cbFdOffset); - - for (int i = 0; i < syms->ifdMax; i++) { - ecoff_sym *entry = (ecoff_sym *)(local_syms + fdesc[i].isymBase); - char *strings = (char *)(local_strings + fdesc[i].issBase); - for (int j = 0; j < fdesc[i].csym; j++) { - if (entry[j].st == stGlobal || entry[j].st == stProc) - if (entry[j].iss != -1) - symtab->insert(entry[j].value, strings + entry[j].iss); - } - } - - for (int i = 0; i < syms->isymMax; i++) { - ecoff_sym *entry = &(local_syms[i]); - if (entry->st == stProc) - symtab->insert(entry->value, local_strings + entry->iss); - } - - return true; -} diff --git a/base/ecoff_object.hh b/base/ecoff_object.hh deleted file mode 100644 index af757cd0e..000000000 --- a/base/ecoff_object.hh +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __ECOFF_OBJECT_HH__ -#define __ECOFF_OBJECT_HH__ - -#include "object_file.hh" - -// forward decls: avoid including exec_ecoff.h here -struct ecoff_exechdr; -struct ecoff_filehdr; -struct ecoff_aouthdr; - -class EcoffObject : public ObjectFile -{ - protected: - ecoff_exechdr *execHdr; - ecoff_filehdr *fileHdr; - ecoff_aouthdr *aoutHdr; - - EcoffObject(const std::string &_filename, int _fd, - size_t _len, uint8_t *_data); - - public: - virtual ~EcoffObject() {} - - virtual bool loadSections(FunctionalMemory *mem, - bool loadPhys = false); - virtual bool loadGlobalSymbols(SymbolTable *symtab); - virtual bool loadLocalSymbols(SymbolTable *symtab); - - static ObjectFile *tryFile(const std::string &fname, int fd, - size_t len, uint8_t *data); -}; - -#endif // __ECOFF_OBJECT_HH__ diff --git a/base/elf_object.cc b/base/elf_object.cc deleted file mode 100644 index 97f50e289..000000000 --- a/base/elf_object.cc +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "elf_object.hh" - -#include "functional_memory.hh" -#include "symtab.hh" - -#include "trace.hh" // for DPRINTF - -#include "exec_elf.h" - -using namespace std; - -ObjectFile * -ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) -{ - if (memcmp(((Elf64_Ehdr *)data)->e_ident, ELFMAG, SELFMAG) == 0) { - // for now we'll assume it's a 64-bit Alpha binary - return new ElfObject(fname, fd, len, data); - } - else { - return NULL; - } -} - - -ElfObject::ElfObject(const string &_filename, int _fd, - size_t _len, uint8_t *_data) - : ObjectFile(_filename, _fd, _len, _data) -{ - ehdr = (Elf64_Ehdr *)fileData; - - entry = ehdr->e_entry; - - phdr = (Elf64_Phdr *)(fileData + ehdr->e_phoff); - assert(sizeof(Elf64_Phdr) == ehdr->e_phentsize); - - bool foundText = false; - bool foundData = false; - for (int i = 0; i < ehdr->e_phnum; ++i) { - Elf64_Phdr *p = &phdr[i]; - - // for now we don't care about non-loadable segments - if (!(p->p_type & PT_LOAD)) - continue; - - if (p->p_flags & PF_X) { - // executable: must be text - assert(!foundText); - foundText = true; - textPhdrIdx = i; - text.baseAddr = p->p_vaddr; - text.size = p->p_filesz; - assert(p->p_filesz == p->p_memsz); - } - else { - assert(p->p_flags & PF_R); - assert(!foundData); - foundData = true; - dataPhdrIdx = i; - data.baseAddr = p->p_vaddr; - data.size = p->p_filesz; - bss.baseAddr = data.baseAddr + data.size; - bss.size = p->p_memsz - p->p_filesz; - } - } - - assert(foundText && foundData); - - DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", - text.baseAddr, text.size, data.baseAddr, data.size, - bss.baseAddr, bss.size); -} - - -bool -ElfObject::loadSections(FunctionalMemory *mem, bool loadPhys) -{ - Addr textAddr = text.baseAddr; - Addr dataAddr = data.baseAddr; - - if (loadPhys) { - textAddr &= (ULL(1) << 40) - 1; - dataAddr &= (ULL(1) << 40) - 1; - } - - // Since we don't really have an MMU and all memory is - // zero-filled, there's no need to set up the BSS segment. - if (text.size != 0) - mem->prot_write(textAddr, fileData + phdr[textPhdrIdx].p_offset, - text.size); - if (data.size != 0) - mem->prot_write(dataAddr, fileData + phdr[dataPhdrIdx].p_offset, - data.size); - - return true; -} - - -bool -ElfObject::loadGlobalSymbols(SymbolTable *symtab) -{ - // symbols not supported yet - return false; -} - -bool -ElfObject::loadLocalSymbols(SymbolTable *symtab) -{ - // symbols not supported yet - return false; -} diff --git a/base/elf_object.hh b/base/elf_object.hh deleted file mode 100644 index c90f6ebd5..000000000 --- a/base/elf_object.hh +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __ELF_OBJECT_HH__ -#define __ELF_OBJECT_HH__ - -#include "object_file.hh" - -// forward decls: avoid including exec_elf.hh here -struct Elf64_Ehdr; -struct Elf64_Phdr; - -class ElfObject : public ObjectFile -{ - protected: - Elf64_Ehdr *ehdr; - Elf64_Phdr *phdr; - - int textPhdrIdx; - int dataPhdrIdx; - - ElfObject(const std::string &_filename, int _fd, - size_t _len, uint8_t *_data); - - public: - virtual ~ElfObject() {} - - virtual bool loadSections(FunctionalMemory *mem, - bool loadPhys = false); - virtual bool loadGlobalSymbols(SymbolTable *symtab); - virtual bool loadLocalSymbols(SymbolTable *symtab); - - static ObjectFile *tryFile(const std::string &fname, int fd, - size_t len, uint8_t *data); -}; - -#endif // __ELF_OBJECT_HH__ diff --git a/base/exec_aout.h b/base/exec_aout.h deleted file mode 100644 index baed30c42..000000000 --- a/base/exec_aout.h +++ /dev/null @@ -1,62 +0,0 @@ -/* $Id$ */ - -/* - * Taken from NetBSD sys/exec_aout.h - */ - -/* $NetBSD: exec_aout.h,v 1.29 2002/12/10 17:14:31 thorpej Exp $ */ - -/* - * Copyright (c) 1993, 1994 Christopher G. Demetriou - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Christopher G. Demetriou. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SYS_EXEC_AOUT_H_ -#define _SYS_EXEC_AOUT_H_ - -#ifndef N_PAGSIZ -#define N_PAGSIZ(ex) (AOUT_LDPGSZ) -#endif - -/* a_magic */ -#define OMAGIC 0407 /* old impure format */ -#define NMAGIC 0410 /* read-only text */ -#define ZMAGIC 0413 /* demand load format */ - -#define N_ALIGN(ex,x) \ - (N_GETMAGIC(ex) == ZMAGIC ? \ - ((x) + AOUT_LDPGSZ - 1) & ~(AOUT_LDPGSZ - 1) : (x)) - -/* Valid magic number check. */ -#define N_BADMAG(ex) \ - (N_GETMAGIC(ex) != NMAGIC && N_GETMAGIC(ex) != OMAGIC && \ - N_GETMAGIC(ex) != ZMAGIC) - -#include "aout_machdep.h" - -#endif /* !_SYS_EXEC_AOUT_H_ */ diff --git a/base/exec_ecoff.h b/base/exec_ecoff.h deleted file mode 100644 index 8c559ab90..000000000 --- a/base/exec_ecoff.h +++ /dev/null @@ -1,111 +0,0 @@ -/* $Id$ */ - -/* - * Taken from NetBSD sys/exec_ecoff.h - */ - -/* $NetBSD: exec_ecoff.h,v 1.13 2003/01/18 09:53:18 thorpej Exp $ */ - -/* - * Copyright (c) 1994 Adam Glass - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Adam Glass. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SYS_EXEC_ECOFF_H_ -#define _SYS_EXEC_ECOFF_H_ - -#include "ecoff_machdep.h" - -struct ecoff_filehdr { - coff_ushort f_magic; /* magic number */ - coff_ushort f_nscns; /* # of sections */ - coff_uint f_timdat; /* time and date stamp */ - coff_ulong f_symptr; /* file offset of symbol table */ - coff_uint f_nsyms; /* # of symbol table entries */ - coff_ushort f_opthdr; /* sizeof the optional header */ - coff_ushort f_flags; /* flags??? */ -}; - -struct ecoff_aouthdr { - coff_ushort magic; - coff_ushort vstamp; - ECOFF_PAD - coff_ulong tsize; - coff_ulong dsize; - coff_ulong bsize; - coff_ulong entry; - coff_ulong text_start; - coff_ulong data_start; - coff_ulong bss_start; - ECOFF_MACHDEP; -}; - -struct ecoff_scnhdr { /* needed for size info */ - char s_name[8]; /* name */ - coff_ulong s_paddr; /* physical addr? for ROMing?*/ - coff_ulong s_vaddr; /* virtual addr? */ - coff_ulong s_size; /* size */ - coff_ulong s_scnptr; /* file offset of raw data */ - coff_ulong s_relptr; /* file offset of reloc data */ - coff_ulong s_lnnoptr; /* file offset of line data */ - coff_ushort s_nreloc; /* # of relocation entries */ - coff_ushort s_nlnno; /* # of line entries */ - coff_uint s_flags; /* flags */ -}; - -struct ecoff_exechdr { - struct ecoff_filehdr f; - struct ecoff_aouthdr a; -}; - -#define ECOFF_HDR_SIZE (sizeof(struct ecoff_exechdr)) - -#define ECOFF_OMAGIC 0407 -#define ECOFF_NMAGIC 0410 -#define ECOFF_ZMAGIC 0413 - -#define ECOFF_ROUND(value, by) \ - (((value) + (by) - 1) & ~((by) - 1)) - -#define ECOFF_BLOCK_ALIGN(ep, value) \ - ((ep)->a.magic == ECOFF_ZMAGIC ? ECOFF_ROUND((value), ECOFF_LDPGSZ) : \ - (value)) - -#define ECOFF_TXTOFF(ep) \ - ((ep)->a.magic == ECOFF_ZMAGIC ? 0 : \ - ECOFF_ROUND(ECOFF_HDR_SIZE + (ep)->f.f_nscns * \ - sizeof(struct ecoff_scnhdr), ECOFF_SEGMENT_ALIGNMENT(ep))) - -#define ECOFF_DATOFF(ep) \ - (ECOFF_BLOCK_ALIGN((ep), ECOFF_TXTOFF(ep) + (ep)->a.tsize)) - -#define ECOFF_SEGMENT_ALIGN(ep, value) \ - (ECOFF_ROUND((value), ((ep)->a.magic == ECOFF_ZMAGIC ? ECOFF_LDPGSZ : \ - ECOFF_SEGMENT_ALIGNMENT(ep)))) - -#endif /* !_SYS_EXEC_ECOFF_H_ */ diff --git a/base/hybrid_pred.cc b/base/hybrid_pred.cc new file mode 100644 index 000000000..ed7f781b2 --- /dev/null +++ b/base/hybrid_pred.cc @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "hybrid_pred.hh" +#include "statistics.hh" +#include "sim_stats.hh" + +using namespace std; + +HybridPredictor::HybridPredictor(const char *_p_name, const char *_z_name, + const char *_o_name, + unsigned _index_bits, unsigned _counter_bits, + unsigned _zero_change, unsigned _one_change, + unsigned _thresh, + unsigned _global_bits, + unsigned _global_thresh, + bool _reg_individual_stats) +{ + stringstream local_name, global_name; + + pred_name = _p_name; + one_name = _o_name; + zero_name = _z_name; + reg_individual_stats = _reg_individual_stats; + + local_name << pred_name.c_str() << ":L"; + local = new SaturatingCounterPred(local_name.str(), zero_name, one_name, + _index_bits, _counter_bits, + _zero_change, _one_change, _thresh); + + global_name << pred_name.c_str() << ":G"; + global = new SaturatingCounterPred(global_name.str(), zero_name, one_name, + 0, _global_bits, 1, 1, _global_thresh); +} + +void HybridPredictor::regStats() +{ + using namespace Statistics; + + string p_name; + stringstream description; + + if (reg_individual_stats) + p_name = pred_name + ":A"; + else + p_name = pred_name; + + + // + // Number of predictions + // + stringstream num_zero_preds; + num_zero_preds << p_name << ":" << zero_name << ":preds"; + description << "number of predictions of " << zero_name; + pred_zero + .name(num_zero_preds.str()) + .desc(description.str()); + description.str(""); + + stringstream num_one_preds; + num_one_preds << p_name << ":" << one_name << ":preds"; + description << "number of predictions of " << one_name; + pred_one + .name(num_one_preds.str()) + .desc(description.str()) + ; + description.str(""); + + // + // Count the number of correct predictions + // + stringstream num_zero_correct; + num_zero_correct << p_name << ":" << zero_name << ":corr_preds"; + description << "number of correct " << zero_name << " preds" ; + correct_pred_zero + .name(num_zero_correct.str()) + .desc(description.str()) + ; + description.str(""); + + stringstream num_one_correct; + num_one_correct << p_name << ":" << one_name << ":corr_preds"; + description << "number of correct " << one_name << " preds" ; + correct_pred_one + .name(num_one_correct.str()) + .desc(description.str()) + ; + description.str(""); + + + // + // Number of predictor updates + // + stringstream num_zero_updates; + num_zero_updates << p_name << ":" << zero_name << ":updates" ; + description << "number of actual " << zero_name << "s" ; + record_zero + .name(num_zero_updates.str()) + .desc(description.str()) + ; + description.str(""); + + stringstream num_one_updates; + num_one_updates << p_name << ":" << one_name << ":updates" ; + description << "number of actual " << one_name << "s" ; + record_one + .name(num_one_updates.str()) + .desc(description.str()) + ; + description.str(""); + + // + // Local & Global predictor stats + // + if (reg_individual_stats) { + local->regStats(); + global->regStats(); + } +} + +void HybridPredictor::regFormulas() +{ + using namespace Statistics; + + string p_name; + stringstream description; + stringstream name; + + if (reg_individual_stats) + p_name = pred_name + ":A"; + else + p_name = pred_name; + + // + // Number of predictions + // + name << p_name << ":predictions" ; + total_preds + .name(name.str()) + .desc("total number of predictions made") + ; + total_preds = pred_one + pred_zero; + name.str(""); + + // + // Fraction of all predictions that are one or zero + // + name << p_name << ":" << zero_name << ":pred_frac"; + description << "fraction of all preds that were " << zero_name ; + frac_preds_zero + .name(name.str()) + .desc(description.str()) + ; + frac_preds_zero = 100 * record_zero / total_preds; + description.str(""); + name.str(""); + + name << p_name << ":" << one_name << ":pred_frac"; + description << "fraction of all preds that were " << one_name ; + frac_preds_one + .name(name.str()) + .desc(description.str()) + ; + frac_preds_one = 100 * record_one / total_preds; + description.str(""); + name.str(""); + + // + // Count the number of correct predictions + // + name << p_name << ":correct_preds" ; + total_correct + .name(name.str()) + .desc("total number of correct predictions made") + ; + total_correct = correct_pred_one + correct_pred_zero; + name.str(""); + + + // + // Prediction accuracy rates + // + name << p_name << ":pred_rate"; + total_accuracy + .name(name.str()) + .desc("fraction of all preds that were correct") + ; + total_accuracy = 100 * total_correct / total_preds; + name.str(""); + + name << p_name << ":" << zero_name << ":pred_rate" ; + description << "fraction of "<< zero_name <<" preds that were correct"; + zero_accuracy + .name(name.str()) + .desc(description.str()) + ; + zero_accuracy = 100 * correct_pred_zero / pred_zero; + description.str(""); + name.str(""); + + name << p_name << ":" << one_name << ":pred_rate" ; + description << "fraction of "<< one_name <<" preds that were correct"; + one_accuracy + .name(name.str()) + .desc(description.str()) + ; + one_accuracy = 100 * correct_pred_one / pred_one; + description.str(""); + name.str(""); + + // + // Coverage + // + name << p_name << ":" << zero_name << ":coverage"; + description << "fraction of " << zero_name + << "s that were predicted correctly"; + zero_coverage + .name(name.str()) + .desc(description.str()) + ; + zero_coverage = 100 * correct_pred_zero / record_zero; + description.str(""); + name.str(""); + + name << p_name << ":" << one_name << ":coverage"; + description << "fraction of " << one_name + << "s that were predicted correctly"; + one_coverage + .name(name.str()) + .desc(description.str()) + ; + one_coverage = 100 * correct_pred_one / record_one; + description.str(""); + name.str(""); + + // + // Local & Global predictor stats + // + if (reg_individual_stats) { + local->regFormulas(); + global->regFormulas(); + } + +} + diff --git a/base/hybrid_pred.hh b/base/hybrid_pred.hh new file mode 100644 index 000000000..f6e14e3e3 --- /dev/null +++ b/base/hybrid_pred.hh @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//========================================================================== +// +// This predictor takes the AND of a "local" and a "global" predictor +// in order to determine its prediction. +// +// +// +// + +#ifndef __HYBRID_PRED_HH__ +#define __HYBRID_PRED_HH__ + +#include + +#include "sat_counter.hh" + +#include "statistics.hh" +#include "sim_stats.hh" + +class HybridPredictor : public GenericPredictor +{ + private: + std::string pred_name; + std::string one_name; + std::string zero_name; + bool reg_individual_stats; + + SaturatingCounterPred *local; + SaturatingCounterPred *global; + + unsigned long max_index; + + // + // Stats + // + Statistics::Scalar<> pred_one; //num_one_preds + Statistics::Scalar<> pred_zero; //num_zero_preds + Statistics::Scalar<> correct_pred_one; //num_one_correct + Statistics::Scalar<> correct_pred_zero; //num_zero_correct + Statistics::Scalar<> record_one; //num_one_updates + Statistics::Scalar<> record_zero; //num_zero_updates + + Statistics::Formula total_preds; + Statistics::Formula frac_preds_zero; + Statistics::Formula frac_preds_one; + Statistics::Formula total_correct; + Statistics::Formula total_accuracy; + Statistics::Formula zero_accuracy; + Statistics::Formula one_accuracy; + Statistics::Formula zero_coverage; + Statistics::Formula one_coverage; + + public: + HybridPredictor(const char *_p_name, const char *_z_name, + const char *_o_name, + unsigned _index_bits, unsigned _counter_bits, + unsigned _zero_change, unsigned _one_change, + unsigned _thresh, + unsigned _global_bits, unsigned _global_thresh, + bool _reg_individual_stats = false); + + void clear() { + global->clear(); + local->clear(); + } + + unsigned peek(unsigned long _index) { + unsigned l = local->peek(_index); + unsigned g = global->peek(_index); + + if (l && g) + return 1; + + return 0; + } + + unsigned value(unsigned long _index) { + unsigned l = local->peek(_index); + unsigned g = global->peek(_index); + + l = l & 0xFFFF; + g = g & 0xFFFF; + + return (l << 16) | g; + + } + + unsigned predict(unsigned long _index) { + unsigned l = local->predict(_index); + unsigned g = global->predict(_index); + + if (l && g) { + ++pred_one; + return 1; + } + + ++pred_zero; + return 0; + } + + + // + // This version need only be used if local/global statistics + // will be maintained + // + unsigned predict(unsigned long _index, unsigned &_pdata) { + unsigned l = local->predict(_index); + unsigned g = global->predict(_index); + + // + // bit 0 => local predictor result + // bit 1 => global predictor result + // + _pdata = 0; + if (l) + _pdata |= 1; + if (g) + _pdata |= 2; + if (l && g) { + ++pred_one; + return 1; + } + + ++pred_zero; + return 0; + } + + void record(unsigned long _index, unsigned _val, unsigned _predicted) { + + if (_val) { + local->record(_index, _val, 0); + global->record(_index, _val, 0); + ++record_one; + + if (_val == _predicted) { + ++correct_pred_one; + } + } else { + local->record(_index, _val, 0); + global->record(_index, _val, 0); + ++record_zero; + + if (_val == _predicted) + ++correct_pred_zero; + } + } + + void record(unsigned long _index, unsigned _val, unsigned _predicted, + unsigned _pdata) + { + + local->record(_index, _val, (_pdata & 1)); + global->record(_index, _val, ((_pdata & 2) ? 1 : 0)); + + + if (_val) { + ++record_one; + + if (_val == _predicted) + ++correct_pred_one; + } else { + ++record_zero; + + if (_val == _predicted) + ++correct_pred_zero; + } + } + + void regStats(); + void regFormulas(); +}; + + +#endif // _HYBRID_PRED_HH__ + diff --git a/base/loader/aout_object.cc b/base/loader/aout_object.cc new file mode 100644 index 000000000..c0f43a687 --- /dev/null +++ b/base/loader/aout_object.cc @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "aout_object.hh" + +#include "functional_memory.hh" +#include "symtab.hh" + +#include "trace.hh" // for DPRINTF + +#include "exec_aout.h" + +using namespace std; + +ObjectFile * +AoutObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) +{ + if (!N_BADMAG(*(aout_exechdr *)data)) { + return new AoutObject(fname, fd, len, data); + } + else { + return NULL; + } +} + + +AoutObject::AoutObject(const string &_filename, int _fd, + size_t _len, uint8_t *_data) + : ObjectFile(_filename, _fd, _len, _data) +{ + execHdr = (aout_exechdr *)fileData; + + entry = execHdr->entry; + + text.baseAddr = N_TXTADDR(*execHdr); + text.size = execHdr->tsize; + + data.baseAddr = N_DATADDR(*execHdr); + data.size = execHdr->dsize; + + bss.baseAddr = N_BSSADDR(*execHdr); + bss.size = execHdr->bsize; + + DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", + text.baseAddr, text.size, data.baseAddr, data.size, + bss.baseAddr, bss.size); +} + + +bool +AoutObject::loadSections(FunctionalMemory *mem, bool loadPhys) +{ + Addr textAddr = text.baseAddr; + Addr dataAddr = data.baseAddr; + + if (loadPhys) { + textAddr &= (ULL(1) << 40) - 1; + dataAddr &= (ULL(1) << 40) - 1; + } + + // Since we don't really have an MMU and all memory is + // zero-filled, there's no need to set up the BSS segment. + if (text.size != 0) + mem->prot_write(textAddr, fileData + N_TXTOFF(*execHdr), text.size); + if (data.size != 0) + mem->prot_write(dataAddr, fileData + N_DATOFF(*execHdr), data.size); + + return true; +} + + +bool +AoutObject::loadGlobalSymbols(SymbolTable *symtab) +{ + // a.out symbols not supported yet + return false; +} + +bool +AoutObject::loadLocalSymbols(SymbolTable *symtab) +{ + // a.out symbols not supported yet + return false; +} diff --git a/base/loader/aout_object.hh b/base/loader/aout_object.hh new file mode 100644 index 000000000..baa8904a8 --- /dev/null +++ b/base/loader/aout_object.hh @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __AOUT_OBJECT_HH__ +#define __AOUT_OBJECT_HH__ + +#include "object_file.hh" + +// forward decls: avoid including exec_aout.h here +struct aout_exechdr; + +class AoutObject : public ObjectFile +{ + protected: + aout_exechdr *execHdr; + + AoutObject(const std::string &_filename, int _fd, + size_t _len, uint8_t *_data); + + public: + virtual ~AoutObject() {} + + virtual bool loadSections(FunctionalMemory *mem, + bool loadPhys = false); + virtual bool loadGlobalSymbols(SymbolTable *symtab); + virtual bool loadLocalSymbols(SymbolTable *symtab); + + static ObjectFile *tryFile(const std::string &fname, int fd, + size_t len, uint8_t *data); +}; + +#endif // __AOUT_OBJECT_HH__ diff --git a/base/loader/coff_sym.h b/base/loader/coff_sym.h new file mode 100644 index 000000000..dae9d8590 --- /dev/null +++ b/base/loader/coff_sym.h @@ -0,0 +1,491 @@ +/* $Id$ */ + +/* + * Taken from binutils-2.14.90.0.5 include/coff/sym.h + */ + +/* Declarations of internal format of MIPS ECOFF symbols. + Originally contributed by MIPS Computer Systems and Third Eye Software. + Changes contributed by Cygnus Support are in the public domain. + + This file is just aggregated with the files that make up the GNU + release; it is not considered part of GAS, GDB, or other GNU + programs. */ + +/* + * |-----------------------------------------------------------| + * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.| + * | MIPS Computer Systems, Inc. grants reproduction and use | + * | rights to all parties, PROVIDED that this comment is | + * | maintained in the copy. | + * |-----------------------------------------------------------| + */ +#ifndef _SYM_H +#define _SYM_H + +/* (C) Copyright 1984 by Third Eye Software, Inc. + * + * Third Eye Software, Inc. grants reproduction and use rights to + * all parties, PROVIDED that this comment is maintained in the copy. + * + * Third Eye makes no claims about the applicability of this + * symbol table to a particular use. + */ + +/* + * This file contains the definition of the Third Eye Symbol Table. + * + * Symbols are assumed to be in 'encounter order' - i.e. the order that + * the things they represent were encountered by the compiler/assembler/loader. + * EXCEPT for globals! These are assumed to be bunched together, + * probably right after the last 'normal' symbol. Globals ARE sorted + * in ascending order. + * + * ----------------------------------------------------------------------- + * A brief word about Third Eye naming/use conventions: + * + * All arrays and index's are 0 based. + * All "ifooMax" values are the highest legal value PLUS ONE. This makes + * them good for allocating arrays, etc. All checks are "ifoo < ifooMax". + * + * "isym" Index into the SYMbol table. + * "ipd" Index into the Procedure Descriptor array. + * "ifd" Index into the File Descriptor array. + * "iss" Index into String Space. + * "cb" Count of Bytes. + * "rgPd" array whose domain is "0..ipdMax-1" and RanGe is PDR. + * "rgFd" array whose domain is "0..ifdMax-1" and RanGe is FDR. + */ + + +/* + * Symbolic Header (HDR) structure. + * As long as all the pointers are set correctly, + * we don't care WHAT order the various sections come out in! + * + * A file produced solely for the use of CDB will probably NOT have + * any instructions or data areas in it, as these are available + * in the original. + */ + +typedef struct ecoff_symhdr { + coff_short magic; /* to verify validity of the table */ + coff_short vstamp; /* version stamp */ + coff_int ilineMax; /* number of line number entries */ + coff_int idnMax; /* max index into dense number table */ + coff_int ipdMax; /* number of procedures */ + coff_int isymMax; /* number of local symbols */ + coff_int ioptMax; /* max index into optimization symbol entries */ + coff_int iauxMax; /* number of auxillary symbol entries */ + coff_int issMax; /* max index into local strings */ + coff_int issExtMax; /* max index into external strings */ + coff_int ifdMax; /* number of file descriptor entries */ + coff_int crfd; /* number of relative file descriptor entries */ + coff_int iextMax; /* max index into external symbols */ + coff_addr cbLine; /* number of bytes for line number entries */ + coff_addr cbLineOffset; /* offset to start of line number entries*/ + coff_addr cbDnOffset; /* offset to start dense number table */ + coff_addr cbPdOffset; /* offset to procedure descriptor table */ + coff_addr cbSymOffset; /* offset to start of local symbols*/ + coff_addr cbOptOffset; /* offset to optimization symbol entries */ + coff_addr cbAuxOffset; /* offset to start of auxillary symbol entries*/ + coff_addr cbSsOffset; /* offset to start of local strings */ + coff_addr cbSsExtOffset; /* offset to start of external strings */ + coff_addr cbFdOffset; /* offset to file descriptor table */ + coff_addr cbRfdOffset; /* offset to relative file descriptor table */ + coff_addr cbExtOffset; /* offset to start of external symbol entries*/ + /* If you add machine dependent fields, add them here */ +} HDRR, *pHDRR; +#define cbHDRR sizeof(HDRR) +#define hdrNil ((pHDRR)0) + +/* + * The FDR and PDR structures speed mapping of address <-> name. + * They are sorted in ascending memory order and are kept in + * memory by CDB at runtime. + */ + +/* + * File Descriptor + * + * There is one of these for EVERY FILE, whether compiled with + * full debugging symbols or not. The name of a file should be + * the path name given to the compiler. This allows the user + * to simply specify the names of the directories where the COMPILES + * were done, and we will be able to find their files. + * A field whose comment starts with "R - " indicates that it will be + * setup at runtime. + */ +typedef struct ecoff_fdr { + coff_addr adr; /* memory address of beginning of file */ + coff_addr cbLineOffset; /* byte offset from header for this file ln's */ + coff_addr cbLine; /* size of lines for this file */ + coff_addr cbSs; /* number of bytes in the ss */ + coff_int rss; /* file name (of source, if known) */ + coff_int issBase; /* file's string space */ + coff_int isymBase; /* beginning of symbols */ + coff_int csym; /* count file's of symbols */ + coff_int ilineBase; /* file's line symbols */ + coff_int cline; /* count of file's line symbols */ + coff_int ioptBase; /* file's optimization entries */ + coff_int copt; /* count of file's optimization entries */ + coff_int ipdFirst; /* start of procedures for this file */ + coff_int cpd; /* count of procedures for this file */ + coff_int iauxBase; /* file's auxiliary entries */ + coff_int caux; /* count of file's auxiliary entries */ + coff_int rfdBase; /* index into the file indirect table */ + coff_int crfd; /* count file indirect entries */ + unsigned lang: 5; /* language for this file */ + unsigned fMerge : 1; /* whether this file can be merged */ + unsigned fReadin : 1; /* true if it was read in (not just created) */ + unsigned fBigendian : 1;/* if set, was compiled on big endian machine */ + /* aux's will be in compile host's sex */ + unsigned glevel : 2; /* level this file was compiled with */ + unsigned reserved : 22; /* reserved for future use */ + coff_uint reserved2; +} FDR, *pFDR; +#define cbFDR sizeof(FDR) +#define fdNil ((pFDR)0) +#define ifdNil -1 +#define ifdTemp 0 +#define ilnNil -1 + + +/* + * Procedure Descriptor + * + * There is one of these for EVERY TEXT LABEL. + * If a procedure is in a file with full symbols, then isym + * will point to the PROC symbols, else it will point to the + * global symbol for the label. + */ + +typedef struct pdr { + coff_addr adr; /* memory address of start of procedure */ + coff_addr cbLineOffset; /* byte offset for this procedure from the fd base */ + coff_int isym; /* start of local symbol entries */ + coff_int iline; /* start of line number entries*/ + coff_uint regmask; /* save register mask */ + coff_int regoffset; /* save register offset */ + coff_int iopt; /* start of optimization symbol entries*/ + coff_uint fregmask; /* save floating point register mask */ + coff_int fregoffset; /* save floating point register offset */ + coff_int frameoffset; /* frame size */ + coff_int lnLow; /* lowest line in the procedure */ + coff_int lnHigh; /* highest line in the procedure */ + /* These fields are new for 64 bit ECOFF. */ + unsigned gp_prologue : 8; /* byte size of GP prologue */ + unsigned gp_used : 1; /* true if the procedure uses GP */ + unsigned reg_frame : 1; /* true if register frame procedure */ + unsigned prof : 1; /* true if compiled with -pg */ + unsigned reserved : 13; /* reserved: must be zero */ + unsigned localoff : 8; /* offset of local variables from vfp */ + coff_short framereg; /* frame pointer register */ + coff_short pcreg; /* offset or reg of return pc */ +} PDR, *pPDR; +#define cbPDR sizeof(PDR) +#define pdNil ((pPDR) 0) +#define ipdNil -1 + +/* + * The structure of the runtime procedure descriptor created by the loader + * for use by the static exception system. + */ +/* + * If 0'd out because exception_info chokes Visual C++ and because there + * don't seem to be any references to this structure elsewhere in gdb. + */ +#if 0 +typedef struct runtime_pdr { + coff_addr adr; /* memory address of start of procedure */ + coff_uint regmask; /* save register mask */ + coff_int regoffset; /* save register offset */ + coff_uint fregmask; /* save floating point register mask */ + coff_int fregoffset; /* save floating point register offset */ + coff_int frameoffset; /* frame size */ + coff_ushort framereg; /* frame pointer register */ + coff_ushort pcreg; /* offset or reg of return pc */ + coff_int irpss; /* index into the runtime string table */ + coff_uint reserved; + struct exception_info *exception_info;/* pointer to exception array */ +} RPDR, *pRPDR; +#define cbRPDR sizeof(RPDR) +#define rpdNil ((pRPDR) 0) +#endif + +/* + * Line Numbers + * + * Line Numbers are segregated from the normal symbols because they + * are [1] smaller , [2] are of no interest to your + * average loader, and [3] are never needed in the middle of normal + * scanning and therefore slow things down. + * + * By definition, the first LINER for any given procedure will have + * the first line of a procedure and represent the first address. + */ + +typedef coff_int LINER, *pLINER; +#define lineNil ((pLINER)0) +#define cbLINER sizeof(LINER) +#define ilineNil -1 + + + +/* + * The Symbol Structure (GFW, to those who Know!) + */ + +typedef struct ecoff_sym { + coff_long value; /* value of symbol */ + coff_int iss; /* index into String Space of name */ + unsigned st : 6; /* symbol type */ + unsigned sc : 5; /* storage class - text, data, etc */ + unsigned reserved : 1; /* reserved */ + unsigned index : 20; /* index into sym/aux table */ +} SYMR, *pSYMR; +#define symNil ((pSYMR)0) +#define cbSYMR sizeof(SYMR) +#define isymNil -1 +#define indexNil 0xfffff +#define issNil -1 +#define issNull 0 + + +/* The following converts a memory resident string to an iss. + * This hack is recognized in SbFIss, in sym.c of the debugger. + */ +#define IssFSb(sb) (0x80000000 | ((coff_ulong)(sb))) + +/* E X T E R N A L S Y M B O L R E C O R D + * + * Same as the SYMR except it contains file context to determine where + * the index is. + */ +typedef struct ecoff_extsym { + SYMR asym; /* symbol for the external */ + unsigned jmptbl:1; /* symbol is a jump table entry for shlibs */ + unsigned cobol_main:1; /* symbol is a cobol main procedure */ + unsigned weakext:1; /* symbol is weak external */ + unsigned reserved:29; /* reserved for future use */ + coff_int ifd; /* where the iss and index fields point into */ +} EXTR, *pEXTR; +#define extNil ((pEXTR)0) +#define cbEXTR sizeof(EXTR) + + +/* A U X I L L A R Y T Y P E I N F O R M A T I O N */ + +/* + * Type Information Record + */ +typedef struct { + unsigned fBitfield : 1; /* set if bit width is specified */ + unsigned continued : 1; /* indicates additional TQ info in next AUX */ + unsigned bt : 6; /* basic type */ + unsigned tq4 : 4; + unsigned tq5 : 4; + /* ---- 16 bit boundary ---- */ + unsigned tq0 : 4; + unsigned tq1 : 4; /* 6 type qualifiers - tqPtr, etc. */ + unsigned tq2 : 4; + unsigned tq3 : 4; +} TIR, *pTIR; +#define cbTIR sizeof(TIR) +#define tiNil ((pTIR)0) +#define itqMax 6 + +/* + * Relative symbol record + * + * If the rfd field is 4095, the index field indexes into the global symbol + * table. + */ + +typedef struct { + unsigned rfd : 12; /* index into the file indirect table */ + unsigned index : 20; /* index int sym/aux/iss tables */ +} RNDXR, *pRNDXR; +#define cbRNDXR sizeof(RNDXR) +#define rndxNil ((pRNDXR)0) + +/* dense numbers or sometimes called block numbers are stored in this type, + * a rfd of 0xffffffff is an index into the global table. + */ +typedef struct { + coff_uint rfd; /* index into the file table */ + coff_uint index; /* index int sym/aux/iss tables */ +} DNR, *pDNR; +#define cbDNR sizeof(DNR) +#define dnNil ((pDNR)0) + + + +/* + * Auxillary information occurs only if needed. + * It ALWAYS occurs in this order when present. + + isymMac used by stProc only + TIR type info + TIR additional TQ info (if first TIR was not enough) + rndx if (bt == btStruct,btUnion,btEnum,btSet,btRange, + btTypedef): + rsym.index == iaux for btSet or btRange + else rsym.index == isym + dimLow btRange, btSet + dimMac btRange, btSet + rndx0 As many as there are tq arrays + dimLow0 + dimHigh0 + ... + rndxMax-1 + dimLowMax-1 + dimHighMax-1 + width in bits if (bit field), width in bits. + */ +#define cAuxMax (6 + (idimMax*3)) + +/* a union of all possible info in the AUX universe */ +typedef union { + TIR ti; /* type information record */ + RNDXR rndx; /* relative index into symbol table */ + coff_int dnLow; /* low dimension */ + coff_int dnHigh; /* high dimension */ + coff_int isym; /* symbol table index (end of proc) */ + coff_int iss; /* index into string space (not used) */ + coff_int width; /* width for non-default sized struc fields */ + coff_int count; /* count of ranges for variant arm */ +} AUXU, *pAUXU; +#define cbAUXU sizeof(AUXU) +#define auxNil ((pAUXU)0) +#define iauxNil -1 + + +/* + * Optimization symbols + * + * Optimization symbols contain some overlap information with the normal + * symbol table. In particular, the proc information + * is somewhat redundant but necessary to easily find the other information + * present. + * + * All of the offsets are relative to the beginning of the last otProc + */ + +typedef struct { + unsigned ot: 8; /* optimization type */ + unsigned value: 24; /* address where we are moving it to */ + RNDXR rndx; /* points to a symbol or opt entry */ + coff_ulong offset; /* relative offset this occured */ +} OPTR, *pOPTR; +#define optNil ((pOPTR) 0) +#define cbOPTR sizeof(OPTR) +#define ioptNil -1 + +/* + * File Indirect + * + * When a symbol is referenced across files the following procedure is used: + * 1) use the file index to get the File indirect entry. + * 2) use the file indirect entry to get the File descriptor. + * 3) add the sym index to the base of that file's sym table + * + */ + +typedef coff_long RFDT, *pRFDT; +#define cbRFDT sizeof(RFDT) +#define rfdNil -1 + +/* + * The file indirect table in the mips loader is known as an array of FITs. + * This is done to keep the code in the loader readable in the area where + * these tables are merged. Note this is only a name change. + */ +typedef coff_int FIT, *pFIT; +#define cbFIT sizeof(FIT) +#define ifiNil -1 +#define fiNil ((pFIT) 0) + +#ifdef _LANGUAGE_PASCAL +#define ifdNil -1 +#define ilnNil -1 +#define ipdNil -1 +#define ilineNil -1 +#define isymNil -1 +#define indexNil 16#fffff +#define issNil -1 +#define issNull 0 +#define itqMax 6 +#define iauxNil -1 +#define ioptNil -1 +#define rfdNil -1 +#define ifiNil -1 +#endif /* _LANGUAGE_PASCAL */ + + +/* Dense numbers + * + * Rather than use file index, symbol index pairs to represent symbols + * and globals, we use dense number so that they can be easily embeded + * in intermediate code and the programs that process them can + * use direct access tabls instead of hash table (which would be + * necesary otherwise because of the sparse name space caused by + * file index, symbol index pairs. Dense number are represented + * by RNDXRs. + */ + +/* + * The following table defines the meaning of each SYM field as + * a function of the "st". (scD/B == scData OR scBss) + * + * Note: the value "isymMac" is used by symbols that have the concept + * of enclosing a block of related information. This value is the + * isym of the first symbol AFTER the end associated with the primary + * symbol. For example if a procedure was at isym==90 and had an + * isymMac==155, the associated end would be at isym==154, and the + * symbol at 155 would probably (although not necessarily) be the + * symbol for the next procedure. This allows rapid skipping over + * internal information of various sorts. "stEnd"s ALWAYS have the + * isym of the primary symbol that started the block. + * + +ST SC VALUE INDEX +-------- ------ -------- ------ +stFile scText address isymMac +stLabel scText address --- +stGlobal scD/B address iaux +stStatic scD/B address iaux +stParam scAbs offset iaux +stLocal scAbs offset iaux +stProc scText address iaux (isymMac is first AUX) +stStaticProc scText address iaux (isymMac is first AUX) + +stMember scNil ordinal --- (if member of enum) + (mipsread thinks the case below has a bit, not byte, offset.) +stMember scNil byte offset iaux (if member of struct/union) +stMember scBits bit offset iaux (bit field spec) + +stBlock scText address isymMac (text block) + (the code seems to think that rather than scNil, we see scInfo for + the two cases below.) +stBlock scNil cb isymMac (struct/union member define) +stBlock scNil cMembers isymMac (enum member define) + + (New types added by SGI to simplify things:) +stStruct scInfo cb isymMac (struct type define) +stUnion scInfo cb isymMac (union type define) +stEnum scInfo cMembers isymMac (enum type define) + +stEnd scText address isymStart +stEnd scNil ------- isymStart (struct/union/enum) + +stTypedef scNil ------- iaux +stRegReloc sc??? value old register number +stForward sc??? new address isym to original symbol + +stConstant scInfo value --- (scalar) +stConstant scInfo iss --- (complex, e.g. string) + + * + */ +#endif diff --git a/base/loader/coff_symconst.h b/base/loader/coff_symconst.h new file mode 100644 index 000000000..caed413c2 --- /dev/null +++ b/base/loader/coff_symconst.h @@ -0,0 +1,172 @@ +/* $Id$ */ + +/* + * Taken from binutils-2.14.90.0.5 include/coff/symconst.h + */ + +/* Declarations of constants for internal format of MIPS ECOFF symbols. + Originally contributed by MIPS Computer Systems and Third Eye Software. + Changes contributed by Cygnus Support are in the public domain. + + This file is just aggregated with the files that make up the GNU + release; it is not considered part of GAS, GDB, or other GNU + programs. */ + +/* + * |-----------------------------------------------------------| + * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.| + * | MIPS Computer Systems, Inc. grants reproduction and use | + * | rights to all parties, PROVIDED that this comment is | + * | maintained in the copy. | + * |-----------------------------------------------------------| + */ + +/* (C) Copyright 1984 by Third Eye Software, Inc. + * + * Third Eye Software, Inc. grants reproduction and use rights to + * all parties, PROVIDED that this comment is maintained in the copy. + * + * Third Eye makes no claims about the applicability of this + * symbol table to a particular use. + */ + +/* glevels for field in FDR */ +#define GLEVEL_0 2 +#define GLEVEL_1 1 +#define GLEVEL_2 0 /* for upward compat reasons. */ +#define GLEVEL_3 3 + +/* magic number fo symheader */ +#define magicSym 0x7009 +/* The Alpha uses this value instead, for some reason. */ +#define magicSym2 0x1992 + +/* Language codes */ +#define langC 0 +#define langPascal 1 +#define langFortran 2 +#define langAssembler 3 /* one Assembley inst might map to many mach */ +#define langMachine 4 +#define langNil 5 +#define langAda 6 +#define langPl1 7 +#define langCobol 8 +#define langStdc 9 /* FIXME: Collides with SGI langCplusplus */ +#define langCplusplus 9 /* FIXME: Collides with langStdc */ +#define langCplusplusV2 10 /* SGI addition */ +#define langMax 11 /* maximun allowed 32 -- 5 bits */ + +/* The following are value definitions for the fields in the SYMR */ + +/* + * Storage Classes + */ + +#define scNil 0 +#define scText 1 /* text symbol */ +#define scData 2 /* initialized data symbol */ +#define scBss 3 /* un-initialized data symbol */ +#define scRegister 4 /* value of symbol is register number */ +#define scAbs 5 /* value of symbol is absolute */ +#define scUndefined 6 /* who knows? */ +#define scCdbLocal 7 /* variable's value is IN se->va.?? */ +#define scBits 8 /* this is a bit field */ +#define scCdbSystem 9 /* variable's value is IN CDB's address space */ +#define scDbx 9 /* overlap dbx internal use */ +#define scRegImage 10 /* register value saved on stack */ +#define scInfo 11 /* symbol contains debugger information */ +#define scUserStruct 12 /* address in struct user for current process */ +#define scSData 13 /* load time only small data */ +#define scSBss 14 /* load time only small common */ +#define scRData 15 /* load time only read only data */ +#define scVar 16 /* Var parameter (fortran,pascal) */ +#define scCommon 17 /* common variable */ +#define scSCommon 18 /* small common */ +#define scVarRegister 19 /* Var parameter in a register */ +#define scVariant 20 /* Variant record */ +#define scSUndefined 21 /* small undefined(external) data */ +#define scInit 22 /* .init section symbol */ +#define scBasedVar 23 /* Fortran or PL/1 ptr based var */ +#define scXData 24 /* exception handling data */ +#define scPData 25 /* Procedure section */ +#define scFini 26 /* .fini section */ +#define scRConst 27 /* .rconst section */ +#define scMax 32 + + +/* + * Symbol Types + */ + +#define stNil 0 /* Nuthin' special */ +#define stGlobal 1 /* external symbol */ +#define stStatic 2 /* static */ +#define stParam 3 /* procedure argument */ +#define stLocal 4 /* local variable */ +#define stLabel 5 /* label */ +#define stProc 6 /* " " Procedure */ +#define stBlock 7 /* beginnning of block */ +#define stEnd 8 /* end (of anything) */ +#define stMember 9 /* member (of anything - struct/union/enum */ +#define stTypedef 10 /* type definition */ +#define stFile 11 /* file name */ +#define stRegReloc 12 /* register relocation */ +#define stForward 13 /* forwarding address */ +#define stStaticProc 14 /* load time only static procs */ +#define stConstant 15 /* const */ +#define stStaParam 16 /* Fortran static parameters */ + /* These new symbol types have been recently added to SGI machines. */ +#define stStruct 26 /* Beginning of block defining a struct type */ +#define stUnion 27 /* Beginning of block defining a union type */ +#define stEnum 28 /* Beginning of block defining an enum type */ +#define stIndirect 34 /* Indirect type specification */ + /* Pseudo-symbols - internal to debugger */ +#define stStr 60 /* string */ +#define stNumber 61 /* pure number (ie. 4 NOR 2+2) */ +#define stExpr 62 /* 2+2 vs. 4 */ +#define stType 63 /* post-coersion SER */ +#define stMax 64 + +/* definitions for fields in TIR */ + +/* type qualifiers for ti.tq0 -> ti.(itqMax-1) */ +#define tqNil 0 /* bt is what you see */ +#define tqPtr 1 /* pointer */ +#define tqProc 2 /* procedure */ +#define tqArray 3 /* duh */ +#define tqFar 4 /* longer addressing - 8086/8 land */ +#define tqVol 5 /* volatile */ +#define tqConst 6 /* const */ +#define tqMax 8 + +/* basic types as seen in ti.bt */ +#define btNil 0 /* undefined (also, enum members) */ +#define btAdr 1 /* address - integer same size as pointer */ +#define btChar 2 /* character */ +#define btUChar 3 /* unsigned character */ +#define btShort 4 /* short */ +#define btUShort 5 /* unsigned short */ +#define btInt 6 /* int */ +#define btUInt 7 /* unsigned int */ +#define btLong 8 /* long */ +#define btULong 9 /* unsigned long */ +#define btFloat 10 /* float (real) */ +#define btDouble 11 /* Double (real) */ +#define btStruct 12 /* Structure (Record) */ +#define btUnion 13 /* Union (variant) */ +#define btEnum 14 /* Enumerated */ +#define btTypedef 15 /* defined via a typedef, isymRef points */ +#define btRange 16 /* subrange of int */ +#define btSet 17 /* pascal sets */ +#define btComplex 18 /* fortran complex */ +#define btDComplex 19 /* fortran double complex */ +#define btIndirect 20 /* forward or unnamed typedef */ +#define btFixedDec 21 /* Fixed Decimal */ +#define btFloatDec 22 /* Float Decimal */ +#define btString 23 /* Varying Length Character String */ +#define btBit 24 /* Aligned Bit String */ +#define btPicture 25 /* Picture */ +#define btVoid 26 /* void */ +#define btLongLong 27 /* long long */ +#define btULongLong 28 /* unsigned long long */ +#define btMax 64 diff --git a/base/loader/ecoff_object.cc b/base/loader/ecoff_object.cc new file mode 100644 index 000000000..87ad6fdca --- /dev/null +++ b/base/loader/ecoff_object.cc @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "ecoff_object.hh" + +#include "functional_memory.hh" +#include "symtab.hh" + +#include "trace.hh" // for DPRINTF + +#include "exec_ecoff.h" +#include "coff_sym.h" +#include "coff_symconst.h" + +using namespace std; + +ObjectFile * +EcoffObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) +{ + if (((ecoff_filehdr *)data)->f_magic == ECOFF_MAGIC_ALPHA) { + // it's Alpha ECOFF + return new EcoffObject(fname, fd, len, data); + } + else { + return NULL; + } +} + + +EcoffObject::EcoffObject(const string &_filename, int _fd, + size_t _len, uint8_t *_data) + : ObjectFile(_filename, _fd, _len, _data) +{ + execHdr = (ecoff_exechdr *)fileData; + fileHdr = &(execHdr->f); + aoutHdr = &(execHdr->a); + + entry = aoutHdr->entry; + + text.baseAddr = aoutHdr->text_start; + text.size = aoutHdr->tsize; + + data.baseAddr = aoutHdr->data_start; + data.size = aoutHdr->dsize; + + bss.baseAddr = aoutHdr->bss_start; + bss.size = aoutHdr->bsize; + + DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", + text.baseAddr, text.size, data.baseAddr, data.size, + bss.baseAddr, bss.size); +} + + +bool +EcoffObject::loadSections(FunctionalMemory *mem, bool loadPhys) +{ + Addr textAddr = text.baseAddr; + Addr dataAddr = data.baseAddr; + + if (loadPhys) { + textAddr &= (ULL(1) << 40) - 1; + dataAddr &= (ULL(1) << 40) - 1; + } + + // Since we don't really have an MMU and all memory is + // zero-filled, there's no need to set up the BSS segment. + mem->prot_write(textAddr, fileData + ECOFF_TXTOFF(execHdr), text.size); + mem->prot_write(dataAddr, fileData + ECOFF_DATOFF(execHdr), data.size); + + return true; +} + + +bool +EcoffObject::loadGlobalSymbols(SymbolTable *symtab) +{ + if (!symtab) + return false; + + if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) { + cprintf("wrong magic\n"); + return false; + } + + ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr); + if (syms->magic != magicSym2) { + cprintf("bad symbol header magic\n"); + exit(1); + } + + ecoff_extsym *ext_syms = (ecoff_extsym *)(fileData + syms->cbExtOffset); + + char *ext_strings = (char *)(fileData + syms->cbSsExtOffset); + for (int i = 0; i < syms->iextMax; i++) { + ecoff_sym *entry = &(ext_syms[i].asym); + if (entry->iss != -1) + symtab->insert(entry->value, ext_strings + entry->iss); + } + + return true; +} + +bool +EcoffObject::loadLocalSymbols(SymbolTable *symtab) +{ + if (!symtab) + return false; + + if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) { + cprintf("wrong magic\n"); + return false; + } + + ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr); + if (syms->magic != magicSym2) { + cprintf("bad symbol header magic\n"); + exit(1); + } + + ecoff_sym *local_syms = (ecoff_sym *)(fileData + syms->cbSymOffset); + char *local_strings = (char *)(fileData + syms->cbSsOffset); + ecoff_fdr *fdesc = (ecoff_fdr *)(fileData + syms->cbFdOffset); + + for (int i = 0; i < syms->ifdMax; i++) { + ecoff_sym *entry = (ecoff_sym *)(local_syms + fdesc[i].isymBase); + char *strings = (char *)(local_strings + fdesc[i].issBase); + for (int j = 0; j < fdesc[i].csym; j++) { + if (entry[j].st == stGlobal || entry[j].st == stProc) + if (entry[j].iss != -1) + symtab->insert(entry[j].value, strings + entry[j].iss); + } + } + + for (int i = 0; i < syms->isymMax; i++) { + ecoff_sym *entry = &(local_syms[i]); + if (entry->st == stProc) + symtab->insert(entry->value, local_strings + entry->iss); + } + + return true; +} diff --git a/base/loader/ecoff_object.hh b/base/loader/ecoff_object.hh new file mode 100644 index 000000000..af757cd0e --- /dev/null +++ b/base/loader/ecoff_object.hh @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __ECOFF_OBJECT_HH__ +#define __ECOFF_OBJECT_HH__ + +#include "object_file.hh" + +// forward decls: avoid including exec_ecoff.h here +struct ecoff_exechdr; +struct ecoff_filehdr; +struct ecoff_aouthdr; + +class EcoffObject : public ObjectFile +{ + protected: + ecoff_exechdr *execHdr; + ecoff_filehdr *fileHdr; + ecoff_aouthdr *aoutHdr; + + EcoffObject(const std::string &_filename, int _fd, + size_t _len, uint8_t *_data); + + public: + virtual ~EcoffObject() {} + + virtual bool loadSections(FunctionalMemory *mem, + bool loadPhys = false); + virtual bool loadGlobalSymbols(SymbolTable *symtab); + virtual bool loadLocalSymbols(SymbolTable *symtab); + + static ObjectFile *tryFile(const std::string &fname, int fd, + size_t len, uint8_t *data); +}; + +#endif // __ECOFF_OBJECT_HH__ diff --git a/base/loader/elf_object.cc b/base/loader/elf_object.cc new file mode 100644 index 000000000..97f50e289 --- /dev/null +++ b/base/loader/elf_object.cc @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "elf_object.hh" + +#include "functional_memory.hh" +#include "symtab.hh" + +#include "trace.hh" // for DPRINTF + +#include "exec_elf.h" + +using namespace std; + +ObjectFile * +ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) +{ + if (memcmp(((Elf64_Ehdr *)data)->e_ident, ELFMAG, SELFMAG) == 0) { + // for now we'll assume it's a 64-bit Alpha binary + return new ElfObject(fname, fd, len, data); + } + else { + return NULL; + } +} + + +ElfObject::ElfObject(const string &_filename, int _fd, + size_t _len, uint8_t *_data) + : ObjectFile(_filename, _fd, _len, _data) +{ + ehdr = (Elf64_Ehdr *)fileData; + + entry = ehdr->e_entry; + + phdr = (Elf64_Phdr *)(fileData + ehdr->e_phoff); + assert(sizeof(Elf64_Phdr) == ehdr->e_phentsize); + + bool foundText = false; + bool foundData = false; + for (int i = 0; i < ehdr->e_phnum; ++i) { + Elf64_Phdr *p = &phdr[i]; + + // for now we don't care about non-loadable segments + if (!(p->p_type & PT_LOAD)) + continue; + + if (p->p_flags & PF_X) { + // executable: must be text + assert(!foundText); + foundText = true; + textPhdrIdx = i; + text.baseAddr = p->p_vaddr; + text.size = p->p_filesz; + assert(p->p_filesz == p->p_memsz); + } + else { + assert(p->p_flags & PF_R); + assert(!foundData); + foundData = true; + dataPhdrIdx = i; + data.baseAddr = p->p_vaddr; + data.size = p->p_filesz; + bss.baseAddr = data.baseAddr + data.size; + bss.size = p->p_memsz - p->p_filesz; + } + } + + assert(foundText && foundData); + + DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", + text.baseAddr, text.size, data.baseAddr, data.size, + bss.baseAddr, bss.size); +} + + +bool +ElfObject::loadSections(FunctionalMemory *mem, bool loadPhys) +{ + Addr textAddr = text.baseAddr; + Addr dataAddr = data.baseAddr; + + if (loadPhys) { + textAddr &= (ULL(1) << 40) - 1; + dataAddr &= (ULL(1) << 40) - 1; + } + + // Since we don't really have an MMU and all memory is + // zero-filled, there's no need to set up the BSS segment. + if (text.size != 0) + mem->prot_write(textAddr, fileData + phdr[textPhdrIdx].p_offset, + text.size); + if (data.size != 0) + mem->prot_write(dataAddr, fileData + phdr[dataPhdrIdx].p_offset, + data.size); + + return true; +} + + +bool +ElfObject::loadGlobalSymbols(SymbolTable *symtab) +{ + // symbols not supported yet + return false; +} + +bool +ElfObject::loadLocalSymbols(SymbolTable *symtab) +{ + // symbols not supported yet + return false; +} diff --git a/base/loader/elf_object.hh b/base/loader/elf_object.hh new file mode 100644 index 000000000..c90f6ebd5 --- /dev/null +++ b/base/loader/elf_object.hh @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __ELF_OBJECT_HH__ +#define __ELF_OBJECT_HH__ + +#include "object_file.hh" + +// forward decls: avoid including exec_elf.hh here +struct Elf64_Ehdr; +struct Elf64_Phdr; + +class ElfObject : public ObjectFile +{ + protected: + Elf64_Ehdr *ehdr; + Elf64_Phdr *phdr; + + int textPhdrIdx; + int dataPhdrIdx; + + ElfObject(const std::string &_filename, int _fd, + size_t _len, uint8_t *_data); + + public: + virtual ~ElfObject() {} + + virtual bool loadSections(FunctionalMemory *mem, + bool loadPhys = false); + virtual bool loadGlobalSymbols(SymbolTable *symtab); + virtual bool loadLocalSymbols(SymbolTable *symtab); + + static ObjectFile *tryFile(const std::string &fname, int fd, + size_t len, uint8_t *data); +}; + +#endif // __ELF_OBJECT_HH__ diff --git a/base/loader/exec_aout.h b/base/loader/exec_aout.h new file mode 100644 index 000000000..baed30c42 --- /dev/null +++ b/base/loader/exec_aout.h @@ -0,0 +1,62 @@ +/* $Id$ */ + +/* + * Taken from NetBSD sys/exec_aout.h + */ + +/* $NetBSD: exec_aout.h,v 1.29 2002/12/10 17:14:31 thorpej Exp $ */ + +/* + * Copyright (c) 1993, 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_EXEC_AOUT_H_ +#define _SYS_EXEC_AOUT_H_ + +#ifndef N_PAGSIZ +#define N_PAGSIZ(ex) (AOUT_LDPGSZ) +#endif + +/* a_magic */ +#define OMAGIC 0407 /* old impure format */ +#define NMAGIC 0410 /* read-only text */ +#define ZMAGIC 0413 /* demand load format */ + +#define N_ALIGN(ex,x) \ + (N_GETMAGIC(ex) == ZMAGIC ? \ + ((x) + AOUT_LDPGSZ - 1) & ~(AOUT_LDPGSZ - 1) : (x)) + +/* Valid magic number check. */ +#define N_BADMAG(ex) \ + (N_GETMAGIC(ex) != NMAGIC && N_GETMAGIC(ex) != OMAGIC && \ + N_GETMAGIC(ex) != ZMAGIC) + +#include "aout_machdep.h" + +#endif /* !_SYS_EXEC_AOUT_H_ */ diff --git a/base/loader/exec_ecoff.h b/base/loader/exec_ecoff.h new file mode 100644 index 000000000..8c559ab90 --- /dev/null +++ b/base/loader/exec_ecoff.h @@ -0,0 +1,111 @@ +/* $Id$ */ + +/* + * Taken from NetBSD sys/exec_ecoff.h + */ + +/* $NetBSD: exec_ecoff.h,v 1.13 2003/01/18 09:53:18 thorpej Exp $ */ + +/* + * Copyright (c) 1994 Adam Glass + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Adam Glass. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_EXEC_ECOFF_H_ +#define _SYS_EXEC_ECOFF_H_ + +#include "ecoff_machdep.h" + +struct ecoff_filehdr { + coff_ushort f_magic; /* magic number */ + coff_ushort f_nscns; /* # of sections */ + coff_uint f_timdat; /* time and date stamp */ + coff_ulong f_symptr; /* file offset of symbol table */ + coff_uint f_nsyms; /* # of symbol table entries */ + coff_ushort f_opthdr; /* sizeof the optional header */ + coff_ushort f_flags; /* flags??? */ +}; + +struct ecoff_aouthdr { + coff_ushort magic; + coff_ushort vstamp; + ECOFF_PAD + coff_ulong tsize; + coff_ulong dsize; + coff_ulong bsize; + coff_ulong entry; + coff_ulong text_start; + coff_ulong data_start; + coff_ulong bss_start; + ECOFF_MACHDEP; +}; + +struct ecoff_scnhdr { /* needed for size info */ + char s_name[8]; /* name */ + coff_ulong s_paddr; /* physical addr? for ROMing?*/ + coff_ulong s_vaddr; /* virtual addr? */ + coff_ulong s_size; /* size */ + coff_ulong s_scnptr; /* file offset of raw data */ + coff_ulong s_relptr; /* file offset of reloc data */ + coff_ulong s_lnnoptr; /* file offset of line data */ + coff_ushort s_nreloc; /* # of relocation entries */ + coff_ushort s_nlnno; /* # of line entries */ + coff_uint s_flags; /* flags */ +}; + +struct ecoff_exechdr { + struct ecoff_filehdr f; + struct ecoff_aouthdr a; +}; + +#define ECOFF_HDR_SIZE (sizeof(struct ecoff_exechdr)) + +#define ECOFF_OMAGIC 0407 +#define ECOFF_NMAGIC 0410 +#define ECOFF_ZMAGIC 0413 + +#define ECOFF_ROUND(value, by) \ + (((value) + (by) - 1) & ~((by) - 1)) + +#define ECOFF_BLOCK_ALIGN(ep, value) \ + ((ep)->a.magic == ECOFF_ZMAGIC ? ECOFF_ROUND((value), ECOFF_LDPGSZ) : \ + (value)) + +#define ECOFF_TXTOFF(ep) \ + ((ep)->a.magic == ECOFF_ZMAGIC ? 0 : \ + ECOFF_ROUND(ECOFF_HDR_SIZE + (ep)->f.f_nscns * \ + sizeof(struct ecoff_scnhdr), ECOFF_SEGMENT_ALIGNMENT(ep))) + +#define ECOFF_DATOFF(ep) \ + (ECOFF_BLOCK_ALIGN((ep), ECOFF_TXTOFF(ep) + (ep)->a.tsize)) + +#define ECOFF_SEGMENT_ALIGN(ep, value) \ + (ECOFF_ROUND((value), ((ep)->a.magic == ECOFF_ZMAGIC ? ECOFF_LDPGSZ : \ + ECOFF_SEGMENT_ALIGNMENT(ep)))) + +#endif /* !_SYS_EXEC_ECOFF_H_ */ diff --git a/base/loader/object_file.cc b/base/loader/object_file.cc new file mode 100644 index 000000000..07b10b5ee --- /dev/null +++ b/base/loader/object_file.cc @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "cprintf.hh" +#include "object_file.hh" +#include "symtab.hh" + +#include "ecoff_object.hh" +#include "aout_object.hh" +#include "elf_object.hh" + +using namespace std; + +ObjectFile::ObjectFile(const string &_filename, int _fd, + size_t _len, uint8_t *_data) + : filename(_filename), descriptor(_fd), fileData(_data), len(_len) +{ +} + + +ObjectFile::~ObjectFile() +{ + close(); +} + + +void +ObjectFile::close() +{ + if (descriptor >= 0) { + ::close(descriptor); + descriptor = -1; + } + + if (fileData) { + ::munmap(fileData, len); + fileData = NULL; + } +} + + +ObjectFile * +createObjectFile(const string &fname) +{ + // open the file + int fd = open(fname.c_str(), O_RDONLY); + if (fd < 0) { + return NULL; + } + + // find the length of the file by seeking to the end + size_t len = (size_t)lseek(fd, 0, SEEK_END); + + // mmap the whole shebang + uint8_t *fileData = + (uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); + if (fileData == MAP_FAILED) { + close(fd); + return NULL; + } + + ObjectFile *fileObj = NULL; + + // figure out what we have here + if ((fileObj = EcoffObject::tryFile(fname, fd, len, fileData)) != NULL) { + return fileObj; + } + + if ((fileObj = AoutObject::tryFile(fname, fd, len, fileData)) != NULL) { + return fileObj; + } + + if ((fileObj = ElfObject::tryFile(fname, fd, len, fileData)) != NULL) { + return fileObj; + } + + // don't know what it is + close(fd); + munmap(fileData, len); + return NULL; +} diff --git a/base/loader/object_file.hh b/base/loader/object_file.hh new file mode 100644 index 000000000..1e37b7b70 --- /dev/null +++ b/base/loader/object_file.hh @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __OBJECT_FILE_HH__ +#define __OBJECT_FILE_HH__ + +#include "isa_traits.hh" // for Addr + +class FunctionalMemory; +class SymbolTable; + +class ObjectFile +{ + protected: + const std::string filename; + int descriptor; + uint8_t *fileData; + size_t len; + + ObjectFile(const std::string &_filename, int _fd, + size_t _len, uint8_t *_data); + + public: + virtual ~ObjectFile(); + + void close(); + + virtual bool loadSections(FunctionalMemory *mem, + bool loadPhys = false) = 0; + virtual bool loadGlobalSymbols(SymbolTable *symtab) = 0; + virtual bool loadLocalSymbols(SymbolTable *symtab) = 0; + + protected: + + struct Section { + Addr baseAddr; + size_t size; + }; + + Addr entry; + Addr globalPtr; + + Section text; + Section data; + Section bss; + + public: + Addr entryPoint() const { return entry; } + Addr globalPointer() const { return globalPtr; } + + Addr textBase() const { return text.baseAddr; } + Addr dataBase() const { return data.baseAddr; } + Addr bssBase() const { return bss.baseAddr; } + + size_t textSize() const { return text.size; } + size_t dataSize() const { return data.size; } + size_t bssSize() const { return bss.size; } +}; + +ObjectFile *createObjectFile(const std::string &fname); + + +#endif // __OBJECT_FILE_HH__ diff --git a/base/loader/symtab.cc b/base/loader/symtab.cc new file mode 100644 index 000000000..7beee182b --- /dev/null +++ b/base/loader/symtab.cc @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "host.hh" +#include "misc.hh" +#include "str.hh" +#include "symtab.hh" + +using namespace std; + +bool +SymbolTable::insert(Addr address, string symbol) +{ + if (!addrTable.insert(make_pair(address, symbol)).second) + return false; + + if (!symbolTable.insert(make_pair(symbol, address)).second) + return false; + + return true; +} + + +bool +SymbolTable::load(const string &filename) +{ + string buffer; + ifstream file(filename.c_str()); + + if (!file) { + cerr << "Can't open symbol table file " << filename << endl; + fatal("file error"); + } + + while (!file.eof()) { + getline(file, buffer); + if (buffer.empty()) + continue; + + int idx = buffer.find(','); + if (idx == string::npos) + return false; + + string address = buffer.substr(0, idx); + eat_white(address); + if (address.empty()) + return false; + + string symbol = buffer.substr(idx + 1); + eat_white(symbol); + if (symbol.empty()) + return false; + + Addr addr; + if (!to_number(address, addr)) + return false; + + if (!insert(addr, symbol)) + return false; + } + + file.close(); + + return true; +} + +bool +SymbolTable::findSymbol(Addr address, string &symbol) const +{ + ATable::const_iterator i = addrTable.find(address); + if (i == addrTable.end()) + return false; + + symbol = (*i).second; + return true; +} + +bool +SymbolTable::findAddress(const string &symbol, Addr &address) const +{ + STable::const_iterator i = symbolTable.find(symbol); + if (i == symbolTable.end()) + return false; + + address = (*i).second; + return true; +} + +string +SymbolTable::find(Addr addr) const +{ + string s; + findSymbol(addr, s); + return s; +} + +Addr +SymbolTable::find(const string &symbol) const +{ + Addr a = 0; + findAddress(symbol, a); + return a; +} diff --git a/base/loader/symtab.hh b/base/loader/symtab.hh new file mode 100644 index 000000000..073325eba --- /dev/null +++ b/base/loader/symtab.hh @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SYMTAB_HH__ +#define __SYMTAB_HH__ + +#include "hashmap.hh" +#include "isa_traits.hh" // for Addr + +class SymbolTable +{ + private: + typedef m5::hash_map ATable; + typedef m5::hash_map STable; + + ATable addrTable; + STable symbolTable; + + public: + SymbolTable() {} + SymbolTable(const std::string &file) { load(file); } + ~SymbolTable() {} + + bool insert(Addr address, std::string symbol); + bool load(const std::string &file); + + bool findSymbol(Addr address, std::string &symbol) const; + bool findAddress(const std::string &symbol, Addr &address) const; + + std::string find(Addr addr) const; + Addr find(const std::string &symbol) const; +}; + +#endif // __SYMTAB_HH__ diff --git a/base/object_file.cc b/base/object_file.cc deleted file mode 100644 index 07b10b5ee..000000000 --- a/base/object_file.cc +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include -#include -#include -#include -#include - -#include "cprintf.hh" -#include "object_file.hh" -#include "symtab.hh" - -#include "ecoff_object.hh" -#include "aout_object.hh" -#include "elf_object.hh" - -using namespace std; - -ObjectFile::ObjectFile(const string &_filename, int _fd, - size_t _len, uint8_t *_data) - : filename(_filename), descriptor(_fd), fileData(_data), len(_len) -{ -} - - -ObjectFile::~ObjectFile() -{ - close(); -} - - -void -ObjectFile::close() -{ - if (descriptor >= 0) { - ::close(descriptor); - descriptor = -1; - } - - if (fileData) { - ::munmap(fileData, len); - fileData = NULL; - } -} - - -ObjectFile * -createObjectFile(const string &fname) -{ - // open the file - int fd = open(fname.c_str(), O_RDONLY); - if (fd < 0) { - return NULL; - } - - // find the length of the file by seeking to the end - size_t len = (size_t)lseek(fd, 0, SEEK_END); - - // mmap the whole shebang - uint8_t *fileData = - (uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); - if (fileData == MAP_FAILED) { - close(fd); - return NULL; - } - - ObjectFile *fileObj = NULL; - - // figure out what we have here - if ((fileObj = EcoffObject::tryFile(fname, fd, len, fileData)) != NULL) { - return fileObj; - } - - if ((fileObj = AoutObject::tryFile(fname, fd, len, fileData)) != NULL) { - return fileObj; - } - - if ((fileObj = ElfObject::tryFile(fname, fd, len, fileData)) != NULL) { - return fileObj; - } - - // don't know what it is - close(fd); - munmap(fileData, len); - return NULL; -} diff --git a/base/object_file.hh b/base/object_file.hh deleted file mode 100644 index 1e37b7b70..000000000 --- a/base/object_file.hh +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __OBJECT_FILE_HH__ -#define __OBJECT_FILE_HH__ - -#include "isa_traits.hh" // for Addr - -class FunctionalMemory; -class SymbolTable; - -class ObjectFile -{ - protected: - const std::string filename; - int descriptor; - uint8_t *fileData; - size_t len; - - ObjectFile(const std::string &_filename, int _fd, - size_t _len, uint8_t *_data); - - public: - virtual ~ObjectFile(); - - void close(); - - virtual bool loadSections(FunctionalMemory *mem, - bool loadPhys = false) = 0; - virtual bool loadGlobalSymbols(SymbolTable *symtab) = 0; - virtual bool loadLocalSymbols(SymbolTable *symtab) = 0; - - protected: - - struct Section { - Addr baseAddr; - size_t size; - }; - - Addr entry; - Addr globalPtr; - - Section text; - Section data; - Section bss; - - public: - Addr entryPoint() const { return entry; } - Addr globalPointer() const { return globalPtr; } - - Addr textBase() const { return text.baseAddr; } - Addr dataBase() const { return data.baseAddr; } - Addr bssBase() const { return bss.baseAddr; } - - size_t textSize() const { return text.size; } - size_t dataSize() const { return data.size; } - size_t bssSize() const { return bss.size; } -}; - -ObjectFile *createObjectFile(const std::string &fname); - - -#endif // __OBJECT_FILE_HH__ diff --git a/base/predictor.hh b/base/predictor.hh new file mode 100644 index 000000000..7c446f26c --- /dev/null +++ b/base/predictor.hh @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// Abstract base class for a generic predictor +// +// + +#ifndef __PREDICTOR_HH__ +#define __PREDICTOR_HH__ + +struct stat_sdb_t; + +class GenericPredictor { + + public: + virtual void clear() = 0; + + virtual unsigned predict(unsigned long _index) = 0; + virtual unsigned predict(unsigned long _index, unsigned &pdata) = 0; + + virtual unsigned peek(unsigned long _index) = 0; + + virtual void record(unsigned long _index, unsigned _actual_value, + unsigned _pred_value) = 0; + virtual void record(unsigned long _index, unsigned _actual_value, + unsigned _pred_value, unsigned _pdata) = 0; + + virtual unsigned value(unsigned long _index) = 0; + + virtual void regStats() = 0; + virtual void regFormulas() = 0; + + virtual ~GenericPredictor() {}; +}; + +#endif // __PREDICTOR_HH__ diff --git a/base/sat_counter.cc b/base/sat_counter.cc new file mode 100644 index 000000000..dc365f0f3 --- /dev/null +++ b/base/sat_counter.cc @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "sat_counter.hh" + +#include "statistics.hh" +#include "sim_stats.hh" + + +using namespace std; + + +SaturatingCounterPred::SaturatingCounterPred(string p_name, + string z_name, + string o_name, + unsigned _index_bits, + unsigned _counter_bits, + unsigned _zero_change, + unsigned _one_change, + unsigned _thresh, + unsigned _init_value) +{ + pred_name = p_name; + zero_name = z_name; + one_name = o_name; + + index_bits = _index_bits; + counter_bits = _counter_bits; + zero_change = _zero_change; + one_change = _one_change; + thresh = _thresh; + init_value = _init_value; + + max_index = (1 << index_bits) - 1; + max_value = (1 << counter_bits) - 1; + + table = new unsigned[max_index + 1]; + + // Initialize with the right parameters & clear the counter + for (int i = 0; i <= max_index; ++i) + table[i] = init_value; +} + +void SaturatingCounterPred::regStats() +{ + using namespace Statistics; + stringstream name, description; + + // + // Number of predictions + // + name << pred_name << ":" << zero_name << ":preds"; + description << "number of predictions of " << zero_name; + predicted_zero + .name(name.str()) + .desc(description.str()) + ; + description.str(""); + name.str(""); + + name << pred_name << ":" << one_name << ":preds"; + description << "number of predictions of " << one_name; + predicted_one + .name(name.str()) + .desc(description.str()) + ; + description.str(""); + name.str(""); + + // + // Count the number of correct predictions + // + name << pred_name << ":" << zero_name << ":corr_preds"; + description << "number of correct " << zero_name << " preds"; + correct_pred_zero + .name(name.str()) + .desc(description.str()) + ; + description.str(""); + name.str(""); + + name << pred_name << ":" << one_name << ":corr_preds"; + description << "number of correct " << one_name << " preds"; + correct_pred_one + .name(name.str()) + .desc(description.str()) + ; + description.str(""); + name.str(""); + + // + // Number of predictor updates + // + name << pred_name << ":" << zero_name << ":updates"; + description << "number of actual " << zero_name << "s"; + record_zero + .name(name.str()) + .desc(description.str()) + ; + description.str(""); + name.str(""); + + name << pred_name << ":" << one_name << ":updates"; + description << "number of actual " << one_name << "s"; + record_one + .name(name.str()) + .desc(description.str()) + ; + description.str(""); + name.str(""); +} + +void SaturatingCounterPred::regFormulas() +{ + using namespace Statistics; + stringstream name, description; + + // + // Number of predictions + // + name << pred_name << ":predictions"; + preds_total + .name(name.str()) + .desc("total number of predictions made") + ; + preds_total = predicted_zero + predicted_one; + name.str(""); + + // + // Fraction of all predictions that are one or zero + // + name << pred_name << ":" << zero_name << ":pred_frac"; + description << "fraction of all preds that were " << zero_name; + pred_frac_zero + .name(name.str()) + .desc(description.str()) + ; + pred_frac_zero = 100 * predicted_zero / preds_total; + description.str(""); + name.str(""); + + name << pred_name << ":" << one_name << ":pred_frac"; + description << "fraction of all preds that were " << one_name; + pred_frac_one + .name(name.str()) + .desc(description.str()) + ; + pred_frac_one = 100 * predicted_one / preds_total; + description.str(""); + name.str(""); + + + // + // Count the number of correct predictions + // + name << pred_name << ":correct_preds"; + correct_total + .name(name.str()) + .desc("total correct predictions made") + ; + correct_total = correct_pred_one + correct_pred_zero; + name.str(""); + + // + // Number of predictor updates + // + name << pred_name << ":updates"; + updates_total + .name(name.str()) + .desc("total number of updates") + ; + updates_total = record_zero + record_one; + name.str(""); + + // + // Prediction accuracy rates + // + name << pred_name << ":pred_rate"; + pred_rate + .name(name.str()) + .desc("correct fraction of all preds") + ; + pred_rate = correct_total / updates_total; + name.str(""); + + name << pred_name << ":" << zero_name << ":pred_rate"; + description << "fraction of " << zero_name << " preds that were correct"; + frac_correct_zero + .name(name.str()) + .desc(description.str()) + ; + frac_correct_zero = 100 * correct_pred_zero / + (correct_pred_zero + record_one - correct_pred_one); + description.str(""); + name.str(""); + + name << pred_name << ":" << one_name << ":pred_rate"; + description << "fraction of " << one_name << " preds that were correct"; + frac_correct_one + .name(name.str()) + .desc(description.str()) + ; + frac_correct_one = 100 * correct_pred_one / + (correct_pred_one + record_zero - correct_pred_zero); + description.str(""); + name.str(""); + + // + // Coverage + // + name << pred_name << ":" << zero_name << ":coverage"; + description << "fraction of " << zero_name + << "s that were predicted correctly"; + coverage_zero + .name(name.str()) + .desc(description.str()) + ; + coverage_zero = 100 * correct_pred_zero / record_zero; + description.str(""); + name.str(""); + + name << pred_name << ":" << one_name << ":coverage"; + description << "fraction of " << one_name + << "s that were predicted correctly"; + coverage_one + .name(name.str()) + .desc(description.str()) + ; + coverage_one = 100 * correct_pred_one / record_one; + description.str(""); + name.str(""); +} + + + + + + + + + + diff --git a/base/sat_counter.hh b/base/sat_counter.hh new file mode 100644 index 000000000..18eab3574 --- /dev/null +++ b/base/sat_counter.hh @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SAT_COUNTER_HH__ +#define __SAT_COUNTER_HH__ + +#include + +#include "predictor.hh" + +#include "statistics.hh" +#include "sim_stats.hh" + +struct stat_sdb_t; + +// +// +// A simple saturating counter predictor +// +// +class SaturatingCounterPred : public GenericPredictor +{ + private: + std::string pred_name; + std::string zero_name; + std::string one_name; + + unsigned index_bits; + unsigned counter_bits; + unsigned zero_change; + unsigned one_change; + unsigned thresh; + unsigned init_value; + + unsigned max_value; // maximum counter value + + unsigned long max_index; // also the index mask value + unsigned *table; + + // Statistics + Statistics::Scalar<> predicted_one; // Total predictions of one, preds_one + Statistics::Scalar<> predicted_zero; // Total predictions of zero, preds_zero + Statistics::Scalar<> correct_pred_one; // Total correct predictions of one, correct_one + Statistics::Scalar<> correct_pred_zero; // Total correct predictions of zero, correct_zero + + Statistics::Scalar<> record_zero; //updates_zero + Statistics::Scalar<> record_one; //updates_one + + Statistics::Formula preds_total; + Statistics::Formula pred_frac_zero; + Statistics::Formula pred_frac_one; + Statistics::Formula correct_total; + Statistics::Formula updates_total; + Statistics::Formula pred_rate; + Statistics::Formula frac_correct_zero; + Statistics::Formula frac_correct_one; + Statistics::Formula coverage_zero; + Statistics::Formula coverage_one; + + private: + bool pred_one(unsigned &counter) { return counter > thresh; } + bool pred_zero(unsigned &counter) { return counter <= thresh; } + + void update_one(unsigned &counter) { + + if (one_change) + counter += one_change; + else + counter = 0; + + // check for wrap + if (counter > max_value) + counter = max_value; + } + + void update_zero(unsigned &counter) { + if (zero_change) { + // check for wrap + if (counter < zero_change) + counter = 0; + else + counter -= zero_change; + } else + counter = 0; + } + + + public: + + SaturatingCounterPred(std::string p_name, + std::string z_name, std::string o_name, + unsigned _index_bits, unsigned _counter_bits = 2, + unsigned _zero_change = 1, unsigned _one_change = 1, + unsigned _thresh = 1, unsigned _init_value = 0); + + void clear() { + for (int i = 0; i <= max_index; ++i) + table[i] = init_value; + } + + // Record the ACTUAL result... and indicate whether the prediction + // corresponding to this event was correct + void record(unsigned long _index, unsigned _val, unsigned _predicted, + unsigned _pdata) + { + record(_index, _val, _predicted); + } + + void record(unsigned long _index, unsigned _val, unsigned _predicted) { + unsigned long index = _index & max_index; + + if (_val) { + update_one(table[index]); + ++record_one; + + if (_predicted) + ++correct_pred_one; + } else { + update_zero(table[index]); + ++record_zero; + + if (!_predicted) + ++correct_pred_zero; + } + } + + unsigned value(unsigned long _index) { + unsigned long index = _index & max_index; + + return table[index]; + } + + + unsigned predict(unsigned long _index, unsigned &pdata) { + return predict(_index); + } + + unsigned predict(unsigned long _index) { + unsigned long index = _index & max_index; + + if (pred_one(table[index])) { + ++predicted_one; + return 1; + } + + ++predicted_zero; + return 0; + } + + // No internal state is changed here + unsigned peek(unsigned long _index) { + unsigned long index = _index & max_index; + + if (pred_one(table[index])) + return 1; + + return 0; + } + + + //======================================================= + void regStats(); + void regFormulas(); +}; + + +#endif // __SAT_COUNTER_HH__ diff --git a/base/symtab.cc b/base/symtab.cc deleted file mode 100644 index 7beee182b..000000000 --- a/base/symtab.cc +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -#include "host.hh" -#include "misc.hh" -#include "str.hh" -#include "symtab.hh" - -using namespace std; - -bool -SymbolTable::insert(Addr address, string symbol) -{ - if (!addrTable.insert(make_pair(address, symbol)).second) - return false; - - if (!symbolTable.insert(make_pair(symbol, address)).second) - return false; - - return true; -} - - -bool -SymbolTable::load(const string &filename) -{ - string buffer; - ifstream file(filename.c_str()); - - if (!file) { - cerr << "Can't open symbol table file " << filename << endl; - fatal("file error"); - } - - while (!file.eof()) { - getline(file, buffer); - if (buffer.empty()) - continue; - - int idx = buffer.find(','); - if (idx == string::npos) - return false; - - string address = buffer.substr(0, idx); - eat_white(address); - if (address.empty()) - return false; - - string symbol = buffer.substr(idx + 1); - eat_white(symbol); - if (symbol.empty()) - return false; - - Addr addr; - if (!to_number(address, addr)) - return false; - - if (!insert(addr, symbol)) - return false; - } - - file.close(); - - return true; -} - -bool -SymbolTable::findSymbol(Addr address, string &symbol) const -{ - ATable::const_iterator i = addrTable.find(address); - if (i == addrTable.end()) - return false; - - symbol = (*i).second; - return true; -} - -bool -SymbolTable::findAddress(const string &symbol, Addr &address) const -{ - STable::const_iterator i = symbolTable.find(symbol); - if (i == symbolTable.end()) - return false; - - address = (*i).second; - return true; -} - -string -SymbolTable::find(Addr addr) const -{ - string s; - findSymbol(addr, s); - return s; -} - -Addr -SymbolTable::find(const string &symbol) const -{ - Addr a = 0; - findAddress(symbol, a); - return a; -} diff --git a/base/symtab.hh b/base/symtab.hh deleted file mode 100644 index 073325eba..000000000 --- a/base/symtab.hh +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SYMTAB_HH__ -#define __SYMTAB_HH__ - -#include "hashmap.hh" -#include "isa_traits.hh" // for Addr - -class SymbolTable -{ - private: - typedef m5::hash_map ATable; - typedef m5::hash_map STable; - - ATable addrTable; - STable symbolTable; - - public: - SymbolTable() {} - SymbolTable(const std::string &file) { load(file); } - ~SymbolTable() {} - - bool insert(Addr address, std::string symbol); - bool load(const std::string &file); - - bool findSymbol(Addr address, std::string &symbol) const; - bool findAddress(const std::string &symbol, Addr &address) const; - - std::string find(Addr addr) const; - Addr find(const std::string &symbol) const; -}; - -#endif // __SYMTAB_HH__ diff --git a/cpu/base_cpu.cc b/cpu/base_cpu.cc new file mode 100644 index 000000000..06b2ec65c --- /dev/null +++ b/cpu/base_cpu.cc @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "base_cpu.hh" +#include "cprintf.hh" +#include "exec_context.hh" +#include "misc.hh" +#include "sim_events.hh" + +using namespace std; + +vector BaseCPU::cpuList; + +// This variable reflects the max number of threads in any CPU. Be +// careful to only use it once all the CPUs that you care about have +// been initialized +int maxThreadsPerCPU = 1; + +#ifdef FULL_SYSTEM +BaseCPU::BaseCPU(const string &_name, int _number_of_threads, + Counter max_insts_any_thread, + Counter max_insts_all_threads, + System *_system, int num, Tick freq) + : SimObject(_name), number(num), frequency(freq), + number_of_threads(_number_of_threads), system(_system) +#else +BaseCPU::BaseCPU(const string &_name, int _number_of_threads, + Counter max_insts_any_thread, + Counter max_insts_all_threads) + : SimObject(_name), number_of_threads(_number_of_threads) +#endif +{ + // add self to global list of CPUs + cpuList.push_back(this); + + if (number_of_threads > maxThreadsPerCPU) + maxThreadsPerCPU = number_of_threads; + + // allocate per-thread instruction-based event queues + comInsnEventQueue = new (EventQueue *)[number_of_threads]; + for (int i = 0; i < number_of_threads; ++i) + comInsnEventQueue[i] = new EventQueue("instruction-based event queue"); + + // + // set up instruction-count-based termination events, if any + // + if (max_insts_any_thread != 0) + for (int i = 0; i < number_of_threads; ++i) + new SimExitEvent(comInsnEventQueue[i], max_insts_any_thread, + "a thread reached the max instruction count"); + + if (max_insts_all_threads != 0) { + // allocate & initialize shared downcounter: each event will + // decrement this when triggered; simulation will terminate + // when counter reaches 0 + int *counter = new int; + *counter = number_of_threads; + for (int i = 0; i < number_of_threads; ++i) + new CountedExitEvent(comInsnEventQueue[i], + "all threads reached the max instruction count", + max_insts_all_threads, *counter); + } + +#ifdef FULL_SYSTEM + memset(interrupts, 0, sizeof(interrupts)); + intstatus = 0; +#endif +} + +void +BaseCPU::regStats() +{ + int size = contexts.size(); + if (size > 1) { + for (int i = 0; i < size; ++i) { + stringstream namestr; + ccprintf(namestr, "%s.ctx%d", name(), i); + contexts[i]->regStats(namestr.str()); + } + } else if (size == 1) + contexts[0]->regStats(name()); +} + +#ifdef FULL_SYSTEM +void +BaseCPU::post_interrupt(int int_num, int index) +{ + DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); + + if (int_num < 0 || int_num >= NumInterruptLevels) + panic("int_num out of bounds\n"); + + if (index < 0 || index >= sizeof(uint8_t) * 8) + panic("int_num out of bounds\n"); + + AlphaISA::check_interrupts = 1; + interrupts[int_num] |= 1 << index; + intstatus |= (ULL(1) << int_num); +} + +void +BaseCPU::clear_interrupt(int int_num, int index) +{ + DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); + + if (int_num < 0 || int_num >= NumInterruptLevels) + panic("int_num out of bounds\n"); + + if (index < 0 || index >= sizeof(uint8_t) * 8) + panic("int_num out of bounds\n"); + + interrupts[int_num] &= ~(1 << index); + if (interrupts[int_num] == 0) + intstatus &= ~(ULL(1) << int_num); +} + +void +BaseCPU::clear_interrupts() +{ + DPRINTF(Interrupt, "Interrupts all cleared\n"); + + memset(interrupts, 0, sizeof(interrupts)); + intstatus = 0; +} + +#endif // FULL_SYSTEM + +DEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU) diff --git a/cpu/base_cpu.hh b/cpu/base_cpu.hh new file mode 100644 index 000000000..745220d85 --- /dev/null +++ b/cpu/base_cpu.hh @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __BASE_CPU_HH__ +#define __BASE_CPU_HH__ + +#include + +#include "eventq.hh" +#include "sim_object.hh" + +#include "isa_traits.hh" // for Addr + +#ifdef FULL_SYSTEM +class System; +#endif + +class BranchPred; +class ExecContext; + +class BaseCPU : public SimObject +{ +#ifdef FULL_SYSTEM + protected: + int number; + Tick frequency; + uint8_t interrupts[NumInterruptLevels]; + uint64_t intstatus; + + public: + virtual void post_interrupt(int int_num, int index); + virtual void clear_interrupt(int int_num, int index); + virtual void clear_interrupts(); + + bool check_interrupt(int int_num) const { + if (int_num > NumInterruptLevels) + panic("int_num out of bounds\n"); + + return interrupts[int_num] != 0; + } + + bool check_interrupts() const { return intstatus != 0; } + uint64_t intr_status() const { return intstatus; } + + Tick getFreq() const { return frequency; } +#endif + + protected: + std::vector contexts; + + public: + virtual void execCtxStatusChg() {} + + public: + +#ifdef FULL_SYSTEM + BaseCPU(const std::string &_name, int _number_of_threads, + Counter max_insts_any_thread, Counter max_insts_all_threads, + System *_system, + int num, Tick freq); +#else + BaseCPU(const std::string &_name, int _number_of_threads, + Counter max_insts_any_thread = 0, + Counter max_insts_all_threads = 0); +#endif + + virtual ~BaseCPU() {} + + virtual void regStats(); + + /// Number of threads we're actually simulating (<= SMT_MAX_THREADS). + /// This is a constant for the duration of the simulation. + int number_of_threads; + + /// Vector of per-thread instruction-based event queues. Used for + /// scheduling events based on number of instructions committed by + /// a particular thread. + EventQueue **comInsnEventQueue; + +#ifdef FULL_SYSTEM + System *system; +#endif + + virtual bool filterThisInstructionPrefetch(int thread_number, + short asid, Addr prefetchTarget) const { return true; } + + /// Return pointer to CPU's branch predictor (NULL if none). + virtual BranchPred *getBranchPred() { return NULL; }; + + private: + static std::vector cpuList; //!< Static global cpu list + + public: + static int numSimulatedCPUs() { return cpuList.size(); } +}; + +#endif // __BASE_CPU_HH__ diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc new file mode 100644 index 000000000..c81d172a8 --- /dev/null +++ b/cpu/exec_context.cc @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "base_cpu.hh" +#include "exec_context.hh" + +#ifdef FULL_SYSTEM +#include "system.hh" +#else +#include "prog.hh" +#endif + +using namespace std; + +// constructor +#ifdef FULL_SYSTEM +ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, + AlphaItb *_itb, AlphaDtb *_dtb, + FunctionalMemory *_mem, int _cpu_id) + : kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num), mem(_mem), + itb(_itb), dtb(_dtb), cpu_id(_cpu_id), system(_sys), + memCtrl(_sys->memCtrl), physmem(_sys->physmem) +{ + memset(®s, 0, sizeof(RegFile)); + _status = Active; + func_exe_insn = 0; + storeCondFailures = 0; + system->registerExecContext(this); +} +#else +ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, + Process *_process, int _asid) + : cpu(_cpu), thread_num(_thread_num), process(_process), asid (_asid) +{ + + // Register with process object. Our 'active' will be set by the + // process iff we're the initial context. Others are reserved for + // dynamically created threads. + process->registerExecContext(this); + + mem = process->getMemory(); + + func_exe_insn = 0; + storeCondFailures = 0; +} + +ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, + FunctionalMemory *_mem, int _asid) + : cpu(_cpu), thread_num(_thread_num), process(NULL), mem(_mem), + asid(_asid) +{ +} +#endif + +void +ExecContext::setStatus(Status new_status) +{ +#ifdef FULL_SYSTEM + if (status() == new_status) + return; + + // Don't change the status from active if there are pending interrupts + if (new_status == Suspended && cpu->check_interrupts()) { + assert(status() == Active); + return; + } +#endif + + _status = new_status; + cpu->execCtxStatusChg(); +} + +void +ExecContext::regStats(const string &name) +{ +#ifdef FULL_SYSTEM + kernelStats.regStats(name + ".kern"); +#endif +} diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh new file mode 100644 index 000000000..988673a0f --- /dev/null +++ b/cpu/exec_context.hh @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __EXEC_CONTEXT_HH__ +#define __EXEC_CONTEXT_HH__ + +#include "host.hh" +#include "mem_req.hh" + +// forward declaration: see functional_memory.hh +class FunctionalMemory; +class PhysicalMemory; +class BaseCPU; + +#ifdef FULL_SYSTEM + +#include "alpha_memory.hh" +class MemoryController; + +#include "kernel_stats.hh" +#include "system.hh" + +#else // !FULL_SYSTEM + +#include "prog.hh" + +#endif // FULL_SYSTEM + +// +// The ExecContext object represents a functional context for +// instruction execution. It incorporates everything required for +// architecture-level functional simulation of a single thread. +// + +class ExecContext +{ + public: + enum Status { Unallocated, Active, Suspended, Halted }; + + private: + Status _status; + + public: + Status status() const { return _status; } + void setStatus(Status new_status); + +#ifdef FULL_SYSTEM + public: + KernelStats kernelStats; +#endif + + public: + RegFile regs; // correct-path register context + + // pointer to CPU associated with this context + BaseCPU *cpu; + + // Index of hardware thread context on the CPU that this represents. + int thread_num; + +#ifdef FULL_SYSTEM + + FunctionalMemory *mem; + AlphaItb *itb; + AlphaDtb *dtb; + int cpu_id; + System *system; + + // the following two fields are redundant, since we can always + // look them up through the system pointer, but we'll leave them + // here for now for convenience + MemoryController *memCtrl; + PhysicalMemory *physmem; + +#else + Process *process; + + FunctionalMemory *mem; // functional storage for process address space + + // Address space ID. Note that this is used for TIMING cache + // simulation only; all functional memory accesses should use + // one of the FunctionalMemory pointers above. + short asid; + +#endif + + + /* + * number of executed instructions, for matching with syscall trace + * points in EIO files. + */ + Counter func_exe_insn; + + // + // Count failed store conditionals so we can warn of apparent + // application deadlock situations. + unsigned storeCondFailures; + + // constructor: initialize context from given process structure +#ifdef FULL_SYSTEM + ExecContext(BaseCPU *_cpu, int _thread_num, System *_system, + AlphaItb *_itb, AlphaDtb *_dtb, FunctionalMemory *_dem, + int _cpu_id); +#else + ExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid); + ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem, + int _asid); +#endif + virtual ~ExecContext() {} + + void regStats(const std::string &name); + +#ifdef FULL_SYSTEM + bool validInstAddr(Addr addr) { return true; } + bool validDataAddr(Addr addr) { return true; } + int getInstAsid() { return ITB_ASN_ASN(regs.ipr[TheISA::IPR_ITB_ASN]); } + int getDataAsid() { return DTB_ASN_ASN(regs.ipr[TheISA::IPR_DTB_ASN]); } + + Fault translateInstReq(MemReqPtr req) + { + return itb->translate(req); + } + + Fault translateDataReadReq(MemReqPtr req) + { + return dtb->translate(req, false); + } + + Fault translateDataWriteReq(MemReqPtr req) + { + return dtb->translate(req, true); + } + + +#else + bool validInstAddr(Addr addr) + { return process->validInstAddr(addr); } + + bool validDataAddr(Addr addr) + { return process->validDataAddr(addr); } + + int getInstAsid() { return asid; } + int getDataAsid() { return asid; } + + Fault dummyTranslation(MemReqPtr req) + { +#if 0 + assert((req->vaddr >> 48 & 0xffff) == 0); +#endif + + // put the asid in the upper 16 bits of the paddr + req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16); + req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16; + return No_Fault; + } + Fault translateInstReq(MemReqPtr req) + { + return dummyTranslation(req); + } + Fault translateDataReadReq(MemReqPtr req) + { + return dummyTranslation(req); + } + Fault translateDataWriteReq(MemReqPtr req) + { + return dummyTranslation(req); + } + +#endif + + template + Fault read(MemReqPtr req, T& data) + { +#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM) + if (req->flags & LOCKED) { + MiscRegFile *cregs = &req->xc->regs.miscRegs; + cregs->lock_addr = req->paddr; + cregs->lock_flag = true; + } +#endif + return mem->read(req, data); + } + + template + Fault write(MemReqPtr req, T& data) + { +#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM) + + MiscRegFile *cregs; + + // If this is a store conditional, act appropriately + if (req->flags & LOCKED) { + cregs = &req->xc->regs.miscRegs; + + if (req->flags & UNCACHEABLE) { + // Don't update result register (see machine.def) + req->result = 2; + req->xc->storeCondFailures = 0;//Needed? [RGD] + } else { + req->result = cregs->lock_flag; + if (!cregs->lock_flag || + ((cregs->lock_addr & ~0xf) != (req->paddr & ~0xf))) { + cregs->lock_flag = false; + if (((++req->xc->storeCondFailures) % 100000) == 0) { + std::cerr << "Warning: " + << req->xc->storeCondFailures + << " consecutive store conditional failures " + << "on cpu " << req->xc->cpu_id + << std::endl; + } + return No_Fault; + } + else req->xc->storeCondFailures = 0; + } + } + + // Need to clear any locked flags on other proccessors for this + // address + // Only do this for succsful Store Conditionals and all other + // stores (WH64?) + // Unsuccesful Store Conditionals would have returned above, + // and wouldn't fall through + for(int i = 0; i < system->num_cpus; i++){ + cregs = &system->xc_array[i]->regs.miscRegs; + if((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) { + cregs->lock_flag = false; + } + } + +#endif + return mem->write(req, data); + } + + virtual bool misspeculating(); + + + // + // New accessors for new decoder. + // + uint64_t readIntReg(int reg_idx) + { + return regs.intRegFile[reg_idx]; + } + + float readFloatRegSingle(int reg_idx) + { + return (float)regs.floatRegFile.d[reg_idx]; + } + + double readFloatRegDouble(int reg_idx) + { + return regs.floatRegFile.d[reg_idx]; + } + + uint64_t readFloatRegInt(int reg_idx) + { + return regs.floatRegFile.q[reg_idx]; + } + + void setIntReg(int reg_idx, uint64_t val) + { + regs.intRegFile[reg_idx] = val; + } + + void setFloatRegSingle(int reg_idx, float val) + { + regs.floatRegFile.d[reg_idx] = (double)val; + } + + void setFloatRegDouble(int reg_idx, double val) + { + regs.floatRegFile.d[reg_idx] = val; + } + + void setFloatRegInt(int reg_idx, uint64_t val) + { + regs.floatRegFile.q[reg_idx] = val; + } + + uint64_t readPC() + { + return regs.pc; + } + + void setNextPC(uint64_t val) + { + regs.npc = val; + } + + uint64_t readUniq() + { + return regs.miscRegs.uniq; + } + + void setUniq(uint64_t val) + { + regs.miscRegs.uniq = val; + } + + uint64_t readFpcr() + { + return regs.miscRegs.fpcr; + } + + void setFpcr(uint64_t val) + { + regs.miscRegs.fpcr = val; + } + +#ifdef FULL_SYSTEM + uint64_t readIpr(int idx, Fault &fault); + Fault setIpr(int idx, uint64_t val); + Fault hwrei(); + void ev5_trap(Fault fault); + bool simPalCheck(int palFunc); +#endif + +#ifndef FULL_SYSTEM + void syscall() + { + process->syscall(this); + } +#endif +}; + + +// for non-speculative execution context, spec_mode is always false +inline bool +ExecContext::misspeculating() +{ + return false; +} + +#endif // __EXEC_CONTEXT_HH__ diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc new file mode 100644 index 000000000..4c5d14893 --- /dev/null +++ b/cpu/exetrace.cc @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "dyn_inst.hh" +#include "spec_state.hh" +#include "issue.hh" +#include "exetrace.hh" +#include "exec_context.hh" +#include "symtab.hh" +#include "base_cpu.hh" +#include "static_inst.hh" + +using namespace std; + + +//////////////////////////////////////////////////////////////////////// +// +// Methods for the InstRecord object +// + + +const SymbolTable *debugSymbolTable = NULL; + +void +Trace::InstRecord::dump(ostream &outs) +{ + if (flags[PRINT_CYCLE]) + ccprintf(outs, "%7d: ", cycle); + + outs << cpu->name() << " "; + + if (flags[TRACE_MISSPEC]) + outs << (misspeculating ? "-" : "+") << " "; + + if (flags[PRINT_THREAD_NUM]) + outs << "T" << thread << " : "; + + outs << "0x" << hex << PC << " : "; + + // + // Print decoded instruction + // + +#if defined(__GNUC__) && (__GNUC__ < 3) + // There's a bug in gcc 2.x library that prevents setw() + // from working properly on strings + string mc(staticInst->disassemble(PC, debugSymbolTable)); + while (mc.length() < 25) + mc += " "; + outs << mc; +#else + outs << setw(25) << staticInst->disassemble(PC, debugSymbolTable); +#endif + + outs << " : "; + + if (flags[PRINT_OP_CLASS]) { + outs << opClassStrings[staticInst->opClass()] << " : "; + } + + if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) { + outs << " D="; +#if 0 + if (data_status == DataDouble) + ccprintf(outs, "%f", data.as_double); + else + ccprintf(outs, "%#018x", data.as_int); +#else + ccprintf(outs, "%#018x", data.as_int); +#endif + } + + if (flags[PRINT_EFF_ADDR] && addr_valid) + outs << " A=0x" << hex << addr; + + if (flags[PRINT_INT_REGS] && regs_valid) { + for (int i = 0; i < 32;) + for (int j = i + 1; i <= j; i++) + ccprintf(outs, "r%02d = %#018x%s", i, iregs->regs[i], + ((i == j) ? "\n" : " ")); + outs << "\n"; + } + + if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid) + outs << " FetchSeq=" << dec << fetch_seq; + + if (flags[PRINT_CP_SEQ] && cp_seq_valid) + outs << " CPSeq=" << dec << cp_seq; + + // + // End of line... + // + outs << endl; + outs.flush(); +} + + +vector Trace::InstRecord::flags(NUM_BITS); + +//////////////////////////////////////////////////////////////////////// +// +// Parameter space for per-cycle execution address tracing options. +// Derive from ParamContext so we can override checkParams() function. +// +class ExecutionTraceParamContext : public ParamContext +{ + public: + ExecutionTraceParamContext(const string &_iniSection) + : ParamContext(_iniSection) + { + } + + void checkParams(); // defined at bottom of file +}; + +ExecutionTraceParamContext exeTraceParams("exetrace"); + +Param exe_trace_spec(&exeTraceParams, "speculative", + "capture speculative instructions", false); + +Param exe_trace_print_cycle(&exeTraceParams, "print_cycle", + "print cycle number", true); +Param exe_trace_print_opclass(&exeTraceParams, "print_opclass", + "print op class", true); +Param exe_trace_print_thread(&exeTraceParams, "print_thread", + "print thread number", true); +Param exe_trace_print_effaddr(&exeTraceParams, "print_effaddr", + "print effective address", true); +Param exe_trace_print_data(&exeTraceParams, "print_data", + "print result data", true); +Param exe_trace_print_iregs(&exeTraceParams, "print_iregs", + "print all integer regs", false); +Param exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq", + "print fetch sequence number", false); +Param exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq", + "print correct-path sequence number", false); + +// +// Helper function for ExecutionTraceParamContext::checkParams() just +// to get us into the InstRecord namespace +// +void +Trace::InstRecord::setParams() +{ + flags[TRACE_MISSPEC] = exe_trace_spec; + + flags[PRINT_CYCLE] = exe_trace_print_cycle; + flags[PRINT_OP_CLASS] = exe_trace_print_opclass; + flags[PRINT_THREAD_NUM] = exe_trace_print_thread; + flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr; + flags[PRINT_EFF_ADDR] = exe_trace_print_data; + flags[PRINT_INT_REGS] = exe_trace_print_iregs; + flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq; + flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq; +} + +void +ExecutionTraceParamContext::checkParams() +{ + Trace::InstRecord::setParams(); +} + diff --git a/cpu/exetrace.hh b/cpu/exetrace.hh new file mode 100644 index 000000000..2eb7753e5 --- /dev/null +++ b/cpu/exetrace.hh @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __EXETRACE_HH__ +#define __EXETRACE_HH__ + +#include +#include + +#include "host.hh" +#include "inst_seq.hh" // for InstSeqNum +#include "trace.hh" +#include "exec_context.hh" +#include "static_inst.hh" + +class BaseCPU; + + +namespace Trace { + +#if 0 + static const FlagVec ALL = ULL(0x1); + static const FlagVec FULL = ULL(0x2); + static const FlagVec SYMBOLS = ULL(0x4); + static const FlagVec EXTENDED = ULL(0x8); + static const FlagVec BRANCH_TAKEN = ULL(0x10); + static const FlagVec BRANCH_NOTTAKEN = ULL(0x20); + static const FlagVec CALLPAL = ULL(0x40); + static const FlagVec SPECULATIVE = ULL(0x100); + static const FlagVec OMIT_COUNT = ULL(0x200); + static const FlagVec INCLUDE_THREAD_NUM = ULL(0x400); +#endif + +class InstRecord : public Record +{ + protected: + + // The following fields are initialized by the constructor and + // thus guaranteed to be valid. + BaseCPU *cpu; + // need to make this ref-counted so it doesn't go away before we + // dump the record + StaticInstPtr staticInst; + Addr PC; + bool misspeculating; + unsigned thread; + + // The remaining fields are only valid for particular instruction + // types (e.g, addresses for memory ops) or when particular + // options are enabled (e.g., tracing full register contents). + // Each data field has an associated valid flag to indicate + // whether the data field is valid. + Addr addr; + bool addr_valid; + + union { + uint64_t as_int; + double as_double; + } data; + enum { + DataInvalid = 0, + DataInt8 = 1, // set to equal number of bytes + DataInt16 = 2, + DataInt32 = 4, + DataInt64 = 8, + DataDouble = 3 + } data_status; + + InstSeqNum fetch_seq; + bool fetch_seq_valid; + + InstSeqNum cp_seq; + bool cp_seq_valid; + + struct iRegFile { + IntRegFile regs; + }; + iRegFile *iregs; + bool regs_valid; + + public: + InstRecord(Tick _cycle, BaseCPU *_cpu, StaticInstPtr _staticInst, + Addr _pc, bool spec, unsigned _thread) + : Record(_cycle), cpu(_cpu), staticInst(_staticInst), PC(_pc), + misspeculating(spec), thread(_thread) + { + data_status = DataInvalid; + addr_valid = false; + regs_valid = false; + + fetch_seq_valid = false; + cp_seq_valid = false; + } + + virtual ~InstRecord() { } + + virtual void dump(std::ostream &outs); + + void setAddr(Addr a) { addr = a; addr_valid = true; } + + void setData(uint64_t d) { data.as_int = d; data_status = DataInt64; } + void setData(uint32_t d) { data.as_int = d; data_status = DataInt32; } + void setData(uint16_t d) { data.as_int = d; data_status = DataInt16; } + void setData(uint8_t d) { data.as_int = d; data_status = DataInt8; } + + void setData(int64_t d) { setData((uint64_t)d); } + void setData(int32_t d) { setData((uint32_t)d); } + void setData(int16_t d) { setData((uint16_t)d); } + void setData(int8_t d) { setData((uint8_t)d); } + + void setData(double d) { data.as_double = d; data_status = DataDouble; } + + void setFetchSeq(InstSeqNum seq) + { fetch_seq = seq; fetch_seq_valid = true; } + + void setCPSeq(InstSeqNum seq) + { cp_seq = seq; cp_seq_valid = true; } + + void setRegs(const IntRegFile ®s); + + void finalize() { theLog.append(this); } + + enum InstExecFlagBits { + TRACE_MISSPEC = 0, + PRINT_CYCLE, + PRINT_OP_CLASS, + PRINT_THREAD_NUM, + PRINT_RESULT_DATA, + PRINT_EFF_ADDR, + PRINT_INT_REGS, + PRINT_FETCH_SEQ, + PRINT_CP_SEQ, + NUM_BITS + }; + + static std::vector flags; + + static void setParams(); + + static bool traceMisspec() { return flags[TRACE_MISSPEC]; } +}; + + +inline void +InstRecord::setRegs(const IntRegFile ®s) +{ + if (!iregs) + iregs = new iRegFile; + + memcpy(&iregs->regs, regs, sizeof(IntRegFile)); + regs_valid = true; +} + +inline +InstRecord * +getInstRecord(Tick cycle, ExecContext *xc, BaseCPU *cpu, + const StaticInstPtr staticInst, + Addr pc, int thread = 0) +{ + if (DTRACE(InstExec) && + (InstRecord::traceMisspec() || !xc->misspeculating())) { + return new InstRecord(cycle, cpu, staticInst, pc, + xc->misspeculating(), thread); + } + + return NULL; +} + + +} + +#endif // __EXETRACE_HH__ diff --git a/cpu/full_cpu/op_class.hh b/cpu/full_cpu/op_class.hh new file mode 100644 index 000000000..67ccaabad --- /dev/null +++ b/cpu/full_cpu/op_class.hh @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __OP_CLASS_HH__ +#define __OP_CLASS_HH__ + +/** + * @file + * Definition of operation classes. + */ + +/** + * Instruction operation classes. These classes are used for + * assigning instructions to functional units. + */ +enum OpClass { + No_OpClass = 0, /* inst does not use a functional unit */ + IntALU, /* integer ALU */ + IntMULT, /* integer multiplier */ + IntDIV, /* integer divider */ + FloatADD, /* floating point adder/subtractor */ + FloatCMP, /* floating point comparator */ + FloatCVT, /* floating point<->integer converter */ + FloatMULT, /* floating point multiplier */ + FloatDIV, /* floating point divider */ + FloatSQRT, /* floating point square root */ + RdPort, /* memory read port */ + WrPort, /* memory write port */ + LvqPort, /* load value queue read port (redundant threading) */ + IPrefPort, + Num_OpClasses /* total functional unit classes */ +}; + +/** + * Array mapping OpClass enum values to strings. + */ +extern const char *opClassStrings[]; + +#endif // __OP_CLASS_HH__ diff --git a/cpu/full_cpu/smt.hh b/cpu/full_cpu/smt.hh new file mode 100644 index 000000000..f9c1e4614 --- /dev/null +++ b/cpu/full_cpu/smt.hh @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Defines SMT_MAX_CPUS and SMT_MAX_THREADS. + */ + +#ifndef __SMT_HH__ +#define __SMT_HH__ + +#ifndef SMT_MAX_CPUS +/** The maximum number of cpus in any one system. */ +#define SMT_MAX_CPUS 4 +#endif + +#ifndef SMT_MAX_THREADS +/** The number of TPUs in any processor. */ +#define SMT_MAX_THREADS 4 +#endif + +/** + * The maximum number of active threads across all cpus. Used to + * initialize per-thread statistics in the cache. + * + * NB: Be careful to only use it once all the CPUs that you care about + * have been initialized + */ +extern int maxThreadsPerCPU; + +/** + * Changes the status and priority of the thread with the given number. + * @param thread_number The thread to change. + * @param activate The new active status. + * @param priority The new priority. + */ +void change_thread_state(int thread_number, int activate, int priority); + +#endif // __SMT_HH__ diff --git a/cpu/inst_seq.hh b/cpu/inst_seq.hh new file mode 100644 index 000000000..9c3898ff7 --- /dev/null +++ b/cpu/inst_seq.hh @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __STD_TYPES_HH__ +#define __STD_TYPES_HH__ + +// inst sequence type, used to order instructions in the ready list, +// if this rolls over the ready list order temporarily will get messed +// up, but execution will continue and complete correctly +typedef unsigned long long InstSeqNum; + +// inst tag type, used to tag an operation instance in the IQ +typedef unsigned int InstTag; + +#endif // __STD_TYPES_HH__ diff --git a/cpu/intr_control.cc b/cpu/intr_control.cc new file mode 100644 index 000000000..7ad32a2b9 --- /dev/null +++ b/cpu/intr_control.cc @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "base_cpu.hh" +#include "intr_control.hh" +#include "sim_object.hh" + +using namespace std; + +IntrControl::IntrControl(const string &name, BaseCPU *c) + : SimObject(name), cpu(c) +{} + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(IntrControl) + + SimObjectParam cpu; + +END_DECLARE_SIM_OBJECT_PARAMS(IntrControl) + +BEGIN_INIT_SIM_OBJECT_PARAMS(IntrControl) + + INIT_PARAM(cpu, "the processor") + +END_INIT_SIM_OBJECT_PARAMS(IntrControl) + +CREATE_SIM_OBJECT(IntrControl) +{ + return new IntrControl(getInstanceName(), cpu); +} + +REGISTER_SIM_OBJECT("IntrControl", IntrControl) diff --git a/cpu/intr_control.hh b/cpu/intr_control.hh new file mode 100644 index 000000000..660d6d704 --- /dev/null +++ b/cpu/intr_control.hh @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __INTR_CONTROL_HH__ +#define __INTR_CONTROL_HH__ + +#include "misc.hh" +#include "base_cpu.hh" +#include "sim_object.hh" + +class IntrControl : public SimObject +{ + public: + BaseCPU *cpu; + IntrControl(const std::string &name, BaseCPU *c); + + void clear(int int_num, int index = 0); + void post(int int_num, int index = 0); +}; + +inline void +IntrControl::post(int int_num, int index) +{ cpu->post_interrupt(int_num, index); } + +inline void +IntrControl::clear(int int_num, int index) +{ cpu->clear_interrupt(int_num, index); } + +#endif // __INTR_CONTROL_HH__ + + + + + + + diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc new file mode 100644 index 000000000..70b6fbf13 --- /dev/null +++ b/cpu/memtest/memtest.cc @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded + +#include +#include +#include +#include + +#include "memtest.hh" +#include "misc.hh" +#include "sim_events.hh" +#include "main_memory.hh" +#include "base_cache.hh" + +#include "statistics.hh" +#include "sim_stats.hh" + +using namespace std; + +MemTest::MemTest(const string &name, + MemInterface *_cache_interface, + FunctionalMemory *main_mem, + FunctionalMemory *check_mem, + unsigned _memorySize, + unsigned _percentReads, + unsigned _percentUncacheable, + unsigned _maxReads, + unsigned _progressInterval, + Addr _traceAddr) + : BaseCPU(name, 1), + tickEvent(this), + cacheInterface(_cache_interface), + mainMem(main_mem), + checkMem(check_mem), + size(_memorySize), + percentReads(_percentReads), + percentUncacheable(_percentUncacheable), + maxReads(_maxReads), + progressInterval(_progressInterval), + nextProgressMessage(_progressInterval) +{ + vector cmd; + cmd.push_back("/bin/ls"); + vector null_vec; + xc = new ExecContext(this ,0,mainMem,0); + + blockSize = cacheInterface->getBlockSize(); + blockAddrMask = blockSize - 1; + traceBlockAddr = blockAddr(_traceAddr); + + //setup data storage with interesting values + uint8_t *data1 = new uint8_t[size]; + uint8_t *data2 = new uint8_t[size]; + uint8_t *data3 = new uint8_t[size]; + memset(data1, 1, size); + memset(data2, 2, size); + memset(data3, 3, size); + curTick = 0; + + baseAddr1 = 0x100000; + baseAddr2 = 0x400000; + uncacheAddr = 0x800000; + + // set up intial memory contents here + mainMem->prot_write(baseAddr1, data1, size); + checkMem->prot_write(baseAddr1, data1, size); + mainMem->prot_write(baseAddr2, data2, size); + checkMem->prot_write(baseAddr2, data2, size); + mainMem->prot_write(uncacheAddr, data3, size); + checkMem->prot_write(uncacheAddr, data3, size); + + delete [] data1; + delete [] data2; + delete [] data3; + + // set up counters + noResponseCycles = 0; + numReads = 0; + numWrites = 0; + tickEvent.schedule(0); +} + +static void +printData(ostream &os, uint8_t *data, int nbytes) +{ + os << hex << setfill('0'); + // assume little-endian: print bytes from highest address to lowest + for (uint8_t *dp = data + nbytes - 1; dp >= data; --dp) { + os << setw(2) << (unsigned)*dp; + } + os << dec; +} + +void +MemTest::completeRequest(MemReqPtr req, uint8_t *data) +{ + switch (req->cmd) { + case Read: + if (memcmp(req->data, data, req->size) != 0) { + cerr << name() << ": on read of 0x" << hex << req->paddr + << " @ cycle " << dec << curTick + << ", cache returns 0x"; + printData(cerr, req->data, req->size); + cerr << ", expected 0x"; + printData(cerr, data, req->size); + cerr << endl; + fatal(""); + } + + numReads++; + + if (numReads.val() == nextProgressMessage) { + cerr << name() << ": completed " << numReads.val() + << " read accesses @ " << curTick << endl; + nextProgressMessage += progressInterval; + } + + if (numReads.val() == maxReads) { + stringstream stream; + stream << name() << " reached max read count (" << maxReads + << ")" << endl; + + new SimExitEvent(stream.str()); + } + break; + + case Write: + numWrites++; + break; + + + default: + panic("invalid command"); + } + + if (blockAddr(req->paddr) == traceBlockAddr) { + cerr << name() << ": completed " + << (req->cmd.isWrite() ? "write" : "read") << " access of " + << req->size << " bytes at address 0x" + << hex << req->paddr << ", value = 0x"; + printData(cerr, req->data, req->size); + cerr << endl; + } + + noResponseCycles = 0; + delete [] data; +} + + +void +MemTest::regStats() +{ + using namespace Statistics; + + numReads + .name(name() + ".num_reads") + .desc("number of read accesses completed") + ; + + numWrites + .name(name() + ".num_writes") + .desc("number of write accesses completed") + ; + + numCopies + .name(name() + ".num_copies") + .desc("number of copy accesses completed") + ; +} + +void +MemTest::tick() +{ + if (!tickEvent.scheduled()) + tickEvent.schedule(curTick + 1); + + if (++noResponseCycles >= 5000) { + cerr << name() << ": deadlocked at cycle " << curTick << endl; + fatal(""); + } + + if (cacheInterface->isBlocked()) { + return; + } + + //make new request + unsigned cmd = rand() % 100; + unsigned offset1 = random() % size; + unsigned base = random() % 2; + uint64_t data = random(); + unsigned access_size = random() % 4; + unsigned cacheable = rand() % 100; + + MemReqPtr req = new MemReq(); + + if (cacheable < percentUncacheable) { + req->flags |= UNCACHEABLE; + req->paddr = uncacheAddr + offset1; + } else { + req->paddr = ((base) ? baseAddr1 : baseAddr2) + offset1; + } + + req->size = 1 << access_size; + req->data = new uint8_t[req->size]; + req->paddr &= ~(req->size - 1); + req->time = curTick; + req->xc = xc; + + if (cmd < percentReads) { + // read + req->cmd = Read; + uint8_t *result = new uint8_t[8]; + checkMem->access(Read, req->paddr, result, req->size); + if (blockAddr(req->paddr) == traceBlockAddr) { + cerr << name() << ": initiating read of " + << req->size << " bytes from addr 0x" + << hex << req->paddr << " at cycle " + << dec << curTick << endl; + } + + req->completionEvent = new MemCompleteEvent(req, result, this); + cacheInterface->access(req); + } else { + // write + req->cmd = Write; + memcpy(req->data, &data, req->size); + checkMem->access(Write, req->paddr, req->data, req->size); + if (blockAddr(req->paddr) == traceBlockAddr) { + cerr << name() << ": initiating write of " + << req->size << " bytes (value = 0x"; + printData(cerr, req->data, req->size); + cerr << ") to addr 0x" + << hex << req->paddr << " at cycle " + << dec << curTick << endl; + } + req->completionEvent = new MemCompleteEvent(req, NULL, this); + cacheInterface->access(req); + } +} + + +void +MemCompleteEvent::process() +{ + tester->completeRequest(req, data); + delete this; +} + + +const char * +MemCompleteEvent::description() +{ + return "memory access completion"; +} + + +BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest) + + SimObjectParam cache; + SimObjectParam main_mem; + SimObjectParam check_mem; + Param memory_size; + Param percent_reads; + Param percent_uncacheable; + Param max_reads; + Param progress_interval; + Param trace_addr; + +END_DECLARE_SIM_OBJECT_PARAMS(MemTest) + + +BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest) + + INIT_PARAM(cache, "L1 cache"), + INIT_PARAM(main_mem, "hierarchical memory"), + INIT_PARAM(check_mem, "check memory"), + INIT_PARAM_DFLT(memory_size, "memory size", 65536), + INIT_PARAM_DFLT(percent_reads, "target read percentage", 65), + INIT_PARAM_DFLT(percent_uncacheable, "target uncacheable percentage", 10), + INIT_PARAM_DFLT(max_reads, "number of reads to simulate", 0), + INIT_PARAM_DFLT(progress_interval, + "progress report interval (in accesses)", 1000000), + INIT_PARAM_DFLT(trace_addr, "address to trace", 0) + +END_INIT_SIM_OBJECT_PARAMS(MemTest) + + +CREATE_SIM_OBJECT(MemTest) +{ + return new MemTest(getInstanceName(), cache->getInterface(), main_mem, + check_mem, + memory_size, percent_reads, + percent_uncacheable, max_reads, progress_interval, + trace_addr); +} + +REGISTER_SIM_OBJECT("MemTest", MemTest) diff --git a/cpu/memtest/memtest.hh b/cpu/memtest/memtest.hh new file mode 100644 index 000000000..aa652abbd --- /dev/null +++ b/cpu/memtest/memtest.hh @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MEMTEST_HH__ +#define __MEMTEST_HH__ + +#include "sim_object.hh" +#include "mem_interface.hh" +#include "functional_memory.hh" +#include "base_cpu.hh" +#include "exec_context.hh" + +#include "statistics.hh" +#include "sim_stats.hh" + +class MemTest : public BaseCPU +{ + public: + + MemTest(const std::string &name, + MemInterface *_cache_interface, + FunctionalMemory *main_mem, + FunctionalMemory *check_mem, + unsigned _memorySize, + unsigned _percentReads, + unsigned _percentUncacheable, + unsigned _maxReads, + unsigned _progressInterval, + Addr _traceAddr); + + // register statistics + virtual void regStats(); + // main simulation loop (one cycle) + void tick(); + + protected: + class TickEvent : public Event + { + private: + MemTest *cpu; + public: + TickEvent(MemTest *c) + : Event(&mainEventQueue, 100), cpu(c) {} + void process() {cpu->tick();} + virtual const char *description() { return "tick event"; } + }; + + TickEvent tickEvent; + + MemInterface *cacheInterface; + FunctionalMemory *mainMem; + FunctionalMemory *checkMem; + ExecContext *xc; + + unsigned size; // size of testing memory region + + unsigned percentReads; // target percentage of read accesses + unsigned percentUncacheable; + + Tick maxReads; // max # of reads to perform (then quit) + + unsigned blockSize; + + Addr blockAddrMask; + + Addr blockAddr(Addr addr) + { + return (addr & ~blockAddrMask); + } + + Addr traceBlockAddr; + + Addr baseAddr1; // fix this to option + Addr baseAddr2; // fix this to option + Addr uncacheAddr; + + unsigned progressInterval; // frequency of progress reports + Tick nextProgressMessage; // access # for next progress report + + Tick noResponseCycles; + + Statistics::Scalar numReads; + Statistics::Scalar numWrites; + Statistics::Scalar numCopies; + + // called by MemCompleteEvent::process() + void completeRequest(MemReqPtr req, uint8_t *data); + + friend class MemCompleteEvent; +}; + + +class MemCompleteEvent : public Event +{ + MemReqPtr req; + uint8_t *data; + MemTest *tester; + + public: + + MemCompleteEvent(MemReqPtr _req, uint8_t *_data, MemTest *_tester) + : Event(&mainEventQueue), + req(_req), data(_data), tester(_tester) + { + } + + void process(); + + virtual const char *description(); +}; + +#endif // __MEMTEST_HH__ + + + diff --git a/cpu/pc_event.cc b/cpu/pc_event.cc new file mode 100644 index 000000000..4de425199 --- /dev/null +++ b/cpu/pc_event.cc @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "debug.hh" +#include "exec_context.hh" +#include "pc_event.hh" +#include "trace.hh" +#include "universe.hh" + +#ifdef FULL_SYSTEM +#include "arguments.hh" +#include "pmap.h" +#include "kernel.hh" +#include "memory_control.hh" +#include "cpu.hh" +#include "system.hh" +#include "bpred.hh" +#endif + +using namespace std; + +PCEventQueue::PCEventQueue() +{} + +PCEventQueue::~PCEventQueue() +{} + +bool +PCEventQueue::remove(PCEvent *event) +{ + int removed = 0; + range_t range = equal_range(event); + for (iterator i = range.first; i != range.second; ++i) { + if (*i == event) { + DPRINTF(PCEvent, "PC based event removed at %#x: %s\n", + event->pc(), event->descr()); + pc_map.erase(i); + ++removed; + } + } + + return removed > 0; +} + +bool +PCEventQueue::schedule(PCEvent *event) +{ + pc_map.push_back(event); + sort(pc_map.begin(), pc_map.end(), MapCompare()); + + DPRINTF(PCEvent, "PC based event scheduled for %#x: %s\n", + event->pc(), event->descr()); + + return true; +} + +bool +PCEventQueue::service(ExecContext *xc) +{ + Addr pc = xc->regs.pc; + int serviced = 0; + range_t range = equal_range(pc); + for (iterator i = range.first; i != range.second; ++i) { + // Make sure that the pc wasn't changed as the side effect of + // another event. This for example, prevents two invocations + // of the SkipFuncEvent. Maybe we should have separate PC + // event queues for each processor? + if (pc != xc->regs.pc) + continue; + + DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n", + (*i)->pc(), (*i)->descr()); + + (*i)->process(xc); + ++serviced; + } + + return serviced > 0; +} + +void +PCEventQueue::dump() const +{ + const_iterator i = pc_map.begin(); + const_iterator e = pc_map.end(); + + for (; i != e; ++i) + cprintf("%d: event at %#x: %s\n", curTick, (*i)->pc(), + (*i)->descr()); +} + +PCEventQueue::range_t +PCEventQueue::equal_range(Addr pc) +{ + return std::equal_range(pc_map.begin(), pc_map.end(), pc, MapCompare()); +} + +#ifdef FULL_SYSTEM +void +SkipFuncEvent::process(ExecContext *xc) +{ + Addr newpc = xc->regs.intRegFile[ReturnAddressReg]; + + DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description, + xc->regs.pc, newpc); + + xc->regs.pc = newpc; + xc->regs.npc = xc->regs.pc + sizeof(MachInst); + + BranchPred *bp = xc->cpu->getBranchPred(); + if (bp != NULL) { + bp->popRAS(xc->thread_num); + } +} + +void +BadAddrEvent::process(ExecContext *xc) +{ + // The following gross hack is the equivalent function to the + // annotation for vmunix::badaddr in: + // simos/simulation/apps/tcl/osf/tlaser.tcl + + uint64_t a0 = xc->regs.intRegFile[ArgumentReg0]; + + if (a0 < ALPHA_K0SEG_BASE || a0 >= ALPHA_K1SEG_BASE || + xc->memCtrl->badaddr(ALPHA_K0SEG_TO_PHYS(a0) & PA_IMPL_MASK)) { + + DPRINTF(BADADDR, "badaddr arg=%#x bad\n", a0); + xc->regs.intRegFile[ReturnValueReg] = 0x1; + SkipFuncEvent::process(xc); + } + else + DPRINTF(BADADDR, "badaddr arg=%#x good\n", a0); +} + +void +PrintfEvent::process(ExecContext *xc) +{ + if (DTRACE(Printf)) { + DebugOut() << curTick << ": " << xc->cpu->name() << ": "; + + AlphaArguments args(xc); + Kernel::Printf(args); + } +} + +void +DebugPrintfEvent::process(ExecContext *xc) +{ + if (DTRACE(DebugPrintf)) { + if (!raw) + DebugOut() << curTick << ": " << xc->cpu->name() << ": "; + + AlphaArguments args(xc); + Kernel::Printf(args); + } +} + +void +DumpMbufEvent::process(ExecContext *xc) +{ + if (DTRACE(DebugPrintf)) { + AlphaArguments args(xc); + Kernel::DumpMbuf(args); + } +} +#endif + +BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, bool del) + : PCEvent(q, desc), remove(del) +{ +} + +void +BreakPCEvent::process(ExecContext *xc) +{ + debug_break(); + if (remove) + delete this; +} + +#ifdef FULL_SYSTEM +extern "C" +void +sched_break_pc_sys(System *sys, Addr addr) +{ + PCEvent *event = new BreakPCEvent(&sys->pcEventQueue, "debug break", true); + event->schedule(addr); +} + +extern "C" +void +sched_break_pc(Addr addr) +{ + for (vector::iterator sysi = System::systemList.begin(); + sysi != System::systemList.end(); ++sysi) { + sched_break_pc_sys(*sysi, addr); + } + +} +#endif diff --git a/cpu/pc_event.hh b/cpu/pc_event.hh new file mode 100644 index 000000000..24442f5f4 --- /dev/null +++ b/cpu/pc_event.hh @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __PC_EVENT_HH__ +#define __PC_EVENT_HH__ + +#include + +#include "mem_req.hh" + +class ExecContext; +class PCEventQueue; + +class PCEvent +{ + protected: + static const Addr badpc = MemReq::inval_addr; + + protected: + std::string description; + PCEventQueue *queue; + Addr evpc; + + public: + PCEvent() : queue(0), evpc(badpc) { } + + PCEvent(const std::string &desc) + : description(desc), queue(0), evpc(badpc) { } + + PCEvent(PCEventQueue *q, Addr pc = badpc) : queue(q), evpc(pc) { } + + PCEvent(PCEventQueue *q, const std::string &desc, Addr pc = badpc) + : description(desc), queue(q), evpc(pc) { } + + virtual ~PCEvent() { if (queue) remove(); } + + std::string descr() const { return description; } + Addr pc() const { return evpc; } + + bool remove(); + bool schedule(); + bool schedule(Addr pc); + bool schedule(PCEventQueue *q, Addr pc); + virtual void process(ExecContext *xc) = 0; +}; + +class PCEventQueue +{ + protected: + typedef PCEvent * record_t; + class MapCompare { + public: + bool operator()(const record_t &l, const record_t &r) const { + return l->pc() < r->pc(); + } + bool operator()(const record_t &l, Addr pc) const { + return l->pc() < pc; + } + bool operator()(Addr pc, const record_t &r) const { + return pc < r->pc(); + } + }; + typedef std::vector map_t; + + public: + typedef map_t::iterator iterator; + typedef map_t::const_iterator const_iterator; + + protected: + typedef std::pair range_t; + typedef std::pair const_range_t; + + protected: + map_t pc_map; + + public: + PCEventQueue(); + ~PCEventQueue(); + + bool remove(PCEvent *event); + bool schedule(PCEvent *event); + bool service(ExecContext *xc); + + range_t equal_range(Addr pc); + range_t equal_range(PCEvent *event) { return equal_range(event->pc()); } + + void dump() const; +}; + +inline bool +PCEvent::remove() +{ + if (!queue) + panic("cannot remove an uninitialized event;"); + + return queue->remove(this); +} + +inline bool +PCEvent::schedule() +{ + if (!queue || evpc == badpc) + panic("cannot schedule an uninitialized event;"); + + return queue->schedule(this); +} + +inline bool +PCEvent::schedule(Addr pc) +{ + if (evpc != badpc) + panic("cannot switch PC"); + evpc = pc; + + return schedule(); +} + +inline bool +PCEvent::schedule(PCEventQueue *q, Addr pc) +{ + if (queue) + panic("cannot switch event queues"); + + if (evpc != badpc) + panic("cannot switch addresses"); + + queue = q; + evpc = pc; + + return schedule(); +} + + +#ifdef FULL_SYSTEM +class SkipFuncEvent : public PCEvent +{ + public: + SkipFuncEvent(PCEventQueue *q, const std::string &desc) + : PCEvent(q, desc) {} + virtual void process(ExecContext *xc); +}; + +class BadAddrEvent : public SkipFuncEvent +{ + public: + BadAddrEvent(PCEventQueue *q, const std::string &desc) + : SkipFuncEvent(q, desc) {} + virtual void process(ExecContext *xc); +}; + +class PrintfEvent : public PCEvent +{ + public: + PrintfEvent(PCEventQueue *q, const std::string &desc) + : PCEvent(q, desc) {} + virtual void process(ExecContext *xc); +}; + +class DebugPrintfEvent : public PCEvent +{ + private: + bool raw; + + public: + DebugPrintfEvent(PCEventQueue *q, const std::string &desc, bool r = false) + : PCEvent(q, desc), raw(r) {} + virtual void process(ExecContext *xc); +}; + +class DumpMbufEvent : public PCEvent +{ + public: + DumpMbufEvent(PCEventQueue *q, const std::string &desc) + : PCEvent(q, desc) {} + virtual void process(ExecContext *xc); +}; +#endif + +class BreakPCEvent : public PCEvent +{ + protected: + bool remove; + + public: + BreakPCEvent(PCEventQueue *q, const std::string &desc, bool del = false); + virtual void process(ExecContext *xc); +}; + + +#endif // __PC_EVENT_HH__ diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc new file mode 100644 index 000000000..41a612318 --- /dev/null +++ b/cpu/simple_cpu/simple_cpu.cc @@ -0,0 +1,746 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "host.hh" +#include "cprintf.hh" +#include "misc.hh" +#include "smt.hh" + +#include "annotation.hh" +#include "exec_context.hh" +#include "base_cpu.hh" +#include "debug.hh" +#include "simple_cpu.hh" +#include "inifile.hh" +#include "mem_interface.hh" +#include "base_mem.hh" +#include "static_inst.hh" + +#ifdef FULL_SYSTEM +#include "memory_control.hh" +#include "physical_memory.hh" +#include "alpha_memory.hh" +#include "system.hh" +#else // !FULL_SYSTEM +#include "functional_memory.hh" +#include "prog.hh" +#include "eio.hh" +#endif // FULL_SYSTEM + +#include "exetrace.hh" +#include "trace.hh" +#include "sim_events.hh" +#include "pollevent.hh" +#include "sim_object.hh" +#include "sim_stats.hh" + +#include "range.hh" +#include "symtab.hh" + +#ifdef FULL_SYSTEM +#include "vtophys.hh" +#include "pciareg.h" +#include "remote_gdb.hh" +#include "alpha_access.h" +#endif + + +using namespace std; + +SimpleCPU::CacheCompletionEvent::CacheCompletionEvent(SimpleCPU *_cpu) + : Event(&mainEventQueue), + cpu(_cpu) +{ +} + +void SimpleCPU::CacheCompletionEvent::process() +{ + cpu->processCacheCompletion(); +} + +const char * +SimpleCPU::CacheCompletionEvent::description() +{ + return "cache completion event"; +} + +#ifdef FULL_SYSTEM +SimpleCPU::SimpleCPU(const string &_name, + System *_system, + Counter max_insts_any_thread, + Counter max_insts_all_threads, + AlphaItb *itb, AlphaDtb *dtb, + FunctionalMemory *mem, + MemInterface *icache_interface, + MemInterface *dcache_interface, + int cpu_id, Tick freq) + : BaseCPU(_name, /* number_of_threads */ 1, + max_insts_any_thread, max_insts_all_threads, + _system, cpu_id, freq), +#else +SimpleCPU::SimpleCPU(const string &_name, Process *_process, + Counter max_insts_any_thread, + Counter max_insts_all_threads, + MemInterface *icache_interface, + MemInterface *dcache_interface) + : BaseCPU(_name, /* number_of_threads */ 1, + max_insts_any_thread, max_insts_all_threads), +#endif + tickEvent(this), xc(NULL), cacheCompletionEvent(this) +{ +#ifdef FULL_SYSTEM + xc = new ExecContext(this, 0, system, itb, dtb, mem, cpu_id); + + _status = Running; + if (cpu_id != 0) { + + xc->setStatus(ExecContext::Unallocated); + + //Open a GDB debug session on port (7000 + the cpu_id) + (new GDBListener(new RemoteGDB(system, xc), 7000 + cpu_id))->listen(); + + AlphaISA::init(system->physmem, &xc->regs); + + fault = Reset_Fault; + + IntReg *ipr = xc->regs.ipr; + ipr[TheISA::IPR_MCSR] = 0x6; + + AlphaISA::swap_palshadow(&xc->regs, true); + + xc->regs.pc = + ipr[TheISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault]; + xc->regs.npc = xc->regs.pc + sizeof(MachInst); + + _status = Idle; + } + else { + system->initBootContext(xc); + + // Reset the system + // + AlphaISA::init(system->physmem, &xc->regs); + + fault = Reset_Fault; + + IntReg *ipr = xc->regs.ipr; + ipr[TheISA::IPR_MCSR] = 0x6; + + AlphaISA::swap_palshadow(&xc->regs, true); + + xc->regs.pc = ipr[TheISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault]; + xc->regs.npc = xc->regs.pc + sizeof(MachInst); + + _status = Running; + tickEvent.schedule(0); + } + +#else + xc = new ExecContext(this, /* thread_num */ 0, _process, /* asid */ 0); + fault = No_Fault; + if (xc->status() == ExecContext::Active) { + _status = Running; + tickEvent.schedule(0); + } else + _status = Idle; +#endif // !FULL_SYSTEM + + icacheInterface = icache_interface; + dcacheInterface = dcache_interface; + + memReq = new MemReq(); + memReq->xc = xc; + memReq->asid = 0; + + numInst = 0; + last_idle = 0; + lastIcacheStall = 0; + lastDcacheStall = 0; + + contexts.push_back(xc); +} + +SimpleCPU::~SimpleCPU() +{ +} + +void +SimpleCPU::regStats() +{ + BaseCPU::regStats(); + + numInsts + .name(name() + ".num_insts") + .desc("Number of instructions executed") + ; + + numMemRefs + .name(name() + ".num_refs") + .desc("Number of memory references") + ; + + idleCycles + .name(name() + ".idle_cycles") + .desc("Number of idle cycles") + ; + + idleFraction + .name(name() + ".idle_fraction") + .desc("Percentage of idle cycles") + ; + + icacheStallCycles + .name(name() + ".icache_stall_cycles") + .desc("ICache total stall cycles") + .prereq(icacheStallCycles) + ; + + dcacheStallCycles + .name(name() + ".dcache_stall_cycles") + .desc("DCache total stall cycles") + .prereq(dcacheStallCycles) + ; + + idleFraction = idleCycles / simTicks; + + numInsts = Statistics::scalar(numInst); + simInsts += numInsts; +} + +void +SimpleCPU::serialize() +{ + nameOut(); + +#ifdef FULL_SYSTEM +#if 0 + // do we need this anymore?? egh + childOut("itb", xc->itb); + childOut("dtb", xc->dtb); + childOut("physmem", physmem); +#endif +#endif + + for (int i = 0; i < NumIntRegs; i++) { + stringstream buf; + ccprintf(buf, "R%02d", i); + paramOut(buf.str(), xc->regs.intRegFile[i]); + } + for (int i = 0; i < NumFloatRegs; i++) { + stringstream buf; + ccprintf(buf, "F%02d", i); + paramOut(buf.str(), xc->regs.floatRegFile.d[i]); + } + // CPUTraitsType::serializeSpecialRegs(getProxy(), xc->regs); +} + +void +SimpleCPU::unserialize(IniFile &db, const string &category, ConfigNode *node) +{ + string data; + + for (int i = 0; i < NumIntRegs; i++) { + stringstream buf; + ccprintf(buf, "R%02d", i); + db.findDefault(category, buf.str(), data); + to_number(data,xc->regs.intRegFile[i]); + } + for (int i = 0; i < NumFloatRegs; i++) { + stringstream buf; + ccprintf(buf, "F%02d", i); + db.findDefault(category, buf.str(), data); + xc->regs.floatRegFile.d[i] = strtod(data.c_str(),NULL); + } + + // Read in Special registers + + // CPUTraitsType::unserializeSpecialRegs(db,category,node,xc->regs); +} + +void +change_thread_state(int thread_number, int activate, int priority) +{ +} + +// precise architected memory state accessor macros +template +Fault +SimpleCPU::read(Addr addr, T& data, unsigned flags) +{ + memReq->reset(addr, sizeof(T), flags); + + // translate to physical address + Fault fault = xc->translateDataReadReq(memReq); + + // do functional access + if (fault == No_Fault) + fault = xc->read(memReq, data); + + if (traceData) { + traceData->setAddr(addr); + if (fault == No_Fault) + traceData->setData(data); + } + + // if we have a cache, do cache access too + if (fault == No_Fault && dcacheInterface) { + memReq->cmd = Read; + memReq->completionEvent = NULL; + memReq->time = curTick; + memReq->flags &= ~UNCACHEABLE; + MemAccessResult result = dcacheInterface->access(memReq); + + // Ugly hack to get an event scheduled *only* if the access is + // a miss. We really should add first-class support for this + // at some point. + if (result != MA_HIT && dcacheInterface->doEvents) { + memReq->completionEvent = &cacheCompletionEvent; + setStatus(DcacheMissStall); + } + } + + return fault; +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +template +Fault +SimpleCPU::read(Addr addr, uint64_t& data, unsigned flags); + +template +Fault +SimpleCPU::read(Addr addr, uint32_t& data, unsigned flags); + +template +Fault +SimpleCPU::read(Addr addr, uint16_t& data, unsigned flags); + +template +Fault +SimpleCPU::read(Addr addr, uint8_t& data, unsigned flags); + +#endif //DOXYGEN_SHOULD_SKIP_THIS + +template<> +Fault +SimpleCPU::read(Addr addr, double& data, unsigned flags) +{ + return read(addr, *(uint64_t*)&data, flags); +} + +template<> +Fault +SimpleCPU::read(Addr addr, float& data, unsigned flags) +{ + return read(addr, *(uint32_t*)&data, flags); +} + + +template<> +Fault +SimpleCPU::read(Addr addr, int32_t& data, unsigned flags) +{ + return read(addr, (uint32_t&)data, flags); +} + + +template +Fault +SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) +{ + if (traceData) { + traceData->setAddr(addr); + traceData->setData(data); + } + + memReq->reset(addr, sizeof(T), flags); + + // translate to physical address + Fault fault = xc->translateDataWriteReq(memReq); + + // do functional access + if (fault == No_Fault) + fault = xc->write(memReq, data); + + if (fault == No_Fault && dcacheInterface) { + memReq->cmd = Write; + memReq->data = (uint8_t *)&data; + memReq->completionEvent = NULL; + memReq->time = curTick; + memReq->flags &= ~UNCACHEABLE; + MemAccessResult result = dcacheInterface->access(memReq); + + // Ugly hack to get an event scheduled *only* if the access is + // a miss. We really should add first-class support for this + // at some point. + if (result != MA_HIT && dcacheInterface->doEvents) { + memReq->completionEvent = &cacheCompletionEvent; + setStatus(DcacheMissStall); + } + } + + if (res && (fault == No_Fault)) + *res = memReq->result; + + return fault; +} + + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template +Fault +SimpleCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); + +template +Fault +SimpleCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); + +template +Fault +SimpleCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); + +template +Fault +SimpleCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); + +#endif //DOXYGEN_SHOULD_SKIP_THIS + +template<> +Fault +SimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) +{ + return write(*(uint64_t*)&data, addr, flags, res); +} + +template<> +Fault +SimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) +{ + return write(*(uint32_t*)&data, addr, flags, res); +} + + +template<> +Fault +SimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) +{ + return write((uint32_t)data, addr, flags, res); +} + + +#ifdef FULL_SYSTEM +Addr +SimpleCPU::dbg_vtophys(Addr addr) +{ + return vtophys(xc, addr); +} +#endif // FULL_SYSTEM + +Tick save_cycle = 0; + + +void +SimpleCPU::processCacheCompletion() +{ + switch (status()) { + case IcacheMissStall: + icacheStallCycles += curTick - lastIcacheStall; + setStatus(IcacheMissComplete); + break; + case DcacheMissStall: + dcacheStallCycles += curTick - lastDcacheStall; + setStatus(Running); + break; + default: + panic("SimpleCPU::processCacheCompletion: bad state"); + break; + } +} + +#ifdef FULL_SYSTEM +void +SimpleCPU::post_interrupt(int int_num, int index) +{ + BaseCPU::post_interrupt(int_num, index); + + if (xc->status() == ExecContext::Suspended) { + DPRINTF(IPI,"Suspended Processor awoke\n"); + xc->setStatus(ExecContext::Active); + Annotate::Resume(xc); + } +} +#endif // FULL_SYSTEM + +/* start simulation, program loaded, processor precise state initialized */ +void +SimpleCPU::tick() +{ + traceData = NULL; + +#ifdef FULL_SYSTEM + if (fault == No_Fault && AlphaISA::check_interrupts && + xc->cpu->check_interrupts() && + !PC_PAL(xc->regs.pc) && + status() != IcacheMissComplete) { + int ipl = 0; + int summary = 0; + AlphaISA::check_interrupts = 0; + IntReg *ipr = xc->regs.ipr; + + if (xc->regs.ipr[TheISA::IPR_SIRR]) { + for (int i = TheISA::INTLEVEL_SOFTWARE_MIN; + i < TheISA::INTLEVEL_SOFTWARE_MAX; i++) { + if (ipr[TheISA::IPR_SIRR] & (ULL(1) << i)) { + // See table 4-19 of 21164 hardware reference + ipl = (i - TheISA::INTLEVEL_SOFTWARE_MIN) + 1; + summary |= (ULL(1) << i); + } + } + } + + uint64_t interrupts = xc->cpu->intr_status(); + for(int i = TheISA::INTLEVEL_EXTERNAL_MIN; + i < TheISA::INTLEVEL_EXTERNAL_MAX; i++) { + if (interrupts & (ULL(1) << i)) { + // See table 4-19 of 21164 hardware reference + ipl = i; + summary |= (ULL(1) << i); + } + } + + if (ipr[TheISA::IPR_ASTRR]) + panic("asynchronous traps not implemented\n"); + + if (ipl && ipl > xc->regs.ipr[TheISA::IPR_IPLR]) { + ipr[TheISA::IPR_ISR] = summary; + ipr[TheISA::IPR_INTID] = ipl; + xc->ev5_trap(Interrupt_Fault); + + DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", + ipr[TheISA::IPR_IPLR], ipl, summary); + } + } +#endif + + // maintain $r0 semantics + xc->regs.intRegFile[ZeroReg] = 0; +#ifdef TARGET_ALPHA + xc->regs.floatRegFile.d[ZeroReg] = 0.0; +#endif // TARGET_ALPHA + + if (status() == IcacheMissComplete) { + // We've already fetched an instruction and were stalled on an + // I-cache miss. No need to fetch it again. + + setStatus(Running); + } + else { + // Try to fetch an instruction + + // set up memory request for instruction fetch +#ifdef FULL_SYSTEM +#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 +#else +#define IFETCH_FLAGS(pc) 0 +#endif + + memReq->cmd = Read; + memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t), + IFETCH_FLAGS(xc->regs.pc)); + + fault = xc->translateInstReq(memReq); + + if (fault == No_Fault) + fault = xc->mem->read(memReq, inst); + + if (icacheInterface && fault == No_Fault) { + memReq->completionEvent = NULL; + + memReq->time = curTick; + memReq->flags &= ~UNCACHEABLE; + MemAccessResult result = icacheInterface->access(memReq); + + // Ugly hack to get an event scheduled *only* if the access is + // a miss. We really should add first-class support for this + // at some point. + if (result != MA_HIT && icacheInterface->doEvents) { + memReq->completionEvent = &cacheCompletionEvent; + setStatus(IcacheMissStall); + return; + } + } + } + + // If we've got a valid instruction (i.e., no fault on instruction + // fetch), then execute it. + if (fault == No_Fault) { + + // keep an instruction count + numInst++; + + // check for instruction-count-based events + comInsnEventQueue[0]->serviceEvents(numInst); + + // decode the instruction + StaticInstPtr si(inst); + + traceData = Trace::getInstRecord(curTick, xc, this, si, + xc->regs.pc); + +#ifdef FULL_SYSTEM + xc->regs.opcode = (inst >> 26) & 0x3f; + xc->regs.ra = (inst >> 21) & 0x1f; +#endif // FULL_SYSTEM + + xc->func_exe_insn++; + + fault = si->execute(this, xc, traceData); + + if (si->isMemRef()) { + numMemRefs++; + } + + if (traceData) + traceData->finalize(); + + } // if (fault == No_Fault) + + if (fault != No_Fault) { +#ifdef FULL_SYSTEM + xc->ev5_trap(fault); +#else // !FULL_SYSTEM + fatal("fault (%d) detected @ PC 0x%08p", fault, xc->regs.pc); +#endif // FULL_SYSTEM + } + else { + // go to the next instruction + xc->regs.pc = xc->regs.npc; + xc->regs.npc += sizeof(MachInst); + } + +#ifdef FULL_SYSTEM + Addr oldpc; + do { + oldpc = xc->regs.pc; + system->pcEventQueue.service(xc); + } while (oldpc != xc->regs.pc); +#endif + + assert(status() == Running || + status() == Idle || + status() == DcacheMissStall); + + if (status() == Running && !tickEvent.scheduled()) + tickEvent.schedule(curTick + 1); +} + + +//////////////////////////////////////////////////////////////////////// +// +// SimpleCPU Simulation Object +// +BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) + + Param max_insts_any_thread; + Param max_insts_all_threads; + +#ifdef FULL_SYSTEM + SimObjectParam itb; + SimObjectParam dtb; + SimObjectParam mem; + SimObjectParam system; + Param cpu_id; + Param mult; +#else + SimObjectParam workload; +#endif // FULL_SYSTEM + + SimObjectParam icache; + SimObjectParam dcache; + +END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) + +BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU) + + INIT_PARAM_DFLT(max_insts_any_thread, + "terminate when any thread reaches this insn count", + 0), + INIT_PARAM_DFLT(max_insts_all_threads, + "terminate when all threads have reached this insn count", + 0), + +#ifdef FULL_SYSTEM + INIT_PARAM(itb, "Instruction TLB"), + INIT_PARAM(dtb, "Data TLB"), + INIT_PARAM(mem, "memory"), + INIT_PARAM(system, "system object"), + INIT_PARAM_DFLT(cpu_id, "CPU identification number", 0), + INIT_PARAM_DFLT(mult, "system clock multiplier", 1), +#else + INIT_PARAM(workload, "processes to run"), +#endif // FULL_SYSTEM + + INIT_PARAM_DFLT(icache, "L1 instruction cache object", NULL), + INIT_PARAM_DFLT(dcache, "L1 data cache object", NULL) + +END_INIT_SIM_OBJECT_PARAMS(SimpleCPU) + + +CREATE_SIM_OBJECT(SimpleCPU) +{ +#ifdef FULL_SYSTEM + if (mult != 1) + panic("processor clock multiplier must be 1\n"); + + return new SimpleCPU(getInstanceName(), system, + max_insts_any_thread, max_insts_all_threads, + itb, dtb, mem, + (icache) ? icache->getInterface() : NULL, + (dcache) ? dcache->getInterface() : NULL, + cpu_id, ticksPerSecond * mult); +#else + + return new SimpleCPU(getInstanceName(), workload, + max_insts_any_thread, max_insts_all_threads, + icache->getInterface(), dcache->getInterface()); + +#endif // FULL_SYSTEM +} + +REGISTER_SIM_OBJECT("SimpleCPU", SimpleCPU) diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh new file mode 100644 index 000000000..c5671eb6f --- /dev/null +++ b/cpu/simple_cpu/simple_cpu.hh @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SIMPLE_CPU_HH__ +#define __SIMPLE_CPU_HH__ + +#include "base_cpu.hh" +#include "eventq.hh" +#include "symtab.hh" +#include "pc_event.hh" +#include "statistics.hh" + + +// forward declarations +#ifdef FULL_SYSTEM +class Processor; +class Kernel; +class AlphaItb; +class AlphaDtb; +class PhysicalMemory; + +class RemoteGDB; +class GDBListener; +#endif // FULL_SYSTEM + +class MemInterface; +class IniFile; + +namespace Trace { + class InstRecord; +} + +class SimpleCPU : public BaseCPU +{ + public: + // main simulation loop (one cycle) + void tick(); + + private: + class TickEvent : public Event + { + private: + SimpleCPU *cpu; + + public: + TickEvent(SimpleCPU *c) + : Event(&mainEventQueue, 100), cpu(c) { } + void process() { cpu->tick(); } + virtual const char *description() { return "tick event"; } + }; + + TickEvent tickEvent; + + private: + Trace::InstRecord *traceData; + template + void trace_data(T data) { + if (traceData) { + traceData->setData(data); + } + }; + + public: + // + enum Status { + Running, + Idle, + IcacheMissStall, + IcacheMissComplete, + DcacheMissStall + }; + + private: + Status _status; + + public: + void post_interrupt(int int_num, int index); + + void zero_fill_64(Addr addr) { + static int warned = 0; + if (!warned) { + warn ("WH64 is not implemented"); + warned = 1; + } + }; + +#ifdef FULL_SYSTEM + + SimpleCPU(const std::string &_name, + System *_system, + Counter max_insts_any_thread, Counter max_insts_all_threads, + AlphaItb *itb, AlphaDtb *dtb, FunctionalMemory *mem, + MemInterface *icache_interface, MemInterface *dcache_interface, + int cpu_id, Tick freq); + +#else + + SimpleCPU(const std::string &_name, Process *_process, + Counter max_insts_any_thread, + Counter max_insts_all_threads, + MemInterface *icache_interface, MemInterface *dcache_interface); + +#endif + + virtual ~SimpleCPU(); + + // execution context + ExecContext *xc; + +#ifdef FULL_SYSTEM + Addr dbg_vtophys(Addr addr); + + bool interval_stats; +#endif + + // L1 instruction cache + MemInterface *icacheInterface; + + // L1 data cache + MemInterface *dcacheInterface; + + // current instruction + MachInst inst; + + // current fault status + Fault fault; + + // Refcounted pointer to the one memory request. + MemReqPtr memReq; + + class CacheCompletionEvent : public Event + { + private: + SimpleCPU *cpu; + + public: + CacheCompletionEvent(SimpleCPU *_cpu); + + virtual void process(); + virtual const char *description(); + }; + + CacheCompletionEvent cacheCompletionEvent; + + Status status() const { return _status; } + virtual void execCtxStatusChg() { + if (xc) { + if (xc->status() == ExecContext::Active) + setStatus(Running); + else + setStatus(Idle); + } + } + + void setStatus(Status new_status) { + Status old_status = status(); + _status = new_status; + + switch (status()) { + case IcacheMissStall: + assert(old_status == Running); + lastIcacheStall = curTick; + if (tickEvent.scheduled()) + tickEvent.squash(); + break; + + case IcacheMissComplete: + assert(old_status == IcacheMissStall); + if (tickEvent.squashed()) + tickEvent.reschedule(curTick + 1); + else if (!tickEvent.scheduled()) + tickEvent.schedule(curTick + 1); + break; + + case DcacheMissStall: + assert(old_status == Running); + lastDcacheStall = curTick; + if (tickEvent.scheduled()) + tickEvent.squash(); + break; + + case Idle: + assert(old_status == Running); + last_idle = curTick; + if (tickEvent.scheduled()) + tickEvent.squash(); + break; + + case Running: + assert(old_status == Idle || + old_status == DcacheMissStall || + old_status == IcacheMissComplete); + if (old_status == Idle) + idleCycles += curTick - last_idle; + + if (tickEvent.squashed()) + tickEvent.reschedule(curTick + 1); + else if (!tickEvent.scheduled()) + tickEvent.schedule(curTick + 1); + break; + + default: + panic("can't get here"); + } + } + + // statistics + void regStats(); + + // number of simulated instructions + Counter numInst; + Statistics::Formula numInsts; + + // number of simulated memory references + Statistics::Scalar<> numMemRefs; + + // number of idle cycles + Statistics::Scalar<> idleCycles; + Statistics::Formula idleFraction; + Counter last_idle; + + // number of cycles stalled for I-cache misses + Statistics::Scalar<> icacheStallCycles; + Counter lastIcacheStall; + + // number of cycles stalled for D-cache misses + Statistics::Scalar<> dcacheStallCycles; + Counter lastDcacheStall; + + void processCacheCompletion(); + + virtual void serialize(); + virtual void unserialize(IniFile &db, const std::string &category, + ConfigNode *node); + + template + Fault read(Addr addr, T& data, unsigned flags); + + template + Fault write(T data, Addr addr, unsigned flags, + uint64_t *res); + + Fault prefetch(Addr addr, unsigned flags) + { + // need to do this... + return No_Fault; + } + + void writeHint(Addr addr, int size) + { + // need to do this... + } +}; + +#endif // __SIMPLE_CPU_HH__ diff --git a/cpu/static_inst.cc b/cpu/static_inst.cc new file mode 100644 index 000000000..cf25d5f05 --- /dev/null +++ b/cpu/static_inst.cc @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "static_inst.hh" +#include "universe.hh" + +template +StaticInstPtr StaticInst::nullStaticInstPtr; + +template +typename StaticInst::DecodeCache StaticInst::decodeCache; + +// Define the decode cache hash map. +template StaticInst::DecodeCache +StaticInst::decodeCache; + +template +void +StaticInst::dumpDecodeCacheStats() +{ + using namespace std; + + cerr << "Decode hash table stats @ " << curTick << ":" << endl; + cerr << "\tnum entries = " << decodeCache.size() << endl; + cerr << "\tnum buckets = " << decodeCache.bucket_count() << endl; + vector hist(100, 0); + int max_hist = 0; + for (int i = 0; i < decodeCache.bucket_count(); ++i) { + int count = decodeCache.elems_in_bucket(i); + if (count > max_hist) + max_hist = count; + hist[count]++; + } + for (int i = 0; i <= max_hist; ++i) { + cerr << "\tbuckets of size " << i << " = " << hist[i] << endl; + } +} + + +template StaticInstPtr +StaticInst::nullStaticInstPtr; + +template +bool +StaticInst::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) +{ + if (isDirectCtrl()) { + tgt = branchTarget(pc); + return true; + } + + if (isIndirectCtrl()) { + tgt = branchTarget(xc); + return true; + } + + return false; +} + + +// force instantiation of template function(s) above +template StaticInst; diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh new file mode 100644 index 000000000..b8f9cc00a --- /dev/null +++ b/cpu/static_inst.hh @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __STATIC_INST_HH__ +#define __STATIC_INST_HH__ + +#include +#include + +#include "host.hh" +#include "hashmap.hh" +#include "refcnt.hh" + +#include "op_class.hh" +#include "isa_traits.hh" + +// forward declarations +class ExecContext; +class SpecExecContext; +class SimpleCPU; +class CPU; +class DynInst; +class SymbolTable; + +namespace Trace { + class InstRecord; +} + +/** + * Base, ISA-independent static instruction class. + * + * The main component of this class is the vector of flags and the + * associated methods for reading them. Any object that can rely + * solely on these flags can process instructions without being + * recompiled for multiple ISAs. + */ +class StaticInstBase : public RefCounted +{ + protected: + + /// Set of boolean static instruction properties. + /// + /// Notes: + /// - The IsInteger and IsFloating flags are based on the class of + /// registers accessed by the instruction. Although most + /// instructions will have exactly one of these two flags set, it + /// is possible for an instruction to have neither (e.g., direct + /// unconditional branches, memory barriers) or both (e.g., an + /// FP/int conversion). + /// - If IsMemRef is set, then exactly one of IsLoad or IsStore + /// will be set. Prefetches are marked as IsLoad, even if they + /// prefetch exclusive copies. + /// - If IsControl is set, then exactly one of IsDirectControl or + /// IsIndirect Control will be set, and exactly one of + /// IsCondControl or IsUncondControl will be set. + /// + enum Flags { + IsNop, ///< Is a no-op (no effect at all). + + IsInteger, ///< References integer regs. + IsFloating, ///< References FP regs. + + IsMemRef, ///< References memory (load, store, or prefetch). + IsLoad, ///< Reads from memory (load or prefetch). + IsStore, ///< Writes to memory. + IsInstPrefetch, ///< Instruction-cache prefetch. + IsDataPrefetch, ///< Data-cache prefetch. + + IsControl, ///< Control transfer instruction. + IsDirectControl, ///< PC relative control transfer. + IsIndirectControl, ///< Register indirect control transfer. + IsCondControl, ///< Conditional control transfer. + IsUncondControl, ///< Unconditional control transfer. + IsCall, ///< Subroutine call. + IsReturn, ///< Subroutine return. + + IsThreadSync, ///< Thread synchronization operation. + + NumFlags + }; + + /// Flag values for this instruction. + std::bitset flags; + + /// See opClass(). + OpClass _opClass; + + /// See numSrcRegs(). + int8_t _numSrcRegs; + + /// See numDestRegs(). + int8_t _numDestRegs; + + /// The following are used to track physical register usage + /// for machines with separate int & FP reg files. + //@{ + int8_t _numFPDestRegs; + int8_t _numIntDestRegs; + //@} + + /// Constructor. + /// It's important to initialize everything here to a sane + /// default, since the decoder generally only overrides + /// the fields that are meaningful for the particular + /// instruction. + StaticInstBase(OpClass __opClass) + : _opClass(__opClass), _numSrcRegs(0), _numDestRegs(0), + _numFPDestRegs(0), _numIntDestRegs(0) + { + } + + public: + + /// @name Register information. + /// The sum of numFPDestRegs() and numIntDestRegs() equals + /// numDestRegs(). The former two functions are used to track + /// physical register usage for machines with separate int & FP + /// reg files. + //@{ + /// Number of source registers. + int8_t numSrcRegs() const { return _numSrcRegs; } + /// Number of destination registers. + int8_t numDestRegs() const { return _numDestRegs; } + /// Number of floating-point destination regs. + int8_t numFPDestRegs() const { return _numFPDestRegs; } + /// Number of integer destination regs. + int8_t numIntDestRegs() const { return _numIntDestRegs; } + //@} + + /// @name Flag accessors. + /// These functions are used to access the values of the various + /// instruction property flags. See StaticInstBase::Flags for descriptions + /// of the individual flags. + //@{ + + bool isNop() const { return flags[IsNop]; } + + bool isMemRef() const { return flags[IsMemRef]; } + bool isLoad() const { return flags[IsLoad]; } + bool isStore() const { return flags[IsStore]; } + bool isInstPrefetch() const { return flags[IsInstPrefetch]; } + bool isDataPrefetch() const { return flags[IsDataPrefetch]; } + + bool isInteger() const { return flags[IsInteger]; } + bool isFloating() const { return flags[IsFloating]; } + + bool isControl() const { return flags[IsControl]; } + bool isCall() const { return flags[IsCall]; } + bool isReturn() const { return flags[IsReturn]; } + bool isDirectCtrl() const { return flags[IsDirectControl]; } + bool isIndirectCtrl() const { return flags[IsIndirectControl]; } + bool isCondCtrl() const { return flags[IsCondControl]; } + bool isUncondCtrl() const { return flags[IsUncondControl]; } + + bool isThreadSync() const { return flags[IsThreadSync]; } + //@} + + /// Operation class. Used to select appropriate function unit in issue. + OpClass opClass() const { return _opClass; } +}; + + +// forward declaration +template +class StaticInstPtr; + +/** + * Generic yet ISA-dependent static instruction class. + * + * This class builds on StaticInstBase, defining fields and interfaces + * that are generic across all ISAs but that differ in details + * according to the specific ISA being used. + */ +template +class StaticInst : public StaticInstBase +{ + public: + + /// Binary machine instruction type. + typedef typename ISA::MachInst MachInst; + /// Memory address type. + typedef typename ISA::Addr Addr; + /// Logical register index type. + typedef typename ISA::RegIndex RegIndex; + + enum { + MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs + MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs + }; + + + /// Return logical index (architectural reg num) of i'th destination reg. + /// Only the entries from 0 through numDestRegs()-1 are valid. + RegIndex destRegIdx(int i) { return _destRegIdx[i]; } + + /// Return logical index (architectural reg num) of i'th source reg. + /// Only the entries from 0 through numSrcRegs()-1 are valid. + RegIndex srcRegIdx(int i) { return _srcRegIdx[i]; } + + /// Pointer to a statically allocated "null" instruction object. + /// Used to give eaCompInst() and memAccInst() something to return + /// when called on non-memory instructions. + static StaticInstPtr nullStaticInstPtr; + + /** + * Memory references only: returns "fake" instruction representing + * the effective address part of the memory operation. Used to + * obtain the dependence info (numSrcRegs and srcRegIdx[]) for + * just the EA computation. + */ + virtual StaticInstPtr eaCompInst() { return nullStaticInstPtr; } + + /** + * Memory references only: returns "fake" instruction representing + * the memory access part of the memory operation. Used to + * obtain the dependence info (numSrcRegs and srcRegIdx[]) for + * just the memory access (not the EA computation). + */ + virtual StaticInstPtr memAccInst() { return nullStaticInstPtr; } + + /// The binary machine instruction. + const MachInst machInst; + + protected: + + /// See destRegIdx(). + RegIndex _destRegIdx[MaxInstDestRegs]; + /// See srcRegIdx(). + RegIndex _srcRegIdx[MaxInstSrcRegs]; + + /** + * Base mnemonic (e.g., "add"). Used by generateDisassembly() + * methods. Also useful to readily identify instructions from + * within the debugger when #cachedDisassembly has not been + * initialized. + */ + const char *mnemonic; + + /** + * String representation of disassembly (lazily evaluated via + * disassemble()). + */ + std::string *cachedDisassembly; + + /** + * Internal function to generate disassembly string. + */ + virtual std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) = 0; + + /// Constructor. + StaticInst(const char *_mnemonic, MachInst _machInst, OpClass __opClass) + : StaticInstBase(__opClass), + machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0) + { + } + + public: + + virtual ~StaticInst() + { + if (cachedDisassembly) + delete cachedDisassembly; + } + + /** + * Execute this instruction under SimpleCPU model. + */ + virtual Fault execute(SimpleCPU *cpu, ExecContext *xc, + Trace::InstRecord *traceData) = 0; + + /** + * Execute this instruction under detailed CPU model. + */ + virtual Fault execute(CPU *cpu, SpecExecContext *xc, DynInst *dynInst, + Trace::InstRecord *traceData) = 0; + + /** + * Return the target address for a PC-relative branch. + * Invalid if not a PC-relative branch (i.e. isDirectCtrl() + * should be true). + */ + virtual Addr branchTarget(Addr branchPC) + { + panic("StaticInst::branchTarget() called on instruction " + "that is not a PC-relative branch."); + } + + /** + * Return the target address for an indirect branch (jump). + * The register value is read from the supplied execution context. + * Invalid if not an indirect branch (i.e. isIndirectCtrl() + * should be true). + */ + virtual Addr branchTarget(ExecContext *xc) + { + panic("StaticInst::branchTarget() called on instruction " + "that is not an indirect branch."); + } + + /** + * Return true if the instruction is a control transfer, and if so, + * return the target address as well. + */ + bool hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt); + + /** + * Return string representation of disassembled instruction. + * The default version of this function will call the internal + * virtual generateDisassembly() function to get the string, + * then cache it in #cachedDisassembly. If the disassembly + * should not be cached, this function should be overridden directly. + */ + virtual const std::string &disassemble(Addr pc, + const SymbolTable *symtab = 0) + { + if (!cachedDisassembly) + cachedDisassembly = + new std::string(generateDisassembly(pc, symtab)); + + return *cachedDisassembly; + } + + /// Decoded instruction cache type. + /// For now we're using a generic hash_map; this seems to work + /// pretty well. + typedef m5::hash_map > DecodeCache; + + /// A cache of decoded instruction objects. + static DecodeCache decodeCache; + + /** + * Dump some basic stats on the decode cache hash map. + * Only gets called if DECODE_CACHE_HASH_STATS is defined. + */ + static void dumpDecodeCacheStats(); + + /// Decode a machine instruction. + /// @param mach_inst The binary instruction to decode. + /// @retval A pointer to the corresponding StaticInst object. + static + StaticInstPtr decode(MachInst mach_inst) + { +#ifdef DECODE_CACHE_HASH_STATS + // Simple stats on decode hash_map. Turns out the default + // hash function is as good as anything I could come up with. + const int dump_every_n = 10000000; + static int decodes_til_dump = dump_every_n; + + if (--decodes_til_dump == 0) { + dumpDecodeCacheStats(); + decodes_til_dump = dump_every_n; + } +#endif + + typename DecodeCache::iterator iter = decodeCache.find(mach_inst); + if (iter != decodeCache.end()) { + return iter->second; + } + + StaticInstPtr si = ISA::decodeInst(mach_inst); + decodeCache[mach_inst] = si; + return si; + } +}; + +typedef RefCountingPtr StaticInstBasePtr; + +/// Reference-counted pointer to a StaticInst object. +/// This type should be used instead of "StaticInst *" so that +/// StaticInst objects can be properly reference-counted. +template +class StaticInstPtr : public RefCountingPtr > +{ + public: + /// Constructor. + StaticInstPtr() + : RefCountingPtr >() + { + } + + /// Conversion from "StaticInst *". + StaticInstPtr(StaticInst *p) + : RefCountingPtr >(p) + { + } + + /// Copy constructor. + StaticInstPtr(const StaticInstPtr &r) + : RefCountingPtr >(r) + { + } + + /// Construct directly from machine instruction. + /// Calls StaticInst::decode(). + StaticInstPtr(typename ISA::MachInst mach_inst) + : RefCountingPtr >(StaticInst::decode(mach_inst)) + { + } + + /// Convert to pointer to StaticInstBase class. + operator const StaticInstBasePtr() + { + return get(); + } +}; + +#endif // __STATIC_INST_HH__ diff --git a/sim/base_cpu.cc b/sim/base_cpu.cc deleted file mode 100644 index 06b2ec65c..000000000 --- a/sim/base_cpu.cc +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -#include "base_cpu.hh" -#include "cprintf.hh" -#include "exec_context.hh" -#include "misc.hh" -#include "sim_events.hh" - -using namespace std; - -vector BaseCPU::cpuList; - -// This variable reflects the max number of threads in any CPU. Be -// careful to only use it once all the CPUs that you care about have -// been initialized -int maxThreadsPerCPU = 1; - -#ifdef FULL_SYSTEM -BaseCPU::BaseCPU(const string &_name, int _number_of_threads, - Counter max_insts_any_thread, - Counter max_insts_all_threads, - System *_system, int num, Tick freq) - : SimObject(_name), number(num), frequency(freq), - number_of_threads(_number_of_threads), system(_system) -#else -BaseCPU::BaseCPU(const string &_name, int _number_of_threads, - Counter max_insts_any_thread, - Counter max_insts_all_threads) - : SimObject(_name), number_of_threads(_number_of_threads) -#endif -{ - // add self to global list of CPUs - cpuList.push_back(this); - - if (number_of_threads > maxThreadsPerCPU) - maxThreadsPerCPU = number_of_threads; - - // allocate per-thread instruction-based event queues - comInsnEventQueue = new (EventQueue *)[number_of_threads]; - for (int i = 0; i < number_of_threads; ++i) - comInsnEventQueue[i] = new EventQueue("instruction-based event queue"); - - // - // set up instruction-count-based termination events, if any - // - if (max_insts_any_thread != 0) - for (int i = 0; i < number_of_threads; ++i) - new SimExitEvent(comInsnEventQueue[i], max_insts_any_thread, - "a thread reached the max instruction count"); - - if (max_insts_all_threads != 0) { - // allocate & initialize shared downcounter: each event will - // decrement this when triggered; simulation will terminate - // when counter reaches 0 - int *counter = new int; - *counter = number_of_threads; - for (int i = 0; i < number_of_threads; ++i) - new CountedExitEvent(comInsnEventQueue[i], - "all threads reached the max instruction count", - max_insts_all_threads, *counter); - } - -#ifdef FULL_SYSTEM - memset(interrupts, 0, sizeof(interrupts)); - intstatus = 0; -#endif -} - -void -BaseCPU::regStats() -{ - int size = contexts.size(); - if (size > 1) { - for (int i = 0; i < size; ++i) { - stringstream namestr; - ccprintf(namestr, "%s.ctx%d", name(), i); - contexts[i]->regStats(namestr.str()); - } - } else if (size == 1) - contexts[0]->regStats(name()); -} - -#ifdef FULL_SYSTEM -void -BaseCPU::post_interrupt(int int_num, int index) -{ - DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); - - if (int_num < 0 || int_num >= NumInterruptLevels) - panic("int_num out of bounds\n"); - - if (index < 0 || index >= sizeof(uint8_t) * 8) - panic("int_num out of bounds\n"); - - AlphaISA::check_interrupts = 1; - interrupts[int_num] |= 1 << index; - intstatus |= (ULL(1) << int_num); -} - -void -BaseCPU::clear_interrupt(int int_num, int index) -{ - DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); - - if (int_num < 0 || int_num >= NumInterruptLevels) - panic("int_num out of bounds\n"); - - if (index < 0 || index >= sizeof(uint8_t) * 8) - panic("int_num out of bounds\n"); - - interrupts[int_num] &= ~(1 << index); - if (interrupts[int_num] == 0) - intstatus &= ~(ULL(1) << int_num); -} - -void -BaseCPU::clear_interrupts() -{ - DPRINTF(Interrupt, "Interrupts all cleared\n"); - - memset(interrupts, 0, sizeof(interrupts)); - intstatus = 0; -} - -#endif // FULL_SYSTEM - -DEFINE_SIM_OBJECT_CLASS_NAME("BaseCPU", BaseCPU) diff --git a/sim/base_cpu.hh b/sim/base_cpu.hh deleted file mode 100644 index 745220d85..000000000 --- a/sim/base_cpu.hh +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __BASE_CPU_HH__ -#define __BASE_CPU_HH__ - -#include - -#include "eventq.hh" -#include "sim_object.hh" - -#include "isa_traits.hh" // for Addr - -#ifdef FULL_SYSTEM -class System; -#endif - -class BranchPred; -class ExecContext; - -class BaseCPU : public SimObject -{ -#ifdef FULL_SYSTEM - protected: - int number; - Tick frequency; - uint8_t interrupts[NumInterruptLevels]; - uint64_t intstatus; - - public: - virtual void post_interrupt(int int_num, int index); - virtual void clear_interrupt(int int_num, int index); - virtual void clear_interrupts(); - - bool check_interrupt(int int_num) const { - if (int_num > NumInterruptLevels) - panic("int_num out of bounds\n"); - - return interrupts[int_num] != 0; - } - - bool check_interrupts() const { return intstatus != 0; } - uint64_t intr_status() const { return intstatus; } - - Tick getFreq() const { return frequency; } -#endif - - protected: - std::vector contexts; - - public: - virtual void execCtxStatusChg() {} - - public: - -#ifdef FULL_SYSTEM - BaseCPU(const std::string &_name, int _number_of_threads, - Counter max_insts_any_thread, Counter max_insts_all_threads, - System *_system, - int num, Tick freq); -#else - BaseCPU(const std::string &_name, int _number_of_threads, - Counter max_insts_any_thread = 0, - Counter max_insts_all_threads = 0); -#endif - - virtual ~BaseCPU() {} - - virtual void regStats(); - - /// Number of threads we're actually simulating (<= SMT_MAX_THREADS). - /// This is a constant for the duration of the simulation. - int number_of_threads; - - /// Vector of per-thread instruction-based event queues. Used for - /// scheduling events based on number of instructions committed by - /// a particular thread. - EventQueue **comInsnEventQueue; - -#ifdef FULL_SYSTEM - System *system; -#endif - - virtual bool filterThisInstructionPrefetch(int thread_number, - short asid, Addr prefetchTarget) const { return true; } - - /// Return pointer to CPU's branch predictor (NULL if none). - virtual BranchPred *getBranchPred() { return NULL; }; - - private: - static std::vector cpuList; //!< Static global cpu list - - public: - static int numSimulatedCPUs() { return cpuList.size(); } -}; - -#endif // __BASE_CPU_HH__ diff --git a/sim/cache/lzss_compression.cc b/sim/cache/lzss_compression.cc deleted file mode 100644 index a1933215a..000000000 --- a/sim/cache/lzss_compression.cc +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** @file - * LZSSCompression definitions. - */ - -#include - -#include "lzss_compression.hh" - -#include "misc.hh" //for fatal - -int -LZSSCompression::findSubString(uint8_t *src, int front, int back, int size) -{ - int subSize = 0; - int max_length = 2048; - if (size - back < max_length) { - max_length = size - back; - } - for (int i = 0; i < max_length; ++i) { - if (src[front+i] != src[back+i]) { - return subSize; - } - ++subSize; - } - return subSize; -} - -int -LZSSCompression::emitByte(uint8_t *dest, uint8_t byte) -{ - if ((byte >> 5 & 0x7) == 0 || (byte >> 5 & 0x7) == 7) { - // If the top 3 bits are the same, emit 00<6bits> - dest[0] = byte & 0x3f; - return 1; - } else { - // emit 01XXXXXX <8 bits> - dest[0] = 0x40; - dest[1] = byte; - return 2; - } -} - -void -LZSSCompression::emitString(uint8_t *dest, uint16_t P, uint16_t L) -{ - // Emit 1<7P> <5P><3L> <8L> - dest[0] = 1<<7 | (P >> 5 & 0x7f); - dest[1] = ((P & 0x1f) << 3) | (L>>8 & 0x3); - dest[2] = L & 0xFF; -} - -int -LZSSCompression::compress(uint8_t *dest, uint8_t *src, int size) -{ - if (size > 4096) { - fatal("Compression can only handle block sizes of 4096 bytes or less"); - } - - // Encode the first byte. - int dest_index = emitByte(dest, src[0]); - int i = 1; - // A 11 bit field - uint16_t L; - // A 12 bit field - uint16_t P = 0; - - while (i < size && dest_index < size) { - L = 0; - - if (dest_index+3 >= size) { - dest_index = size; - continue; - } - - if (i == size - 1) { - // Output the character - dest_index += emitByte(&dest[dest_index], src[i]); - ++i; - continue; - } - for (int j = 0; j < i; ++j) { - int sub_size = findSubString(src, j, i, size); - if (sub_size >= L) { - L = sub_size; - P = j; - } - } - if (L > 1) { - // Output the string reference - emitString(&dest[dest_index], P, L); - dest_index += 3; - i = i+L; - } else { - // Output the character - dest_index += emitByte(&dest[dest_index], src[i]); - ++i; - } - } - - if (dest_index >= size) { - // Have expansion instead of compression, just copy. - memcpy(dest,src,size); - return size; - } - return dest_index; -} - -int -LZSSCompression::uncompress(uint8_t *dest, uint8_t *src, int size) -{ - int index = 0; - int i = 0; - while (i < size) { - if (src[i] & 1<<7 ) { - // We have a string - // Extract P - int start = (src[i] & 0x3f)<<5 | ((src[i+1] >> 3) & 0x1f); - // Extract L - int len = (src[i+1] & 0x07)<<8 | src[i+2]; - i += 3; - for (int j = start; j < start+len; ++j) { - dest[index++] = dest[j]; - } - } else { - // We have a character - if (src[i] & 1<<6) { - // Value is in the next byte - dest[index++] = src[i+1]; - i += 2; - } else { - // just extend the lower 6 bits - dest[index++] = (src[i] & 0x3f) | ((src[i] & 1<<5) ? 0xC0 : 0); - ++i; - } - } - } - return index; -} diff --git a/sim/cache/lzss_compression.hh b/sim/cache/lzss_compression.hh deleted file mode 100644 index 5fb47d3f1..000000000 --- a/sim/cache/lzss_compression.hh +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __LZSS_COMPRESSION_HH__ -#define __LZSS_COMPRESSION_HH__ - -/** @file - * LZSSCompression declarations. - */ - -#include "host.hh" // for uint8_t - -/** - * Simple LZSS compression scheme. - */ -class LZSSCompression -{ - /** - * Finds the longest substrings that start at the given offsets. - * @param src The source block that we search for substrings. - * @param front The smaller offset. - * @param back The larger offset. - * @param size The size of the source block. - * @return The size of the longest substring. - */ - int findSubString(uint8_t *src, int front, int back, int size); - - /** - * Emit an encoded byte to the compressed data array. If the 2 high - * order bits can be signed extended, use 1 byte encoding, if not use 2 - * bytes. - * @param dest The compressed data. - * @param byte The byte to emit. - * @return The number of bytes used to encode. - */ - int emitByte(uint8_t *dest, uint8_t byte); - - /** - * Emit a string reference to the compressed data array. A string reference - * always uses 3 bytes. 1 flag bit, 12 bits for the starting position, and - * 11 bits for the length of the string. This allows compression of 4096 - * byte blocks with string lengths of up to 2048 bytes. - * @param dest The compressed data. - * @param P The starting position in the uncompressed data. - * @param L The length in bytes of the string. - */ - void emitString(uint8_t *dest, uint16_t P, uint16_t L); - - public: - /** - * Compresses the source block and stores it in the destination block. If - * the compressed block grows to larger than the source block, it aborts - * and just performs a copy. - * @param dest The destination block. - * @param src The block to be compressed. - * @param size The size of the source block. - * @return The size of the compressed block. - * - * @pre Destination has enough storage to hold the compressed block. - */ - int compress(uint8_t *dest, uint8_t *src, int size); - - /** - * Unompresses the source block and stores it in the destination block. - * @param dest The destination block. - * @param src The block to be uncompressed. - * @param size The size of the source block. - * @return The size of the uncompressed block. - * - * @pre Destination has enough storage to hold the uncompressed block. - */ - int uncompress(uint8_t *dest, uint8_t *src, int size); -}; - -#endif //__LZSS_COMPRESSION_HH__ diff --git a/sim/cache/null_compression.hh b/sim/cache/null_compression.hh deleted file mode 100644 index d2bc76eef..000000000 --- a/sim/cache/null_compression.hh +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __NULL_COMPRESSION_HH__ -#define __NULL_COMPRESSION_HH__ - -/** - * @file - * This file defines a doNothing compression algorithm. - */ - -/** - * A dummy compression class to use when no data compression is desired. - */ -class NullCompression -{ - public: - /** - * Uncompress the data, causes a fatal since no data should be compressed. - * @param dest The output buffer. - * @param src The compressed data. - * @param size The number of bytes in src. - * - * @retval The size of the uncompressed data. - */ - static int uncompress(uint8_t * dest, uint8_t *src, int size) - { - fatal("Can't uncompress data"); - } - - /** - * Compress the data, just returns the source data. - * @param dest The output buffer. - * @param src The data to be compressed. - * @param size The number of bytes in src. - * - * @retval The size of the compressed data. - */ - - static int compress(uint8_t *dest, uint8_t *src, int size) - { - memcpy(dest,src,size); - return size; - } -}; - -#endif //__NULL_COMPRESSION_HH__ diff --git a/sim/exec_context.cc b/sim/exec_context.cc deleted file mode 100644 index c81d172a8..000000000 --- a/sim/exec_context.cc +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "base_cpu.hh" -#include "exec_context.hh" - -#ifdef FULL_SYSTEM -#include "system.hh" -#else -#include "prog.hh" -#endif - -using namespace std; - -// constructor -#ifdef FULL_SYSTEM -ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys, - AlphaItb *_itb, AlphaDtb *_dtb, - FunctionalMemory *_mem, int _cpu_id) - : kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num), mem(_mem), - itb(_itb), dtb(_dtb), cpu_id(_cpu_id), system(_sys), - memCtrl(_sys->memCtrl), physmem(_sys->physmem) -{ - memset(®s, 0, sizeof(RegFile)); - _status = Active; - func_exe_insn = 0; - storeCondFailures = 0; - system->registerExecContext(this); -} -#else -ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, - Process *_process, int _asid) - : cpu(_cpu), thread_num(_thread_num), process(_process), asid (_asid) -{ - - // Register with process object. Our 'active' will be set by the - // process iff we're the initial context. Others are reserved for - // dynamically created threads. - process->registerExecContext(this); - - mem = process->getMemory(); - - func_exe_insn = 0; - storeCondFailures = 0; -} - -ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, - FunctionalMemory *_mem, int _asid) - : cpu(_cpu), thread_num(_thread_num), process(NULL), mem(_mem), - asid(_asid) -{ -} -#endif - -void -ExecContext::setStatus(Status new_status) -{ -#ifdef FULL_SYSTEM - if (status() == new_status) - return; - - // Don't change the status from active if there are pending interrupts - if (new_status == Suspended && cpu->check_interrupts()) { - assert(status() == Active); - return; - } -#endif - - _status = new_status; - cpu->execCtxStatusChg(); -} - -void -ExecContext::regStats(const string &name) -{ -#ifdef FULL_SYSTEM - kernelStats.regStats(name + ".kern"); -#endif -} diff --git a/sim/exec_context.hh b/sim/exec_context.hh deleted file mode 100644 index 988673a0f..000000000 --- a/sim/exec_context.hh +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __EXEC_CONTEXT_HH__ -#define __EXEC_CONTEXT_HH__ - -#include "host.hh" -#include "mem_req.hh" - -// forward declaration: see functional_memory.hh -class FunctionalMemory; -class PhysicalMemory; -class BaseCPU; - -#ifdef FULL_SYSTEM - -#include "alpha_memory.hh" -class MemoryController; - -#include "kernel_stats.hh" -#include "system.hh" - -#else // !FULL_SYSTEM - -#include "prog.hh" - -#endif // FULL_SYSTEM - -// -// The ExecContext object represents a functional context for -// instruction execution. It incorporates everything required for -// architecture-level functional simulation of a single thread. -// - -class ExecContext -{ - public: - enum Status { Unallocated, Active, Suspended, Halted }; - - private: - Status _status; - - public: - Status status() const { return _status; } - void setStatus(Status new_status); - -#ifdef FULL_SYSTEM - public: - KernelStats kernelStats; -#endif - - public: - RegFile regs; // correct-path register context - - // pointer to CPU associated with this context - BaseCPU *cpu; - - // Index of hardware thread context on the CPU that this represents. - int thread_num; - -#ifdef FULL_SYSTEM - - FunctionalMemory *mem; - AlphaItb *itb; - AlphaDtb *dtb; - int cpu_id; - System *system; - - // the following two fields are redundant, since we can always - // look them up through the system pointer, but we'll leave them - // here for now for convenience - MemoryController *memCtrl; - PhysicalMemory *physmem; - -#else - Process *process; - - FunctionalMemory *mem; // functional storage for process address space - - // Address space ID. Note that this is used for TIMING cache - // simulation only; all functional memory accesses should use - // one of the FunctionalMemory pointers above. - short asid; - -#endif - - - /* - * number of executed instructions, for matching with syscall trace - * points in EIO files. - */ - Counter func_exe_insn; - - // - // Count failed store conditionals so we can warn of apparent - // application deadlock situations. - unsigned storeCondFailures; - - // constructor: initialize context from given process structure -#ifdef FULL_SYSTEM - ExecContext(BaseCPU *_cpu, int _thread_num, System *_system, - AlphaItb *_itb, AlphaDtb *_dtb, FunctionalMemory *_dem, - int _cpu_id); -#else - ExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid); - ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem, - int _asid); -#endif - virtual ~ExecContext() {} - - void regStats(const std::string &name); - -#ifdef FULL_SYSTEM - bool validInstAddr(Addr addr) { return true; } - bool validDataAddr(Addr addr) { return true; } - int getInstAsid() { return ITB_ASN_ASN(regs.ipr[TheISA::IPR_ITB_ASN]); } - int getDataAsid() { return DTB_ASN_ASN(regs.ipr[TheISA::IPR_DTB_ASN]); } - - Fault translateInstReq(MemReqPtr req) - { - return itb->translate(req); - } - - Fault translateDataReadReq(MemReqPtr req) - { - return dtb->translate(req, false); - } - - Fault translateDataWriteReq(MemReqPtr req) - { - return dtb->translate(req, true); - } - - -#else - bool validInstAddr(Addr addr) - { return process->validInstAddr(addr); } - - bool validDataAddr(Addr addr) - { return process->validDataAddr(addr); } - - int getInstAsid() { return asid; } - int getDataAsid() { return asid; } - - Fault dummyTranslation(MemReqPtr req) - { -#if 0 - assert((req->vaddr >> 48 & 0xffff) == 0); -#endif - - // put the asid in the upper 16 bits of the paddr - req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16); - req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16; - return No_Fault; - } - Fault translateInstReq(MemReqPtr req) - { - return dummyTranslation(req); - } - Fault translateDataReadReq(MemReqPtr req) - { - return dummyTranslation(req); - } - Fault translateDataWriteReq(MemReqPtr req) - { - return dummyTranslation(req); - } - -#endif - - template - Fault read(MemReqPtr req, T& data) - { -#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM) - if (req->flags & LOCKED) { - MiscRegFile *cregs = &req->xc->regs.miscRegs; - cregs->lock_addr = req->paddr; - cregs->lock_flag = true; - } -#endif - return mem->read(req, data); - } - - template - Fault write(MemReqPtr req, T& data) - { -#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM) - - MiscRegFile *cregs; - - // If this is a store conditional, act appropriately - if (req->flags & LOCKED) { - cregs = &req->xc->regs.miscRegs; - - if (req->flags & UNCACHEABLE) { - // Don't update result register (see machine.def) - req->result = 2; - req->xc->storeCondFailures = 0;//Needed? [RGD] - } else { - req->result = cregs->lock_flag; - if (!cregs->lock_flag || - ((cregs->lock_addr & ~0xf) != (req->paddr & ~0xf))) { - cregs->lock_flag = false; - if (((++req->xc->storeCondFailures) % 100000) == 0) { - std::cerr << "Warning: " - << req->xc->storeCondFailures - << " consecutive store conditional failures " - << "on cpu " << req->xc->cpu_id - << std::endl; - } - return No_Fault; - } - else req->xc->storeCondFailures = 0; - } - } - - // Need to clear any locked flags on other proccessors for this - // address - // Only do this for succsful Store Conditionals and all other - // stores (WH64?) - // Unsuccesful Store Conditionals would have returned above, - // and wouldn't fall through - for(int i = 0; i < system->num_cpus; i++){ - cregs = &system->xc_array[i]->regs.miscRegs; - if((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) { - cregs->lock_flag = false; - } - } - -#endif - return mem->write(req, data); - } - - virtual bool misspeculating(); - - - // - // New accessors for new decoder. - // - uint64_t readIntReg(int reg_idx) - { - return regs.intRegFile[reg_idx]; - } - - float readFloatRegSingle(int reg_idx) - { - return (float)regs.floatRegFile.d[reg_idx]; - } - - double readFloatRegDouble(int reg_idx) - { - return regs.floatRegFile.d[reg_idx]; - } - - uint64_t readFloatRegInt(int reg_idx) - { - return regs.floatRegFile.q[reg_idx]; - } - - void setIntReg(int reg_idx, uint64_t val) - { - regs.intRegFile[reg_idx] = val; - } - - void setFloatRegSingle(int reg_idx, float val) - { - regs.floatRegFile.d[reg_idx] = (double)val; - } - - void setFloatRegDouble(int reg_idx, double val) - { - regs.floatRegFile.d[reg_idx] = val; - } - - void setFloatRegInt(int reg_idx, uint64_t val) - { - regs.floatRegFile.q[reg_idx] = val; - } - - uint64_t readPC() - { - return regs.pc; - } - - void setNextPC(uint64_t val) - { - regs.npc = val; - } - - uint64_t readUniq() - { - return regs.miscRegs.uniq; - } - - void setUniq(uint64_t val) - { - regs.miscRegs.uniq = val; - } - - uint64_t readFpcr() - { - return regs.miscRegs.fpcr; - } - - void setFpcr(uint64_t val) - { - regs.miscRegs.fpcr = val; - } - -#ifdef FULL_SYSTEM - uint64_t readIpr(int idx, Fault &fault); - Fault setIpr(int idx, uint64_t val); - Fault hwrei(); - void ev5_trap(Fault fault); - bool simPalCheck(int palFunc); -#endif - -#ifndef FULL_SYSTEM - void syscall() - { - process->syscall(this); - } -#endif -}; - - -// for non-speculative execution context, spec_mode is always false -inline bool -ExecContext::misspeculating() -{ - return false; -} - -#endif // __EXEC_CONTEXT_HH__ diff --git a/sim/exetrace.cc b/sim/exetrace.cc deleted file mode 100644 index 4c5d14893..000000000 --- a/sim/exetrace.cc +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include "dyn_inst.hh" -#include "spec_state.hh" -#include "issue.hh" -#include "exetrace.hh" -#include "exec_context.hh" -#include "symtab.hh" -#include "base_cpu.hh" -#include "static_inst.hh" - -using namespace std; - - -//////////////////////////////////////////////////////////////////////// -// -// Methods for the InstRecord object -// - - -const SymbolTable *debugSymbolTable = NULL; - -void -Trace::InstRecord::dump(ostream &outs) -{ - if (flags[PRINT_CYCLE]) - ccprintf(outs, "%7d: ", cycle); - - outs << cpu->name() << " "; - - if (flags[TRACE_MISSPEC]) - outs << (misspeculating ? "-" : "+") << " "; - - if (flags[PRINT_THREAD_NUM]) - outs << "T" << thread << " : "; - - outs << "0x" << hex << PC << " : "; - - // - // Print decoded instruction - // - -#if defined(__GNUC__) && (__GNUC__ < 3) - // There's a bug in gcc 2.x library that prevents setw() - // from working properly on strings - string mc(staticInst->disassemble(PC, debugSymbolTable)); - while (mc.length() < 25) - mc += " "; - outs << mc; -#else - outs << setw(25) << staticInst->disassemble(PC, debugSymbolTable); -#endif - - outs << " : "; - - if (flags[PRINT_OP_CLASS]) { - outs << opClassStrings[staticInst->opClass()] << " : "; - } - - if (flags[PRINT_RESULT_DATA] && data_status != DataInvalid) { - outs << " D="; -#if 0 - if (data_status == DataDouble) - ccprintf(outs, "%f", data.as_double); - else - ccprintf(outs, "%#018x", data.as_int); -#else - ccprintf(outs, "%#018x", data.as_int); -#endif - } - - if (flags[PRINT_EFF_ADDR] && addr_valid) - outs << " A=0x" << hex << addr; - - if (flags[PRINT_INT_REGS] && regs_valid) { - for (int i = 0; i < 32;) - for (int j = i + 1; i <= j; i++) - ccprintf(outs, "r%02d = %#018x%s", i, iregs->regs[i], - ((i == j) ? "\n" : " ")); - outs << "\n"; - } - - if (flags[PRINT_FETCH_SEQ] && fetch_seq_valid) - outs << " FetchSeq=" << dec << fetch_seq; - - if (flags[PRINT_CP_SEQ] && cp_seq_valid) - outs << " CPSeq=" << dec << cp_seq; - - // - // End of line... - // - outs << endl; - outs.flush(); -} - - -vector Trace::InstRecord::flags(NUM_BITS); - -//////////////////////////////////////////////////////////////////////// -// -// Parameter space for per-cycle execution address tracing options. -// Derive from ParamContext so we can override checkParams() function. -// -class ExecutionTraceParamContext : public ParamContext -{ - public: - ExecutionTraceParamContext(const string &_iniSection) - : ParamContext(_iniSection) - { - } - - void checkParams(); // defined at bottom of file -}; - -ExecutionTraceParamContext exeTraceParams("exetrace"); - -Param exe_trace_spec(&exeTraceParams, "speculative", - "capture speculative instructions", false); - -Param exe_trace_print_cycle(&exeTraceParams, "print_cycle", - "print cycle number", true); -Param exe_trace_print_opclass(&exeTraceParams, "print_opclass", - "print op class", true); -Param exe_trace_print_thread(&exeTraceParams, "print_thread", - "print thread number", true); -Param exe_trace_print_effaddr(&exeTraceParams, "print_effaddr", - "print effective address", true); -Param exe_trace_print_data(&exeTraceParams, "print_data", - "print result data", true); -Param exe_trace_print_iregs(&exeTraceParams, "print_iregs", - "print all integer regs", false); -Param exe_trace_print_fetchseq(&exeTraceParams, "print_fetchseq", - "print fetch sequence number", false); -Param exe_trace_print_cp_seq(&exeTraceParams, "print_cpseq", - "print correct-path sequence number", false); - -// -// Helper function for ExecutionTraceParamContext::checkParams() just -// to get us into the InstRecord namespace -// -void -Trace::InstRecord::setParams() -{ - flags[TRACE_MISSPEC] = exe_trace_spec; - - flags[PRINT_CYCLE] = exe_trace_print_cycle; - flags[PRINT_OP_CLASS] = exe_trace_print_opclass; - flags[PRINT_THREAD_NUM] = exe_trace_print_thread; - flags[PRINT_RESULT_DATA] = exe_trace_print_effaddr; - flags[PRINT_EFF_ADDR] = exe_trace_print_data; - flags[PRINT_INT_REGS] = exe_trace_print_iregs; - flags[PRINT_FETCH_SEQ] = exe_trace_print_fetchseq; - flags[PRINT_CP_SEQ] = exe_trace_print_cp_seq; -} - -void -ExecutionTraceParamContext::checkParams() -{ - Trace::InstRecord::setParams(); -} - diff --git a/sim/exetrace.hh b/sim/exetrace.hh deleted file mode 100644 index 2eb7753e5..000000000 --- a/sim/exetrace.hh +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __EXETRACE_HH__ -#define __EXETRACE_HH__ - -#include -#include - -#include "host.hh" -#include "inst_seq.hh" // for InstSeqNum -#include "trace.hh" -#include "exec_context.hh" -#include "static_inst.hh" - -class BaseCPU; - - -namespace Trace { - -#if 0 - static const FlagVec ALL = ULL(0x1); - static const FlagVec FULL = ULL(0x2); - static const FlagVec SYMBOLS = ULL(0x4); - static const FlagVec EXTENDED = ULL(0x8); - static const FlagVec BRANCH_TAKEN = ULL(0x10); - static const FlagVec BRANCH_NOTTAKEN = ULL(0x20); - static const FlagVec CALLPAL = ULL(0x40); - static const FlagVec SPECULATIVE = ULL(0x100); - static const FlagVec OMIT_COUNT = ULL(0x200); - static const FlagVec INCLUDE_THREAD_NUM = ULL(0x400); -#endif - -class InstRecord : public Record -{ - protected: - - // The following fields are initialized by the constructor and - // thus guaranteed to be valid. - BaseCPU *cpu; - // need to make this ref-counted so it doesn't go away before we - // dump the record - StaticInstPtr staticInst; - Addr PC; - bool misspeculating; - unsigned thread; - - // The remaining fields are only valid for particular instruction - // types (e.g, addresses for memory ops) or when particular - // options are enabled (e.g., tracing full register contents). - // Each data field has an associated valid flag to indicate - // whether the data field is valid. - Addr addr; - bool addr_valid; - - union { - uint64_t as_int; - double as_double; - } data; - enum { - DataInvalid = 0, - DataInt8 = 1, // set to equal number of bytes - DataInt16 = 2, - DataInt32 = 4, - DataInt64 = 8, - DataDouble = 3 - } data_status; - - InstSeqNum fetch_seq; - bool fetch_seq_valid; - - InstSeqNum cp_seq; - bool cp_seq_valid; - - struct iRegFile { - IntRegFile regs; - }; - iRegFile *iregs; - bool regs_valid; - - public: - InstRecord(Tick _cycle, BaseCPU *_cpu, StaticInstPtr _staticInst, - Addr _pc, bool spec, unsigned _thread) - : Record(_cycle), cpu(_cpu), staticInst(_staticInst), PC(_pc), - misspeculating(spec), thread(_thread) - { - data_status = DataInvalid; - addr_valid = false; - regs_valid = false; - - fetch_seq_valid = false; - cp_seq_valid = false; - } - - virtual ~InstRecord() { } - - virtual void dump(std::ostream &outs); - - void setAddr(Addr a) { addr = a; addr_valid = true; } - - void setData(uint64_t d) { data.as_int = d; data_status = DataInt64; } - void setData(uint32_t d) { data.as_int = d; data_status = DataInt32; } - void setData(uint16_t d) { data.as_int = d; data_status = DataInt16; } - void setData(uint8_t d) { data.as_int = d; data_status = DataInt8; } - - void setData(int64_t d) { setData((uint64_t)d); } - void setData(int32_t d) { setData((uint32_t)d); } - void setData(int16_t d) { setData((uint16_t)d); } - void setData(int8_t d) { setData((uint8_t)d); } - - void setData(double d) { data.as_double = d; data_status = DataDouble; } - - void setFetchSeq(InstSeqNum seq) - { fetch_seq = seq; fetch_seq_valid = true; } - - void setCPSeq(InstSeqNum seq) - { cp_seq = seq; cp_seq_valid = true; } - - void setRegs(const IntRegFile ®s); - - void finalize() { theLog.append(this); } - - enum InstExecFlagBits { - TRACE_MISSPEC = 0, - PRINT_CYCLE, - PRINT_OP_CLASS, - PRINT_THREAD_NUM, - PRINT_RESULT_DATA, - PRINT_EFF_ADDR, - PRINT_INT_REGS, - PRINT_FETCH_SEQ, - PRINT_CP_SEQ, - NUM_BITS - }; - - static std::vector flags; - - static void setParams(); - - static bool traceMisspec() { return flags[TRACE_MISSPEC]; } -}; - - -inline void -InstRecord::setRegs(const IntRegFile ®s) -{ - if (!iregs) - iregs = new iRegFile; - - memcpy(&iregs->regs, regs, sizeof(IntRegFile)); - regs_valid = true; -} - -inline -InstRecord * -getInstRecord(Tick cycle, ExecContext *xc, BaseCPU *cpu, - const StaticInstPtr staticInst, - Addr pc, int thread = 0) -{ - if (DTRACE(InstExec) && - (InstRecord::traceMisspec() || !xc->misspeculating())) { - return new InstRecord(cycle, cpu, staticInst, pc, - xc->misspeculating(), thread); - } - - return NULL; -} - - -} - -#endif // __EXETRACE_HH__ diff --git a/sim/hybrid_pred.cc b/sim/hybrid_pred.cc deleted file mode 100644 index ed7f781b2..000000000 --- a/sim/hybrid_pred.cc +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include "hybrid_pred.hh" -#include "statistics.hh" -#include "sim_stats.hh" - -using namespace std; - -HybridPredictor::HybridPredictor(const char *_p_name, const char *_z_name, - const char *_o_name, - unsigned _index_bits, unsigned _counter_bits, - unsigned _zero_change, unsigned _one_change, - unsigned _thresh, - unsigned _global_bits, - unsigned _global_thresh, - bool _reg_individual_stats) -{ - stringstream local_name, global_name; - - pred_name = _p_name; - one_name = _o_name; - zero_name = _z_name; - reg_individual_stats = _reg_individual_stats; - - local_name << pred_name.c_str() << ":L"; - local = new SaturatingCounterPred(local_name.str(), zero_name, one_name, - _index_bits, _counter_bits, - _zero_change, _one_change, _thresh); - - global_name << pred_name.c_str() << ":G"; - global = new SaturatingCounterPred(global_name.str(), zero_name, one_name, - 0, _global_bits, 1, 1, _global_thresh); -} - -void HybridPredictor::regStats() -{ - using namespace Statistics; - - string p_name; - stringstream description; - - if (reg_individual_stats) - p_name = pred_name + ":A"; - else - p_name = pred_name; - - - // - // Number of predictions - // - stringstream num_zero_preds; - num_zero_preds << p_name << ":" << zero_name << ":preds"; - description << "number of predictions of " << zero_name; - pred_zero - .name(num_zero_preds.str()) - .desc(description.str()); - description.str(""); - - stringstream num_one_preds; - num_one_preds << p_name << ":" << one_name << ":preds"; - description << "number of predictions of " << one_name; - pred_one - .name(num_one_preds.str()) - .desc(description.str()) - ; - description.str(""); - - // - // Count the number of correct predictions - // - stringstream num_zero_correct; - num_zero_correct << p_name << ":" << zero_name << ":corr_preds"; - description << "number of correct " << zero_name << " preds" ; - correct_pred_zero - .name(num_zero_correct.str()) - .desc(description.str()) - ; - description.str(""); - - stringstream num_one_correct; - num_one_correct << p_name << ":" << one_name << ":corr_preds"; - description << "number of correct " << one_name << " preds" ; - correct_pred_one - .name(num_one_correct.str()) - .desc(description.str()) - ; - description.str(""); - - - // - // Number of predictor updates - // - stringstream num_zero_updates; - num_zero_updates << p_name << ":" << zero_name << ":updates" ; - description << "number of actual " << zero_name << "s" ; - record_zero - .name(num_zero_updates.str()) - .desc(description.str()) - ; - description.str(""); - - stringstream num_one_updates; - num_one_updates << p_name << ":" << one_name << ":updates" ; - description << "number of actual " << one_name << "s" ; - record_one - .name(num_one_updates.str()) - .desc(description.str()) - ; - description.str(""); - - // - // Local & Global predictor stats - // - if (reg_individual_stats) { - local->regStats(); - global->regStats(); - } -} - -void HybridPredictor::regFormulas() -{ - using namespace Statistics; - - string p_name; - stringstream description; - stringstream name; - - if (reg_individual_stats) - p_name = pred_name + ":A"; - else - p_name = pred_name; - - // - // Number of predictions - // - name << p_name << ":predictions" ; - total_preds - .name(name.str()) - .desc("total number of predictions made") - ; - total_preds = pred_one + pred_zero; - name.str(""); - - // - // Fraction of all predictions that are one or zero - // - name << p_name << ":" << zero_name << ":pred_frac"; - description << "fraction of all preds that were " << zero_name ; - frac_preds_zero - .name(name.str()) - .desc(description.str()) - ; - frac_preds_zero = 100 * record_zero / total_preds; - description.str(""); - name.str(""); - - name << p_name << ":" << one_name << ":pred_frac"; - description << "fraction of all preds that were " << one_name ; - frac_preds_one - .name(name.str()) - .desc(description.str()) - ; - frac_preds_one = 100 * record_one / total_preds; - description.str(""); - name.str(""); - - // - // Count the number of correct predictions - // - name << p_name << ":correct_preds" ; - total_correct - .name(name.str()) - .desc("total number of correct predictions made") - ; - total_correct = correct_pred_one + correct_pred_zero; - name.str(""); - - - // - // Prediction accuracy rates - // - name << p_name << ":pred_rate"; - total_accuracy - .name(name.str()) - .desc("fraction of all preds that were correct") - ; - total_accuracy = 100 * total_correct / total_preds; - name.str(""); - - name << p_name << ":" << zero_name << ":pred_rate" ; - description << "fraction of "<< zero_name <<" preds that were correct"; - zero_accuracy - .name(name.str()) - .desc(description.str()) - ; - zero_accuracy = 100 * correct_pred_zero / pred_zero; - description.str(""); - name.str(""); - - name << p_name << ":" << one_name << ":pred_rate" ; - description << "fraction of "<< one_name <<" preds that were correct"; - one_accuracy - .name(name.str()) - .desc(description.str()) - ; - one_accuracy = 100 * correct_pred_one / pred_one; - description.str(""); - name.str(""); - - // - // Coverage - // - name << p_name << ":" << zero_name << ":coverage"; - description << "fraction of " << zero_name - << "s that were predicted correctly"; - zero_coverage - .name(name.str()) - .desc(description.str()) - ; - zero_coverage = 100 * correct_pred_zero / record_zero; - description.str(""); - name.str(""); - - name << p_name << ":" << one_name << ":coverage"; - description << "fraction of " << one_name - << "s that were predicted correctly"; - one_coverage - .name(name.str()) - .desc(description.str()) - ; - one_coverage = 100 * correct_pred_one / record_one; - description.str(""); - name.str(""); - - // - // Local & Global predictor stats - // - if (reg_individual_stats) { - local->regFormulas(); - global->regFormulas(); - } - -} - diff --git a/sim/hybrid_pred.hh b/sim/hybrid_pred.hh deleted file mode 100644 index f6e14e3e3..000000000 --- a/sim/hybrid_pred.hh +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -//========================================================================== -// -// This predictor takes the AND of a "local" and a "global" predictor -// in order to determine its prediction. -// -// -// -// - -#ifndef __HYBRID_PRED_HH__ -#define __HYBRID_PRED_HH__ - -#include - -#include "sat_counter.hh" - -#include "statistics.hh" -#include "sim_stats.hh" - -class HybridPredictor : public GenericPredictor -{ - private: - std::string pred_name; - std::string one_name; - std::string zero_name; - bool reg_individual_stats; - - SaturatingCounterPred *local; - SaturatingCounterPred *global; - - unsigned long max_index; - - // - // Stats - // - Statistics::Scalar<> pred_one; //num_one_preds - Statistics::Scalar<> pred_zero; //num_zero_preds - Statistics::Scalar<> correct_pred_one; //num_one_correct - Statistics::Scalar<> correct_pred_zero; //num_zero_correct - Statistics::Scalar<> record_one; //num_one_updates - Statistics::Scalar<> record_zero; //num_zero_updates - - Statistics::Formula total_preds; - Statistics::Formula frac_preds_zero; - Statistics::Formula frac_preds_one; - Statistics::Formula total_correct; - Statistics::Formula total_accuracy; - Statistics::Formula zero_accuracy; - Statistics::Formula one_accuracy; - Statistics::Formula zero_coverage; - Statistics::Formula one_coverage; - - public: - HybridPredictor(const char *_p_name, const char *_z_name, - const char *_o_name, - unsigned _index_bits, unsigned _counter_bits, - unsigned _zero_change, unsigned _one_change, - unsigned _thresh, - unsigned _global_bits, unsigned _global_thresh, - bool _reg_individual_stats = false); - - void clear() { - global->clear(); - local->clear(); - } - - unsigned peek(unsigned long _index) { - unsigned l = local->peek(_index); - unsigned g = global->peek(_index); - - if (l && g) - return 1; - - return 0; - } - - unsigned value(unsigned long _index) { - unsigned l = local->peek(_index); - unsigned g = global->peek(_index); - - l = l & 0xFFFF; - g = g & 0xFFFF; - - return (l << 16) | g; - - } - - unsigned predict(unsigned long _index) { - unsigned l = local->predict(_index); - unsigned g = global->predict(_index); - - if (l && g) { - ++pred_one; - return 1; - } - - ++pred_zero; - return 0; - } - - - // - // This version need only be used if local/global statistics - // will be maintained - // - unsigned predict(unsigned long _index, unsigned &_pdata) { - unsigned l = local->predict(_index); - unsigned g = global->predict(_index); - - // - // bit 0 => local predictor result - // bit 1 => global predictor result - // - _pdata = 0; - if (l) - _pdata |= 1; - if (g) - _pdata |= 2; - if (l && g) { - ++pred_one; - return 1; - } - - ++pred_zero; - return 0; - } - - void record(unsigned long _index, unsigned _val, unsigned _predicted) { - - if (_val) { - local->record(_index, _val, 0); - global->record(_index, _val, 0); - ++record_one; - - if (_val == _predicted) { - ++correct_pred_one; - } - } else { - local->record(_index, _val, 0); - global->record(_index, _val, 0); - ++record_zero; - - if (_val == _predicted) - ++correct_pred_zero; - } - } - - void record(unsigned long _index, unsigned _val, unsigned _predicted, - unsigned _pdata) - { - - local->record(_index, _val, (_pdata & 1)); - global->record(_index, _val, ((_pdata & 2) ? 1 : 0)); - - - if (_val) { - ++record_one; - - if (_val == _predicted) - ++correct_pred_one; - } else { - ++record_zero; - - if (_val == _predicted) - ++correct_pred_zero; - } - } - - void regStats(); - void regFormulas(); -}; - - -#endif // _HYBRID_PRED_HH__ - diff --git a/sim/inst_seq.hh b/sim/inst_seq.hh deleted file mode 100644 index 9c3898ff7..000000000 --- a/sim/inst_seq.hh +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __STD_TYPES_HH__ -#define __STD_TYPES_HH__ - -// inst sequence type, used to order instructions in the ready list, -// if this rolls over the ready list order temporarily will get messed -// up, but execution will continue and complete correctly -typedef unsigned long long InstSeqNum; - -// inst tag type, used to tag an operation instance in the IQ -typedef unsigned int InstTag; - -#endif // __STD_TYPES_HH__ diff --git a/sim/intr_control.cc b/sim/intr_control.cc deleted file mode 100644 index 7ad32a2b9..000000000 --- a/sim/intr_control.cc +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include "base_cpu.hh" -#include "intr_control.hh" -#include "sim_object.hh" - -using namespace std; - -IntrControl::IntrControl(const string &name, BaseCPU *c) - : SimObject(name), cpu(c) -{} - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(IntrControl) - - SimObjectParam cpu; - -END_DECLARE_SIM_OBJECT_PARAMS(IntrControl) - -BEGIN_INIT_SIM_OBJECT_PARAMS(IntrControl) - - INIT_PARAM(cpu, "the processor") - -END_INIT_SIM_OBJECT_PARAMS(IntrControl) - -CREATE_SIM_OBJECT(IntrControl) -{ - return new IntrControl(getInstanceName(), cpu); -} - -REGISTER_SIM_OBJECT("IntrControl", IntrControl) diff --git a/sim/intr_control.hh b/sim/intr_control.hh deleted file mode 100644 index 660d6d704..000000000 --- a/sim/intr_control.hh +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __INTR_CONTROL_HH__ -#define __INTR_CONTROL_HH__ - -#include "misc.hh" -#include "base_cpu.hh" -#include "sim_object.hh" - -class IntrControl : public SimObject -{ - public: - BaseCPU *cpu; - IntrControl(const std::string &name, BaseCPU *c); - - void clear(int int_num, int index = 0); - void post(int int_num, int index = 0); -}; - -inline void -IntrControl::post(int int_num, int index) -{ cpu->post_interrupt(int_num, index); } - -inline void -IntrControl::clear(int int_num, int index) -{ cpu->clear_interrupt(int_num, index); } - -#endif // __INTR_CONTROL_HH__ - - - - - - - diff --git a/sim/memtest.cc b/sim/memtest.cc deleted file mode 100644 index 70b6fbf13..000000000 --- a/sim/memtest.cc +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// FIX ME: make trackBlkAddr use blocksize from actual cache, not hard coded - -#include -#include -#include -#include - -#include "memtest.hh" -#include "misc.hh" -#include "sim_events.hh" -#include "main_memory.hh" -#include "base_cache.hh" - -#include "statistics.hh" -#include "sim_stats.hh" - -using namespace std; - -MemTest::MemTest(const string &name, - MemInterface *_cache_interface, - FunctionalMemory *main_mem, - FunctionalMemory *check_mem, - unsigned _memorySize, - unsigned _percentReads, - unsigned _percentUncacheable, - unsigned _maxReads, - unsigned _progressInterval, - Addr _traceAddr) - : BaseCPU(name, 1), - tickEvent(this), - cacheInterface(_cache_interface), - mainMem(main_mem), - checkMem(check_mem), - size(_memorySize), - percentReads(_percentReads), - percentUncacheable(_percentUncacheable), - maxReads(_maxReads), - progressInterval(_progressInterval), - nextProgressMessage(_progressInterval) -{ - vector cmd; - cmd.push_back("/bin/ls"); - vector null_vec; - xc = new ExecContext(this ,0,mainMem,0); - - blockSize = cacheInterface->getBlockSize(); - blockAddrMask = blockSize - 1; - traceBlockAddr = blockAddr(_traceAddr); - - //setup data storage with interesting values - uint8_t *data1 = new uint8_t[size]; - uint8_t *data2 = new uint8_t[size]; - uint8_t *data3 = new uint8_t[size]; - memset(data1, 1, size); - memset(data2, 2, size); - memset(data3, 3, size); - curTick = 0; - - baseAddr1 = 0x100000; - baseAddr2 = 0x400000; - uncacheAddr = 0x800000; - - // set up intial memory contents here - mainMem->prot_write(baseAddr1, data1, size); - checkMem->prot_write(baseAddr1, data1, size); - mainMem->prot_write(baseAddr2, data2, size); - checkMem->prot_write(baseAddr2, data2, size); - mainMem->prot_write(uncacheAddr, data3, size); - checkMem->prot_write(uncacheAddr, data3, size); - - delete [] data1; - delete [] data2; - delete [] data3; - - // set up counters - noResponseCycles = 0; - numReads = 0; - numWrites = 0; - tickEvent.schedule(0); -} - -static void -printData(ostream &os, uint8_t *data, int nbytes) -{ - os << hex << setfill('0'); - // assume little-endian: print bytes from highest address to lowest - for (uint8_t *dp = data + nbytes - 1; dp >= data; --dp) { - os << setw(2) << (unsigned)*dp; - } - os << dec; -} - -void -MemTest::completeRequest(MemReqPtr req, uint8_t *data) -{ - switch (req->cmd) { - case Read: - if (memcmp(req->data, data, req->size) != 0) { - cerr << name() << ": on read of 0x" << hex << req->paddr - << " @ cycle " << dec << curTick - << ", cache returns 0x"; - printData(cerr, req->data, req->size); - cerr << ", expected 0x"; - printData(cerr, data, req->size); - cerr << endl; - fatal(""); - } - - numReads++; - - if (numReads.val() == nextProgressMessage) { - cerr << name() << ": completed " << numReads.val() - << " read accesses @ " << curTick << endl; - nextProgressMessage += progressInterval; - } - - if (numReads.val() == maxReads) { - stringstream stream; - stream << name() << " reached max read count (" << maxReads - << ")" << endl; - - new SimExitEvent(stream.str()); - } - break; - - case Write: - numWrites++; - break; - - - default: - panic("invalid command"); - } - - if (blockAddr(req->paddr) == traceBlockAddr) { - cerr << name() << ": completed " - << (req->cmd.isWrite() ? "write" : "read") << " access of " - << req->size << " bytes at address 0x" - << hex << req->paddr << ", value = 0x"; - printData(cerr, req->data, req->size); - cerr << endl; - } - - noResponseCycles = 0; - delete [] data; -} - - -void -MemTest::regStats() -{ - using namespace Statistics; - - numReads - .name(name() + ".num_reads") - .desc("number of read accesses completed") - ; - - numWrites - .name(name() + ".num_writes") - .desc("number of write accesses completed") - ; - - numCopies - .name(name() + ".num_copies") - .desc("number of copy accesses completed") - ; -} - -void -MemTest::tick() -{ - if (!tickEvent.scheduled()) - tickEvent.schedule(curTick + 1); - - if (++noResponseCycles >= 5000) { - cerr << name() << ": deadlocked at cycle " << curTick << endl; - fatal(""); - } - - if (cacheInterface->isBlocked()) { - return; - } - - //make new request - unsigned cmd = rand() % 100; - unsigned offset1 = random() % size; - unsigned base = random() % 2; - uint64_t data = random(); - unsigned access_size = random() % 4; - unsigned cacheable = rand() % 100; - - MemReqPtr req = new MemReq(); - - if (cacheable < percentUncacheable) { - req->flags |= UNCACHEABLE; - req->paddr = uncacheAddr + offset1; - } else { - req->paddr = ((base) ? baseAddr1 : baseAddr2) + offset1; - } - - req->size = 1 << access_size; - req->data = new uint8_t[req->size]; - req->paddr &= ~(req->size - 1); - req->time = curTick; - req->xc = xc; - - if (cmd < percentReads) { - // read - req->cmd = Read; - uint8_t *result = new uint8_t[8]; - checkMem->access(Read, req->paddr, result, req->size); - if (blockAddr(req->paddr) == traceBlockAddr) { - cerr << name() << ": initiating read of " - << req->size << " bytes from addr 0x" - << hex << req->paddr << " at cycle " - << dec << curTick << endl; - } - - req->completionEvent = new MemCompleteEvent(req, result, this); - cacheInterface->access(req); - } else { - // write - req->cmd = Write; - memcpy(req->data, &data, req->size); - checkMem->access(Write, req->paddr, req->data, req->size); - if (blockAddr(req->paddr) == traceBlockAddr) { - cerr << name() << ": initiating write of " - << req->size << " bytes (value = 0x"; - printData(cerr, req->data, req->size); - cerr << ") to addr 0x" - << hex << req->paddr << " at cycle " - << dec << curTick << endl; - } - req->completionEvent = new MemCompleteEvent(req, NULL, this); - cacheInterface->access(req); - } -} - - -void -MemCompleteEvent::process() -{ - tester->completeRequest(req, data); - delete this; -} - - -const char * -MemCompleteEvent::description() -{ - return "memory access completion"; -} - - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest) - - SimObjectParam cache; - SimObjectParam main_mem; - SimObjectParam check_mem; - Param memory_size; - Param percent_reads; - Param percent_uncacheable; - Param max_reads; - Param progress_interval; - Param trace_addr; - -END_DECLARE_SIM_OBJECT_PARAMS(MemTest) - - -BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest) - - INIT_PARAM(cache, "L1 cache"), - INIT_PARAM(main_mem, "hierarchical memory"), - INIT_PARAM(check_mem, "check memory"), - INIT_PARAM_DFLT(memory_size, "memory size", 65536), - INIT_PARAM_DFLT(percent_reads, "target read percentage", 65), - INIT_PARAM_DFLT(percent_uncacheable, "target uncacheable percentage", 10), - INIT_PARAM_DFLT(max_reads, "number of reads to simulate", 0), - INIT_PARAM_DFLT(progress_interval, - "progress report interval (in accesses)", 1000000), - INIT_PARAM_DFLT(trace_addr, "address to trace", 0) - -END_INIT_SIM_OBJECT_PARAMS(MemTest) - - -CREATE_SIM_OBJECT(MemTest) -{ - return new MemTest(getInstanceName(), cache->getInterface(), main_mem, - check_mem, - memory_size, percent_reads, - percent_uncacheable, max_reads, progress_interval, - trace_addr); -} - -REGISTER_SIM_OBJECT("MemTest", MemTest) diff --git a/sim/memtest.hh b/sim/memtest.hh deleted file mode 100644 index aa652abbd..000000000 --- a/sim/memtest.hh +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __MEMTEST_HH__ -#define __MEMTEST_HH__ - -#include "sim_object.hh" -#include "mem_interface.hh" -#include "functional_memory.hh" -#include "base_cpu.hh" -#include "exec_context.hh" - -#include "statistics.hh" -#include "sim_stats.hh" - -class MemTest : public BaseCPU -{ - public: - - MemTest(const std::string &name, - MemInterface *_cache_interface, - FunctionalMemory *main_mem, - FunctionalMemory *check_mem, - unsigned _memorySize, - unsigned _percentReads, - unsigned _percentUncacheable, - unsigned _maxReads, - unsigned _progressInterval, - Addr _traceAddr); - - // register statistics - virtual void regStats(); - // main simulation loop (one cycle) - void tick(); - - protected: - class TickEvent : public Event - { - private: - MemTest *cpu; - public: - TickEvent(MemTest *c) - : Event(&mainEventQueue, 100), cpu(c) {} - void process() {cpu->tick();} - virtual const char *description() { return "tick event"; } - }; - - TickEvent tickEvent; - - MemInterface *cacheInterface; - FunctionalMemory *mainMem; - FunctionalMemory *checkMem; - ExecContext *xc; - - unsigned size; // size of testing memory region - - unsigned percentReads; // target percentage of read accesses - unsigned percentUncacheable; - - Tick maxReads; // max # of reads to perform (then quit) - - unsigned blockSize; - - Addr blockAddrMask; - - Addr blockAddr(Addr addr) - { - return (addr & ~blockAddrMask); - } - - Addr traceBlockAddr; - - Addr baseAddr1; // fix this to option - Addr baseAddr2; // fix this to option - Addr uncacheAddr; - - unsigned progressInterval; // frequency of progress reports - Tick nextProgressMessage; // access # for next progress report - - Tick noResponseCycles; - - Statistics::Scalar numReads; - Statistics::Scalar numWrites; - Statistics::Scalar numCopies; - - // called by MemCompleteEvent::process() - void completeRequest(MemReqPtr req, uint8_t *data); - - friend class MemCompleteEvent; -}; - - -class MemCompleteEvent : public Event -{ - MemReqPtr req; - uint8_t *data; - MemTest *tester; - - public: - - MemCompleteEvent(MemReqPtr _req, uint8_t *_data, MemTest *_tester) - : Event(&mainEventQueue), - req(_req), data(_data), tester(_tester) - { - } - - void process(); - - virtual const char *description(); -}; - -#endif // __MEMTEST_HH__ - - - diff --git a/sim/op_class.hh b/sim/op_class.hh deleted file mode 100644 index 67ccaabad..000000000 --- a/sim/op_class.hh +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __OP_CLASS_HH__ -#define __OP_CLASS_HH__ - -/** - * @file - * Definition of operation classes. - */ - -/** - * Instruction operation classes. These classes are used for - * assigning instructions to functional units. - */ -enum OpClass { - No_OpClass = 0, /* inst does not use a functional unit */ - IntALU, /* integer ALU */ - IntMULT, /* integer multiplier */ - IntDIV, /* integer divider */ - FloatADD, /* floating point adder/subtractor */ - FloatCMP, /* floating point comparator */ - FloatCVT, /* floating point<->integer converter */ - FloatMULT, /* floating point multiplier */ - FloatDIV, /* floating point divider */ - FloatSQRT, /* floating point square root */ - RdPort, /* memory read port */ - WrPort, /* memory write port */ - LvqPort, /* load value queue read port (redundant threading) */ - IPrefPort, - Num_OpClasses /* total functional unit classes */ -}; - -/** - * Array mapping OpClass enum values to strings. - */ -extern const char *opClassStrings[]; - -#endif // __OP_CLASS_HH__ diff --git a/sim/pc_event.cc b/sim/pc_event.cc deleted file mode 100644 index 4de425199..000000000 --- a/sim/pc_event.cc +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -#include "debug.hh" -#include "exec_context.hh" -#include "pc_event.hh" -#include "trace.hh" -#include "universe.hh" - -#ifdef FULL_SYSTEM -#include "arguments.hh" -#include "pmap.h" -#include "kernel.hh" -#include "memory_control.hh" -#include "cpu.hh" -#include "system.hh" -#include "bpred.hh" -#endif - -using namespace std; - -PCEventQueue::PCEventQueue() -{} - -PCEventQueue::~PCEventQueue() -{} - -bool -PCEventQueue::remove(PCEvent *event) -{ - int removed = 0; - range_t range = equal_range(event); - for (iterator i = range.first; i != range.second; ++i) { - if (*i == event) { - DPRINTF(PCEvent, "PC based event removed at %#x: %s\n", - event->pc(), event->descr()); - pc_map.erase(i); - ++removed; - } - } - - return removed > 0; -} - -bool -PCEventQueue::schedule(PCEvent *event) -{ - pc_map.push_back(event); - sort(pc_map.begin(), pc_map.end(), MapCompare()); - - DPRINTF(PCEvent, "PC based event scheduled for %#x: %s\n", - event->pc(), event->descr()); - - return true; -} - -bool -PCEventQueue::service(ExecContext *xc) -{ - Addr pc = xc->regs.pc; - int serviced = 0; - range_t range = equal_range(pc); - for (iterator i = range.first; i != range.second; ++i) { - // Make sure that the pc wasn't changed as the side effect of - // another event. This for example, prevents two invocations - // of the SkipFuncEvent. Maybe we should have separate PC - // event queues for each processor? - if (pc != xc->regs.pc) - continue; - - DPRINTF(PCEvent, "PC based event serviced at %#x: %s\n", - (*i)->pc(), (*i)->descr()); - - (*i)->process(xc); - ++serviced; - } - - return serviced > 0; -} - -void -PCEventQueue::dump() const -{ - const_iterator i = pc_map.begin(); - const_iterator e = pc_map.end(); - - for (; i != e; ++i) - cprintf("%d: event at %#x: %s\n", curTick, (*i)->pc(), - (*i)->descr()); -} - -PCEventQueue::range_t -PCEventQueue::equal_range(Addr pc) -{ - return std::equal_range(pc_map.begin(), pc_map.end(), pc, MapCompare()); -} - -#ifdef FULL_SYSTEM -void -SkipFuncEvent::process(ExecContext *xc) -{ - Addr newpc = xc->regs.intRegFile[ReturnAddressReg]; - - DPRINTF(PCEvent, "skipping %s: pc=%x, newpc=%x\n", description, - xc->regs.pc, newpc); - - xc->regs.pc = newpc; - xc->regs.npc = xc->regs.pc + sizeof(MachInst); - - BranchPred *bp = xc->cpu->getBranchPred(); - if (bp != NULL) { - bp->popRAS(xc->thread_num); - } -} - -void -BadAddrEvent::process(ExecContext *xc) -{ - // The following gross hack is the equivalent function to the - // annotation for vmunix::badaddr in: - // simos/simulation/apps/tcl/osf/tlaser.tcl - - uint64_t a0 = xc->regs.intRegFile[ArgumentReg0]; - - if (a0 < ALPHA_K0SEG_BASE || a0 >= ALPHA_K1SEG_BASE || - xc->memCtrl->badaddr(ALPHA_K0SEG_TO_PHYS(a0) & PA_IMPL_MASK)) { - - DPRINTF(BADADDR, "badaddr arg=%#x bad\n", a0); - xc->regs.intRegFile[ReturnValueReg] = 0x1; - SkipFuncEvent::process(xc); - } - else - DPRINTF(BADADDR, "badaddr arg=%#x good\n", a0); -} - -void -PrintfEvent::process(ExecContext *xc) -{ - if (DTRACE(Printf)) { - DebugOut() << curTick << ": " << xc->cpu->name() << ": "; - - AlphaArguments args(xc); - Kernel::Printf(args); - } -} - -void -DebugPrintfEvent::process(ExecContext *xc) -{ - if (DTRACE(DebugPrintf)) { - if (!raw) - DebugOut() << curTick << ": " << xc->cpu->name() << ": "; - - AlphaArguments args(xc); - Kernel::Printf(args); - } -} - -void -DumpMbufEvent::process(ExecContext *xc) -{ - if (DTRACE(DebugPrintf)) { - AlphaArguments args(xc); - Kernel::DumpMbuf(args); - } -} -#endif - -BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, bool del) - : PCEvent(q, desc), remove(del) -{ -} - -void -BreakPCEvent::process(ExecContext *xc) -{ - debug_break(); - if (remove) - delete this; -} - -#ifdef FULL_SYSTEM -extern "C" -void -sched_break_pc_sys(System *sys, Addr addr) -{ - PCEvent *event = new BreakPCEvent(&sys->pcEventQueue, "debug break", true); - event->schedule(addr); -} - -extern "C" -void -sched_break_pc(Addr addr) -{ - for (vector::iterator sysi = System::systemList.begin(); - sysi != System::systemList.end(); ++sysi) { - sched_break_pc_sys(*sysi, addr); - } - -} -#endif diff --git a/sim/pc_event.hh b/sim/pc_event.hh deleted file mode 100644 index 24442f5f4..000000000 --- a/sim/pc_event.hh +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __PC_EVENT_HH__ -#define __PC_EVENT_HH__ - -#include - -#include "mem_req.hh" - -class ExecContext; -class PCEventQueue; - -class PCEvent -{ - protected: - static const Addr badpc = MemReq::inval_addr; - - protected: - std::string description; - PCEventQueue *queue; - Addr evpc; - - public: - PCEvent() : queue(0), evpc(badpc) { } - - PCEvent(const std::string &desc) - : description(desc), queue(0), evpc(badpc) { } - - PCEvent(PCEventQueue *q, Addr pc = badpc) : queue(q), evpc(pc) { } - - PCEvent(PCEventQueue *q, const std::string &desc, Addr pc = badpc) - : description(desc), queue(q), evpc(pc) { } - - virtual ~PCEvent() { if (queue) remove(); } - - std::string descr() const { return description; } - Addr pc() const { return evpc; } - - bool remove(); - bool schedule(); - bool schedule(Addr pc); - bool schedule(PCEventQueue *q, Addr pc); - virtual void process(ExecContext *xc) = 0; -}; - -class PCEventQueue -{ - protected: - typedef PCEvent * record_t; - class MapCompare { - public: - bool operator()(const record_t &l, const record_t &r) const { - return l->pc() < r->pc(); - } - bool operator()(const record_t &l, Addr pc) const { - return l->pc() < pc; - } - bool operator()(Addr pc, const record_t &r) const { - return pc < r->pc(); - } - }; - typedef std::vector map_t; - - public: - typedef map_t::iterator iterator; - typedef map_t::const_iterator const_iterator; - - protected: - typedef std::pair range_t; - typedef std::pair const_range_t; - - protected: - map_t pc_map; - - public: - PCEventQueue(); - ~PCEventQueue(); - - bool remove(PCEvent *event); - bool schedule(PCEvent *event); - bool service(ExecContext *xc); - - range_t equal_range(Addr pc); - range_t equal_range(PCEvent *event) { return equal_range(event->pc()); } - - void dump() const; -}; - -inline bool -PCEvent::remove() -{ - if (!queue) - panic("cannot remove an uninitialized event;"); - - return queue->remove(this); -} - -inline bool -PCEvent::schedule() -{ - if (!queue || evpc == badpc) - panic("cannot schedule an uninitialized event;"); - - return queue->schedule(this); -} - -inline bool -PCEvent::schedule(Addr pc) -{ - if (evpc != badpc) - panic("cannot switch PC"); - evpc = pc; - - return schedule(); -} - -inline bool -PCEvent::schedule(PCEventQueue *q, Addr pc) -{ - if (queue) - panic("cannot switch event queues"); - - if (evpc != badpc) - panic("cannot switch addresses"); - - queue = q; - evpc = pc; - - return schedule(); -} - - -#ifdef FULL_SYSTEM -class SkipFuncEvent : public PCEvent -{ - public: - SkipFuncEvent(PCEventQueue *q, const std::string &desc) - : PCEvent(q, desc) {} - virtual void process(ExecContext *xc); -}; - -class BadAddrEvent : public SkipFuncEvent -{ - public: - BadAddrEvent(PCEventQueue *q, const std::string &desc) - : SkipFuncEvent(q, desc) {} - virtual void process(ExecContext *xc); -}; - -class PrintfEvent : public PCEvent -{ - public: - PrintfEvent(PCEventQueue *q, const std::string &desc) - : PCEvent(q, desc) {} - virtual void process(ExecContext *xc); -}; - -class DebugPrintfEvent : public PCEvent -{ - private: - bool raw; - - public: - DebugPrintfEvent(PCEventQueue *q, const std::string &desc, bool r = false) - : PCEvent(q, desc), raw(r) {} - virtual void process(ExecContext *xc); -}; - -class DumpMbufEvent : public PCEvent -{ - public: - DumpMbufEvent(PCEventQueue *q, const std::string &desc) - : PCEvent(q, desc) {} - virtual void process(ExecContext *xc); -}; -#endif - -class BreakPCEvent : public PCEvent -{ - protected: - bool remove; - - public: - BreakPCEvent(PCEventQueue *q, const std::string &desc, bool del = false); - virtual void process(ExecContext *xc); -}; - - -#endif // __PC_EVENT_HH__ diff --git a/sim/predictor.hh b/sim/predictor.hh deleted file mode 100644 index 7c446f26c..000000000 --- a/sim/predictor.hh +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// -// Abstract base class for a generic predictor -// -// - -#ifndef __PREDICTOR_HH__ -#define __PREDICTOR_HH__ - -struct stat_sdb_t; - -class GenericPredictor { - - public: - virtual void clear() = 0; - - virtual unsigned predict(unsigned long _index) = 0; - virtual unsigned predict(unsigned long _index, unsigned &pdata) = 0; - - virtual unsigned peek(unsigned long _index) = 0; - - virtual void record(unsigned long _index, unsigned _actual_value, - unsigned _pred_value) = 0; - virtual void record(unsigned long _index, unsigned _actual_value, - unsigned _pred_value, unsigned _pdata) = 0; - - virtual unsigned value(unsigned long _index) = 0; - - virtual void regStats() = 0; - virtual void regFormulas() = 0; - - virtual ~GenericPredictor() {}; -}; - -#endif // __PREDICTOR_HH__ diff --git a/sim/sat_counter.cc b/sim/sat_counter.cc deleted file mode 100644 index dc365f0f3..000000000 --- a/sim/sat_counter.cc +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "sat_counter.hh" - -#include "statistics.hh" -#include "sim_stats.hh" - - -using namespace std; - - -SaturatingCounterPred::SaturatingCounterPred(string p_name, - string z_name, - string o_name, - unsigned _index_bits, - unsigned _counter_bits, - unsigned _zero_change, - unsigned _one_change, - unsigned _thresh, - unsigned _init_value) -{ - pred_name = p_name; - zero_name = z_name; - one_name = o_name; - - index_bits = _index_bits; - counter_bits = _counter_bits; - zero_change = _zero_change; - one_change = _one_change; - thresh = _thresh; - init_value = _init_value; - - max_index = (1 << index_bits) - 1; - max_value = (1 << counter_bits) - 1; - - table = new unsigned[max_index + 1]; - - // Initialize with the right parameters & clear the counter - for (int i = 0; i <= max_index; ++i) - table[i] = init_value; -} - -void SaturatingCounterPred::regStats() -{ - using namespace Statistics; - stringstream name, description; - - // - // Number of predictions - // - name << pred_name << ":" << zero_name << ":preds"; - description << "number of predictions of " << zero_name; - predicted_zero - .name(name.str()) - .desc(description.str()) - ; - description.str(""); - name.str(""); - - name << pred_name << ":" << one_name << ":preds"; - description << "number of predictions of " << one_name; - predicted_one - .name(name.str()) - .desc(description.str()) - ; - description.str(""); - name.str(""); - - // - // Count the number of correct predictions - // - name << pred_name << ":" << zero_name << ":corr_preds"; - description << "number of correct " << zero_name << " preds"; - correct_pred_zero - .name(name.str()) - .desc(description.str()) - ; - description.str(""); - name.str(""); - - name << pred_name << ":" << one_name << ":corr_preds"; - description << "number of correct " << one_name << " preds"; - correct_pred_one - .name(name.str()) - .desc(description.str()) - ; - description.str(""); - name.str(""); - - // - // Number of predictor updates - // - name << pred_name << ":" << zero_name << ":updates"; - description << "number of actual " << zero_name << "s"; - record_zero - .name(name.str()) - .desc(description.str()) - ; - description.str(""); - name.str(""); - - name << pred_name << ":" << one_name << ":updates"; - description << "number of actual " << one_name << "s"; - record_one - .name(name.str()) - .desc(description.str()) - ; - description.str(""); - name.str(""); -} - -void SaturatingCounterPred::regFormulas() -{ - using namespace Statistics; - stringstream name, description; - - // - // Number of predictions - // - name << pred_name << ":predictions"; - preds_total - .name(name.str()) - .desc("total number of predictions made") - ; - preds_total = predicted_zero + predicted_one; - name.str(""); - - // - // Fraction of all predictions that are one or zero - // - name << pred_name << ":" << zero_name << ":pred_frac"; - description << "fraction of all preds that were " << zero_name; - pred_frac_zero - .name(name.str()) - .desc(description.str()) - ; - pred_frac_zero = 100 * predicted_zero / preds_total; - description.str(""); - name.str(""); - - name << pred_name << ":" << one_name << ":pred_frac"; - description << "fraction of all preds that were " << one_name; - pred_frac_one - .name(name.str()) - .desc(description.str()) - ; - pred_frac_one = 100 * predicted_one / preds_total; - description.str(""); - name.str(""); - - - // - // Count the number of correct predictions - // - name << pred_name << ":correct_preds"; - correct_total - .name(name.str()) - .desc("total correct predictions made") - ; - correct_total = correct_pred_one + correct_pred_zero; - name.str(""); - - // - // Number of predictor updates - // - name << pred_name << ":updates"; - updates_total - .name(name.str()) - .desc("total number of updates") - ; - updates_total = record_zero + record_one; - name.str(""); - - // - // Prediction accuracy rates - // - name << pred_name << ":pred_rate"; - pred_rate - .name(name.str()) - .desc("correct fraction of all preds") - ; - pred_rate = correct_total / updates_total; - name.str(""); - - name << pred_name << ":" << zero_name << ":pred_rate"; - description << "fraction of " << zero_name << " preds that were correct"; - frac_correct_zero - .name(name.str()) - .desc(description.str()) - ; - frac_correct_zero = 100 * correct_pred_zero / - (correct_pred_zero + record_one - correct_pred_one); - description.str(""); - name.str(""); - - name << pred_name << ":" << one_name << ":pred_rate"; - description << "fraction of " << one_name << " preds that were correct"; - frac_correct_one - .name(name.str()) - .desc(description.str()) - ; - frac_correct_one = 100 * correct_pred_one / - (correct_pred_one + record_zero - correct_pred_zero); - description.str(""); - name.str(""); - - // - // Coverage - // - name << pred_name << ":" << zero_name << ":coverage"; - description << "fraction of " << zero_name - << "s that were predicted correctly"; - coverage_zero - .name(name.str()) - .desc(description.str()) - ; - coverage_zero = 100 * correct_pred_zero / record_zero; - description.str(""); - name.str(""); - - name << pred_name << ":" << one_name << ":coverage"; - description << "fraction of " << one_name - << "s that were predicted correctly"; - coverage_one - .name(name.str()) - .desc(description.str()) - ; - coverage_one = 100 * correct_pred_one / record_one; - description.str(""); - name.str(""); -} - - - - - - - - - - diff --git a/sim/sat_counter.hh b/sim/sat_counter.hh deleted file mode 100644 index 18eab3574..000000000 --- a/sim/sat_counter.hh +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SAT_COUNTER_HH__ -#define __SAT_COUNTER_HH__ - -#include - -#include "predictor.hh" - -#include "statistics.hh" -#include "sim_stats.hh" - -struct stat_sdb_t; - -// -// -// A simple saturating counter predictor -// -// -class SaturatingCounterPred : public GenericPredictor -{ - private: - std::string pred_name; - std::string zero_name; - std::string one_name; - - unsigned index_bits; - unsigned counter_bits; - unsigned zero_change; - unsigned one_change; - unsigned thresh; - unsigned init_value; - - unsigned max_value; // maximum counter value - - unsigned long max_index; // also the index mask value - unsigned *table; - - // Statistics - Statistics::Scalar<> predicted_one; // Total predictions of one, preds_one - Statistics::Scalar<> predicted_zero; // Total predictions of zero, preds_zero - Statistics::Scalar<> correct_pred_one; // Total correct predictions of one, correct_one - Statistics::Scalar<> correct_pred_zero; // Total correct predictions of zero, correct_zero - - Statistics::Scalar<> record_zero; //updates_zero - Statistics::Scalar<> record_one; //updates_one - - Statistics::Formula preds_total; - Statistics::Formula pred_frac_zero; - Statistics::Formula pred_frac_one; - Statistics::Formula correct_total; - Statistics::Formula updates_total; - Statistics::Formula pred_rate; - Statistics::Formula frac_correct_zero; - Statistics::Formula frac_correct_one; - Statistics::Formula coverage_zero; - Statistics::Formula coverage_one; - - private: - bool pred_one(unsigned &counter) { return counter > thresh; } - bool pred_zero(unsigned &counter) { return counter <= thresh; } - - void update_one(unsigned &counter) { - - if (one_change) - counter += one_change; - else - counter = 0; - - // check for wrap - if (counter > max_value) - counter = max_value; - } - - void update_zero(unsigned &counter) { - if (zero_change) { - // check for wrap - if (counter < zero_change) - counter = 0; - else - counter -= zero_change; - } else - counter = 0; - } - - - public: - - SaturatingCounterPred(std::string p_name, - std::string z_name, std::string o_name, - unsigned _index_bits, unsigned _counter_bits = 2, - unsigned _zero_change = 1, unsigned _one_change = 1, - unsigned _thresh = 1, unsigned _init_value = 0); - - void clear() { - for (int i = 0; i <= max_index; ++i) - table[i] = init_value; - } - - // Record the ACTUAL result... and indicate whether the prediction - // corresponding to this event was correct - void record(unsigned long _index, unsigned _val, unsigned _predicted, - unsigned _pdata) - { - record(_index, _val, _predicted); - } - - void record(unsigned long _index, unsigned _val, unsigned _predicted) { - unsigned long index = _index & max_index; - - if (_val) { - update_one(table[index]); - ++record_one; - - if (_predicted) - ++correct_pred_one; - } else { - update_zero(table[index]); - ++record_zero; - - if (!_predicted) - ++correct_pred_zero; - } - } - - unsigned value(unsigned long _index) { - unsigned long index = _index & max_index; - - return table[index]; - } - - - unsigned predict(unsigned long _index, unsigned &pdata) { - return predict(_index); - } - - unsigned predict(unsigned long _index) { - unsigned long index = _index & max_index; - - if (pred_one(table[index])) { - ++predicted_one; - return 1; - } - - ++predicted_zero; - return 0; - } - - // No internal state is changed here - unsigned peek(unsigned long _index) { - unsigned long index = _index & max_index; - - if (pred_one(table[index])) - return 1; - - return 0; - } - - - //======================================================= - void regStats(); - void regFormulas(); -}; - - -#endif // __SAT_COUNTER_HH__ diff --git a/sim/simple_cpu.cc b/sim/simple_cpu.cc deleted file mode 100644 index 41a612318..000000000 --- a/sim/simple_cpu.cc +++ /dev/null @@ -1,746 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "host.hh" -#include "cprintf.hh" -#include "misc.hh" -#include "smt.hh" - -#include "annotation.hh" -#include "exec_context.hh" -#include "base_cpu.hh" -#include "debug.hh" -#include "simple_cpu.hh" -#include "inifile.hh" -#include "mem_interface.hh" -#include "base_mem.hh" -#include "static_inst.hh" - -#ifdef FULL_SYSTEM -#include "memory_control.hh" -#include "physical_memory.hh" -#include "alpha_memory.hh" -#include "system.hh" -#else // !FULL_SYSTEM -#include "functional_memory.hh" -#include "prog.hh" -#include "eio.hh" -#endif // FULL_SYSTEM - -#include "exetrace.hh" -#include "trace.hh" -#include "sim_events.hh" -#include "pollevent.hh" -#include "sim_object.hh" -#include "sim_stats.hh" - -#include "range.hh" -#include "symtab.hh" - -#ifdef FULL_SYSTEM -#include "vtophys.hh" -#include "pciareg.h" -#include "remote_gdb.hh" -#include "alpha_access.h" -#endif - - -using namespace std; - -SimpleCPU::CacheCompletionEvent::CacheCompletionEvent(SimpleCPU *_cpu) - : Event(&mainEventQueue), - cpu(_cpu) -{ -} - -void SimpleCPU::CacheCompletionEvent::process() -{ - cpu->processCacheCompletion(); -} - -const char * -SimpleCPU::CacheCompletionEvent::description() -{ - return "cache completion event"; -} - -#ifdef FULL_SYSTEM -SimpleCPU::SimpleCPU(const string &_name, - System *_system, - Counter max_insts_any_thread, - Counter max_insts_all_threads, - AlphaItb *itb, AlphaDtb *dtb, - FunctionalMemory *mem, - MemInterface *icache_interface, - MemInterface *dcache_interface, - int cpu_id, Tick freq) - : BaseCPU(_name, /* number_of_threads */ 1, - max_insts_any_thread, max_insts_all_threads, - _system, cpu_id, freq), -#else -SimpleCPU::SimpleCPU(const string &_name, Process *_process, - Counter max_insts_any_thread, - Counter max_insts_all_threads, - MemInterface *icache_interface, - MemInterface *dcache_interface) - : BaseCPU(_name, /* number_of_threads */ 1, - max_insts_any_thread, max_insts_all_threads), -#endif - tickEvent(this), xc(NULL), cacheCompletionEvent(this) -{ -#ifdef FULL_SYSTEM - xc = new ExecContext(this, 0, system, itb, dtb, mem, cpu_id); - - _status = Running; - if (cpu_id != 0) { - - xc->setStatus(ExecContext::Unallocated); - - //Open a GDB debug session on port (7000 + the cpu_id) - (new GDBListener(new RemoteGDB(system, xc), 7000 + cpu_id))->listen(); - - AlphaISA::init(system->physmem, &xc->regs); - - fault = Reset_Fault; - - IntReg *ipr = xc->regs.ipr; - ipr[TheISA::IPR_MCSR] = 0x6; - - AlphaISA::swap_palshadow(&xc->regs, true); - - xc->regs.pc = - ipr[TheISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault]; - xc->regs.npc = xc->regs.pc + sizeof(MachInst); - - _status = Idle; - } - else { - system->initBootContext(xc); - - // Reset the system - // - AlphaISA::init(system->physmem, &xc->regs); - - fault = Reset_Fault; - - IntReg *ipr = xc->regs.ipr; - ipr[TheISA::IPR_MCSR] = 0x6; - - AlphaISA::swap_palshadow(&xc->regs, true); - - xc->regs.pc = ipr[TheISA::IPR_PAL_BASE] + AlphaISA::fault_addr[fault]; - xc->regs.npc = xc->regs.pc + sizeof(MachInst); - - _status = Running; - tickEvent.schedule(0); - } - -#else - xc = new ExecContext(this, /* thread_num */ 0, _process, /* asid */ 0); - fault = No_Fault; - if (xc->status() == ExecContext::Active) { - _status = Running; - tickEvent.schedule(0); - } else - _status = Idle; -#endif // !FULL_SYSTEM - - icacheInterface = icache_interface; - dcacheInterface = dcache_interface; - - memReq = new MemReq(); - memReq->xc = xc; - memReq->asid = 0; - - numInst = 0; - last_idle = 0; - lastIcacheStall = 0; - lastDcacheStall = 0; - - contexts.push_back(xc); -} - -SimpleCPU::~SimpleCPU() -{ -} - -void -SimpleCPU::regStats() -{ - BaseCPU::regStats(); - - numInsts - .name(name() + ".num_insts") - .desc("Number of instructions executed") - ; - - numMemRefs - .name(name() + ".num_refs") - .desc("Number of memory references") - ; - - idleCycles - .name(name() + ".idle_cycles") - .desc("Number of idle cycles") - ; - - idleFraction - .name(name() + ".idle_fraction") - .desc("Percentage of idle cycles") - ; - - icacheStallCycles - .name(name() + ".icache_stall_cycles") - .desc("ICache total stall cycles") - .prereq(icacheStallCycles) - ; - - dcacheStallCycles - .name(name() + ".dcache_stall_cycles") - .desc("DCache total stall cycles") - .prereq(dcacheStallCycles) - ; - - idleFraction = idleCycles / simTicks; - - numInsts = Statistics::scalar(numInst); - simInsts += numInsts; -} - -void -SimpleCPU::serialize() -{ - nameOut(); - -#ifdef FULL_SYSTEM -#if 0 - // do we need this anymore?? egh - childOut("itb", xc->itb); - childOut("dtb", xc->dtb); - childOut("physmem", physmem); -#endif -#endif - - for (int i = 0; i < NumIntRegs; i++) { - stringstream buf; - ccprintf(buf, "R%02d", i); - paramOut(buf.str(), xc->regs.intRegFile[i]); - } - for (int i = 0; i < NumFloatRegs; i++) { - stringstream buf; - ccprintf(buf, "F%02d", i); - paramOut(buf.str(), xc->regs.floatRegFile.d[i]); - } - // CPUTraitsType::serializeSpecialRegs(getProxy(), xc->regs); -} - -void -SimpleCPU::unserialize(IniFile &db, const string &category, ConfigNode *node) -{ - string data; - - for (int i = 0; i < NumIntRegs; i++) { - stringstream buf; - ccprintf(buf, "R%02d", i); - db.findDefault(category, buf.str(), data); - to_number(data,xc->regs.intRegFile[i]); - } - for (int i = 0; i < NumFloatRegs; i++) { - stringstream buf; - ccprintf(buf, "F%02d", i); - db.findDefault(category, buf.str(), data); - xc->regs.floatRegFile.d[i] = strtod(data.c_str(),NULL); - } - - // Read in Special registers - - // CPUTraitsType::unserializeSpecialRegs(db,category,node,xc->regs); -} - -void -change_thread_state(int thread_number, int activate, int priority) -{ -} - -// precise architected memory state accessor macros -template -Fault -SimpleCPU::read(Addr addr, T& data, unsigned flags) -{ - memReq->reset(addr, sizeof(T), flags); - - // translate to physical address - Fault fault = xc->translateDataReadReq(memReq); - - // do functional access - if (fault == No_Fault) - fault = xc->read(memReq, data); - - if (traceData) { - traceData->setAddr(addr); - if (fault == No_Fault) - traceData->setData(data); - } - - // if we have a cache, do cache access too - if (fault == No_Fault && dcacheInterface) { - memReq->cmd = Read; - memReq->completionEvent = NULL; - memReq->time = curTick; - memReq->flags &= ~UNCACHEABLE; - MemAccessResult result = dcacheInterface->access(memReq); - - // Ugly hack to get an event scheduled *only* if the access is - // a miss. We really should add first-class support for this - // at some point. - if (result != MA_HIT && dcacheInterface->doEvents) { - memReq->completionEvent = &cacheCompletionEvent; - setStatus(DcacheMissStall); - } - } - - return fault; -} - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -template -Fault -SimpleCPU::read(Addr addr, uint64_t& data, unsigned flags); - -template -Fault -SimpleCPU::read(Addr addr, uint32_t& data, unsigned flags); - -template -Fault -SimpleCPU::read(Addr addr, uint16_t& data, unsigned flags); - -template -Fault -SimpleCPU::read(Addr addr, uint8_t& data, unsigned flags); - -#endif //DOXYGEN_SHOULD_SKIP_THIS - -template<> -Fault -SimpleCPU::read(Addr addr, double& data, unsigned flags) -{ - return read(addr, *(uint64_t*)&data, flags); -} - -template<> -Fault -SimpleCPU::read(Addr addr, float& data, unsigned flags) -{ - return read(addr, *(uint32_t*)&data, flags); -} - - -template<> -Fault -SimpleCPU::read(Addr addr, int32_t& data, unsigned flags) -{ - return read(addr, (uint32_t&)data, flags); -} - - -template -Fault -SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) -{ - if (traceData) { - traceData->setAddr(addr); - traceData->setData(data); - } - - memReq->reset(addr, sizeof(T), flags); - - // translate to physical address - Fault fault = xc->translateDataWriteReq(memReq); - - // do functional access - if (fault == No_Fault) - fault = xc->write(memReq, data); - - if (fault == No_Fault && dcacheInterface) { - memReq->cmd = Write; - memReq->data = (uint8_t *)&data; - memReq->completionEvent = NULL; - memReq->time = curTick; - memReq->flags &= ~UNCACHEABLE; - MemAccessResult result = dcacheInterface->access(memReq); - - // Ugly hack to get an event scheduled *only* if the access is - // a miss. We really should add first-class support for this - // at some point. - if (result != MA_HIT && dcacheInterface->doEvents) { - memReq->completionEvent = &cacheCompletionEvent; - setStatus(DcacheMissStall); - } - } - - if (res && (fault == No_Fault)) - *res = memReq->result; - - return fault; -} - - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -template -Fault -SimpleCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); - -template -Fault -SimpleCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); - -template -Fault -SimpleCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); - -template -Fault -SimpleCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); - -#endif //DOXYGEN_SHOULD_SKIP_THIS - -template<> -Fault -SimpleCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) -{ - return write(*(uint64_t*)&data, addr, flags, res); -} - -template<> -Fault -SimpleCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) -{ - return write(*(uint32_t*)&data, addr, flags, res); -} - - -template<> -Fault -SimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) -{ - return write((uint32_t)data, addr, flags, res); -} - - -#ifdef FULL_SYSTEM -Addr -SimpleCPU::dbg_vtophys(Addr addr) -{ - return vtophys(xc, addr); -} -#endif // FULL_SYSTEM - -Tick save_cycle = 0; - - -void -SimpleCPU::processCacheCompletion() -{ - switch (status()) { - case IcacheMissStall: - icacheStallCycles += curTick - lastIcacheStall; - setStatus(IcacheMissComplete); - break; - case DcacheMissStall: - dcacheStallCycles += curTick - lastDcacheStall; - setStatus(Running); - break; - default: - panic("SimpleCPU::processCacheCompletion: bad state"); - break; - } -} - -#ifdef FULL_SYSTEM -void -SimpleCPU::post_interrupt(int int_num, int index) -{ - BaseCPU::post_interrupt(int_num, index); - - if (xc->status() == ExecContext::Suspended) { - DPRINTF(IPI,"Suspended Processor awoke\n"); - xc->setStatus(ExecContext::Active); - Annotate::Resume(xc); - } -} -#endif // FULL_SYSTEM - -/* start simulation, program loaded, processor precise state initialized */ -void -SimpleCPU::tick() -{ - traceData = NULL; - -#ifdef FULL_SYSTEM - if (fault == No_Fault && AlphaISA::check_interrupts && - xc->cpu->check_interrupts() && - !PC_PAL(xc->regs.pc) && - status() != IcacheMissComplete) { - int ipl = 0; - int summary = 0; - AlphaISA::check_interrupts = 0; - IntReg *ipr = xc->regs.ipr; - - if (xc->regs.ipr[TheISA::IPR_SIRR]) { - for (int i = TheISA::INTLEVEL_SOFTWARE_MIN; - i < TheISA::INTLEVEL_SOFTWARE_MAX; i++) { - if (ipr[TheISA::IPR_SIRR] & (ULL(1) << i)) { - // See table 4-19 of 21164 hardware reference - ipl = (i - TheISA::INTLEVEL_SOFTWARE_MIN) + 1; - summary |= (ULL(1) << i); - } - } - } - - uint64_t interrupts = xc->cpu->intr_status(); - for(int i = TheISA::INTLEVEL_EXTERNAL_MIN; - i < TheISA::INTLEVEL_EXTERNAL_MAX; i++) { - if (interrupts & (ULL(1) << i)) { - // See table 4-19 of 21164 hardware reference - ipl = i; - summary |= (ULL(1) << i); - } - } - - if (ipr[TheISA::IPR_ASTRR]) - panic("asynchronous traps not implemented\n"); - - if (ipl && ipl > xc->regs.ipr[TheISA::IPR_IPLR]) { - ipr[TheISA::IPR_ISR] = summary; - ipr[TheISA::IPR_INTID] = ipl; - xc->ev5_trap(Interrupt_Fault); - - DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n", - ipr[TheISA::IPR_IPLR], ipl, summary); - } - } -#endif - - // maintain $r0 semantics - xc->regs.intRegFile[ZeroReg] = 0; -#ifdef TARGET_ALPHA - xc->regs.floatRegFile.d[ZeroReg] = 0.0; -#endif // TARGET_ALPHA - - if (status() == IcacheMissComplete) { - // We've already fetched an instruction and were stalled on an - // I-cache miss. No need to fetch it again. - - setStatus(Running); - } - else { - // Try to fetch an instruction - - // set up memory request for instruction fetch -#ifdef FULL_SYSTEM -#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 -#else -#define IFETCH_FLAGS(pc) 0 -#endif - - memReq->cmd = Read; - memReq->reset(xc->regs.pc & ~3, sizeof(uint32_t), - IFETCH_FLAGS(xc->regs.pc)); - - fault = xc->translateInstReq(memReq); - - if (fault == No_Fault) - fault = xc->mem->read(memReq, inst); - - if (icacheInterface && fault == No_Fault) { - memReq->completionEvent = NULL; - - memReq->time = curTick; - memReq->flags &= ~UNCACHEABLE; - MemAccessResult result = icacheInterface->access(memReq); - - // Ugly hack to get an event scheduled *only* if the access is - // a miss. We really should add first-class support for this - // at some point. - if (result != MA_HIT && icacheInterface->doEvents) { - memReq->completionEvent = &cacheCompletionEvent; - setStatus(IcacheMissStall); - return; - } - } - } - - // If we've got a valid instruction (i.e., no fault on instruction - // fetch), then execute it. - if (fault == No_Fault) { - - // keep an instruction count - numInst++; - - // check for instruction-count-based events - comInsnEventQueue[0]->serviceEvents(numInst); - - // decode the instruction - StaticInstPtr si(inst); - - traceData = Trace::getInstRecord(curTick, xc, this, si, - xc->regs.pc); - -#ifdef FULL_SYSTEM - xc->regs.opcode = (inst >> 26) & 0x3f; - xc->regs.ra = (inst >> 21) & 0x1f; -#endif // FULL_SYSTEM - - xc->func_exe_insn++; - - fault = si->execute(this, xc, traceData); - - if (si->isMemRef()) { - numMemRefs++; - } - - if (traceData) - traceData->finalize(); - - } // if (fault == No_Fault) - - if (fault != No_Fault) { -#ifdef FULL_SYSTEM - xc->ev5_trap(fault); -#else // !FULL_SYSTEM - fatal("fault (%d) detected @ PC 0x%08p", fault, xc->regs.pc); -#endif // FULL_SYSTEM - } - else { - // go to the next instruction - xc->regs.pc = xc->regs.npc; - xc->regs.npc += sizeof(MachInst); - } - -#ifdef FULL_SYSTEM - Addr oldpc; - do { - oldpc = xc->regs.pc; - system->pcEventQueue.service(xc); - } while (oldpc != xc->regs.pc); -#endif - - assert(status() == Running || - status() == Idle || - status() == DcacheMissStall); - - if (status() == Running && !tickEvent.scheduled()) - tickEvent.schedule(curTick + 1); -} - - -//////////////////////////////////////////////////////////////////////// -// -// SimpleCPU Simulation Object -// -BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) - - Param max_insts_any_thread; - Param max_insts_all_threads; - -#ifdef FULL_SYSTEM - SimObjectParam itb; - SimObjectParam dtb; - SimObjectParam mem; - SimObjectParam system; - Param cpu_id; - Param mult; -#else - SimObjectParam workload; -#endif // FULL_SYSTEM - - SimObjectParam icache; - SimObjectParam dcache; - -END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU) - -BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU) - - INIT_PARAM_DFLT(max_insts_any_thread, - "terminate when any thread reaches this insn count", - 0), - INIT_PARAM_DFLT(max_insts_all_threads, - "terminate when all threads have reached this insn count", - 0), - -#ifdef FULL_SYSTEM - INIT_PARAM(itb, "Instruction TLB"), - INIT_PARAM(dtb, "Data TLB"), - INIT_PARAM(mem, "memory"), - INIT_PARAM(system, "system object"), - INIT_PARAM_DFLT(cpu_id, "CPU identification number", 0), - INIT_PARAM_DFLT(mult, "system clock multiplier", 1), -#else - INIT_PARAM(workload, "processes to run"), -#endif // FULL_SYSTEM - - INIT_PARAM_DFLT(icache, "L1 instruction cache object", NULL), - INIT_PARAM_DFLT(dcache, "L1 data cache object", NULL) - -END_INIT_SIM_OBJECT_PARAMS(SimpleCPU) - - -CREATE_SIM_OBJECT(SimpleCPU) -{ -#ifdef FULL_SYSTEM - if (mult != 1) - panic("processor clock multiplier must be 1\n"); - - return new SimpleCPU(getInstanceName(), system, - max_insts_any_thread, max_insts_all_threads, - itb, dtb, mem, - (icache) ? icache->getInterface() : NULL, - (dcache) ? dcache->getInterface() : NULL, - cpu_id, ticksPerSecond * mult); -#else - - return new SimpleCPU(getInstanceName(), workload, - max_insts_any_thread, max_insts_all_threads, - icache->getInterface(), dcache->getInterface()); - -#endif // FULL_SYSTEM -} - -REGISTER_SIM_OBJECT("SimpleCPU", SimpleCPU) diff --git a/sim/simple_cpu.hh b/sim/simple_cpu.hh deleted file mode 100644 index c5671eb6f..000000000 --- a/sim/simple_cpu.hh +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __SIMPLE_CPU_HH__ -#define __SIMPLE_CPU_HH__ - -#include "base_cpu.hh" -#include "eventq.hh" -#include "symtab.hh" -#include "pc_event.hh" -#include "statistics.hh" - - -// forward declarations -#ifdef FULL_SYSTEM -class Processor; -class Kernel; -class AlphaItb; -class AlphaDtb; -class PhysicalMemory; - -class RemoteGDB; -class GDBListener; -#endif // FULL_SYSTEM - -class MemInterface; -class IniFile; - -namespace Trace { - class InstRecord; -} - -class SimpleCPU : public BaseCPU -{ - public: - // main simulation loop (one cycle) - void tick(); - - private: - class TickEvent : public Event - { - private: - SimpleCPU *cpu; - - public: - TickEvent(SimpleCPU *c) - : Event(&mainEventQueue, 100), cpu(c) { } - void process() { cpu->tick(); } - virtual const char *description() { return "tick event"; } - }; - - TickEvent tickEvent; - - private: - Trace::InstRecord *traceData; - template - void trace_data(T data) { - if (traceData) { - traceData->setData(data); - } - }; - - public: - // - enum Status { - Running, - Idle, - IcacheMissStall, - IcacheMissComplete, - DcacheMissStall - }; - - private: - Status _status; - - public: - void post_interrupt(int int_num, int index); - - void zero_fill_64(Addr addr) { - static int warned = 0; - if (!warned) { - warn ("WH64 is not implemented"); - warned = 1; - } - }; - -#ifdef FULL_SYSTEM - - SimpleCPU(const std::string &_name, - System *_system, - Counter max_insts_any_thread, Counter max_insts_all_threads, - AlphaItb *itb, AlphaDtb *dtb, FunctionalMemory *mem, - MemInterface *icache_interface, MemInterface *dcache_interface, - int cpu_id, Tick freq); - -#else - - SimpleCPU(const std::string &_name, Process *_process, - Counter max_insts_any_thread, - Counter max_insts_all_threads, - MemInterface *icache_interface, MemInterface *dcache_interface); - -#endif - - virtual ~SimpleCPU(); - - // execution context - ExecContext *xc; - -#ifdef FULL_SYSTEM - Addr dbg_vtophys(Addr addr); - - bool interval_stats; -#endif - - // L1 instruction cache - MemInterface *icacheInterface; - - // L1 data cache - MemInterface *dcacheInterface; - - // current instruction - MachInst inst; - - // current fault status - Fault fault; - - // Refcounted pointer to the one memory request. - MemReqPtr memReq; - - class CacheCompletionEvent : public Event - { - private: - SimpleCPU *cpu; - - public: - CacheCompletionEvent(SimpleCPU *_cpu); - - virtual void process(); - virtual const char *description(); - }; - - CacheCompletionEvent cacheCompletionEvent; - - Status status() const { return _status; } - virtual void execCtxStatusChg() { - if (xc) { - if (xc->status() == ExecContext::Active) - setStatus(Running); - else - setStatus(Idle); - } - } - - void setStatus(Status new_status) { - Status old_status = status(); - _status = new_status; - - switch (status()) { - case IcacheMissStall: - assert(old_status == Running); - lastIcacheStall = curTick; - if (tickEvent.scheduled()) - tickEvent.squash(); - break; - - case IcacheMissComplete: - assert(old_status == IcacheMissStall); - if (tickEvent.squashed()) - tickEvent.reschedule(curTick + 1); - else if (!tickEvent.scheduled()) - tickEvent.schedule(curTick + 1); - break; - - case DcacheMissStall: - assert(old_status == Running); - lastDcacheStall = curTick; - if (tickEvent.scheduled()) - tickEvent.squash(); - break; - - case Idle: - assert(old_status == Running); - last_idle = curTick; - if (tickEvent.scheduled()) - tickEvent.squash(); - break; - - case Running: - assert(old_status == Idle || - old_status == DcacheMissStall || - old_status == IcacheMissComplete); - if (old_status == Idle) - idleCycles += curTick - last_idle; - - if (tickEvent.squashed()) - tickEvent.reschedule(curTick + 1); - else if (!tickEvent.scheduled()) - tickEvent.schedule(curTick + 1); - break; - - default: - panic("can't get here"); - } - } - - // statistics - void regStats(); - - // number of simulated instructions - Counter numInst; - Statistics::Formula numInsts; - - // number of simulated memory references - Statistics::Scalar<> numMemRefs; - - // number of idle cycles - Statistics::Scalar<> idleCycles; - Statistics::Formula idleFraction; - Counter last_idle; - - // number of cycles stalled for I-cache misses - Statistics::Scalar<> icacheStallCycles; - Counter lastIcacheStall; - - // number of cycles stalled for D-cache misses - Statistics::Scalar<> dcacheStallCycles; - Counter lastDcacheStall; - - void processCacheCompletion(); - - virtual void serialize(); - virtual void unserialize(IniFile &db, const std::string &category, - ConfigNode *node); - - template - Fault read(Addr addr, T& data, unsigned flags); - - template - Fault write(T data, Addr addr, unsigned flags, - uint64_t *res); - - Fault prefetch(Addr addr, unsigned flags) - { - // need to do this... - return No_Fault; - } - - void writeHint(Addr addr, int size) - { - // need to do this... - } -}; - -#endif // __SIMPLE_CPU_HH__ diff --git a/sim/smt.hh b/sim/smt.hh deleted file mode 100644 index f9c1e4614..000000000 --- a/sim/smt.hh +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * Defines SMT_MAX_CPUS and SMT_MAX_THREADS. - */ - -#ifndef __SMT_HH__ -#define __SMT_HH__ - -#ifndef SMT_MAX_CPUS -/** The maximum number of cpus in any one system. */ -#define SMT_MAX_CPUS 4 -#endif - -#ifndef SMT_MAX_THREADS -/** The number of TPUs in any processor. */ -#define SMT_MAX_THREADS 4 -#endif - -/** - * The maximum number of active threads across all cpus. Used to - * initialize per-thread statistics in the cache. - * - * NB: Be careful to only use it once all the CPUs that you care about - * have been initialized - */ -extern int maxThreadsPerCPU; - -/** - * Changes the status and priority of the thread with the given number. - * @param thread_number The thread to change. - * @param activate The new active status. - * @param priority The new priority. - */ -void change_thread_state(int thread_number, int activate, int priority); - -#endif // __SMT_HH__ diff --git a/sim/static_inst.cc b/sim/static_inst.cc deleted file mode 100644 index cf25d5f05..000000000 --- a/sim/static_inst.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "static_inst.hh" -#include "universe.hh" - -template -StaticInstPtr StaticInst::nullStaticInstPtr; - -template -typename StaticInst::DecodeCache StaticInst::decodeCache; - -// Define the decode cache hash map. -template StaticInst::DecodeCache -StaticInst::decodeCache; - -template -void -StaticInst::dumpDecodeCacheStats() -{ - using namespace std; - - cerr << "Decode hash table stats @ " << curTick << ":" << endl; - cerr << "\tnum entries = " << decodeCache.size() << endl; - cerr << "\tnum buckets = " << decodeCache.bucket_count() << endl; - vector hist(100, 0); - int max_hist = 0; - for (int i = 0; i < decodeCache.bucket_count(); ++i) { - int count = decodeCache.elems_in_bucket(i); - if (count > max_hist) - max_hist = count; - hist[count]++; - } - for (int i = 0; i <= max_hist; ++i) { - cerr << "\tbuckets of size " << i << " = " << hist[i] << endl; - } -} - - -template StaticInstPtr -StaticInst::nullStaticInstPtr; - -template -bool -StaticInst::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) -{ - if (isDirectCtrl()) { - tgt = branchTarget(pc); - return true; - } - - if (isIndirectCtrl()) { - tgt = branchTarget(xc); - return true; - } - - return false; -} - - -// force instantiation of template function(s) above -template StaticInst; diff --git a/sim/static_inst.hh b/sim/static_inst.hh deleted file mode 100644 index b8f9cc00a..000000000 --- a/sim/static_inst.hh +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (c) 2003 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __STATIC_INST_HH__ -#define __STATIC_INST_HH__ - -#include -#include - -#include "host.hh" -#include "hashmap.hh" -#include "refcnt.hh" - -#include "op_class.hh" -#include "isa_traits.hh" - -// forward declarations -class ExecContext; -class SpecExecContext; -class SimpleCPU; -class CPU; -class DynInst; -class SymbolTable; - -namespace Trace { - class InstRecord; -} - -/** - * Base, ISA-independent static instruction class. - * - * The main component of this class is the vector of flags and the - * associated methods for reading them. Any object that can rely - * solely on these flags can process instructions without being - * recompiled for multiple ISAs. - */ -class StaticInstBase : public RefCounted -{ - protected: - - /// Set of boolean static instruction properties. - /// - /// Notes: - /// - The IsInteger and IsFloating flags are based on the class of - /// registers accessed by the instruction. Although most - /// instructions will have exactly one of these two flags set, it - /// is possible for an instruction to have neither (e.g., direct - /// unconditional branches, memory barriers) or both (e.g., an - /// FP/int conversion). - /// - If IsMemRef is set, then exactly one of IsLoad or IsStore - /// will be set. Prefetches are marked as IsLoad, even if they - /// prefetch exclusive copies. - /// - If IsControl is set, then exactly one of IsDirectControl or - /// IsIndirect Control will be set, and exactly one of - /// IsCondControl or IsUncondControl will be set. - /// - enum Flags { - IsNop, ///< Is a no-op (no effect at all). - - IsInteger, ///< References integer regs. - IsFloating, ///< References FP regs. - - IsMemRef, ///< References memory (load, store, or prefetch). - IsLoad, ///< Reads from memory (load or prefetch). - IsStore, ///< Writes to memory. - IsInstPrefetch, ///< Instruction-cache prefetch. - IsDataPrefetch, ///< Data-cache prefetch. - - IsControl, ///< Control transfer instruction. - IsDirectControl, ///< PC relative control transfer. - IsIndirectControl, ///< Register indirect control transfer. - IsCondControl, ///< Conditional control transfer. - IsUncondControl, ///< Unconditional control transfer. - IsCall, ///< Subroutine call. - IsReturn, ///< Subroutine return. - - IsThreadSync, ///< Thread synchronization operation. - - NumFlags - }; - - /// Flag values for this instruction. - std::bitset flags; - - /// See opClass(). - OpClass _opClass; - - /// See numSrcRegs(). - int8_t _numSrcRegs; - - /// See numDestRegs(). - int8_t _numDestRegs; - - /// The following are used to track physical register usage - /// for machines with separate int & FP reg files. - //@{ - int8_t _numFPDestRegs; - int8_t _numIntDestRegs; - //@} - - /// Constructor. - /// It's important to initialize everything here to a sane - /// default, since the decoder generally only overrides - /// the fields that are meaningful for the particular - /// instruction. - StaticInstBase(OpClass __opClass) - : _opClass(__opClass), _numSrcRegs(0), _numDestRegs(0), - _numFPDestRegs(0), _numIntDestRegs(0) - { - } - - public: - - /// @name Register information. - /// The sum of numFPDestRegs() and numIntDestRegs() equals - /// numDestRegs(). The former two functions are used to track - /// physical register usage for machines with separate int & FP - /// reg files. - //@{ - /// Number of source registers. - int8_t numSrcRegs() const { return _numSrcRegs; } - /// Number of destination registers. - int8_t numDestRegs() const { return _numDestRegs; } - /// Number of floating-point destination regs. - int8_t numFPDestRegs() const { return _numFPDestRegs; } - /// Number of integer destination regs. - int8_t numIntDestRegs() const { return _numIntDestRegs; } - //@} - - /// @name Flag accessors. - /// These functions are used to access the values of the various - /// instruction property flags. See StaticInstBase::Flags for descriptions - /// of the individual flags. - //@{ - - bool isNop() const { return flags[IsNop]; } - - bool isMemRef() const { return flags[IsMemRef]; } - bool isLoad() const { return flags[IsLoad]; } - bool isStore() const { return flags[IsStore]; } - bool isInstPrefetch() const { return flags[IsInstPrefetch]; } - bool isDataPrefetch() const { return flags[IsDataPrefetch]; } - - bool isInteger() const { return flags[IsInteger]; } - bool isFloating() const { return flags[IsFloating]; } - - bool isControl() const { return flags[IsControl]; } - bool isCall() const { return flags[IsCall]; } - bool isReturn() const { return flags[IsReturn]; } - bool isDirectCtrl() const { return flags[IsDirectControl]; } - bool isIndirectCtrl() const { return flags[IsIndirectControl]; } - bool isCondCtrl() const { return flags[IsCondControl]; } - bool isUncondCtrl() const { return flags[IsUncondControl]; } - - bool isThreadSync() const { return flags[IsThreadSync]; } - //@} - - /// Operation class. Used to select appropriate function unit in issue. - OpClass opClass() const { return _opClass; } -}; - - -// forward declaration -template -class StaticInstPtr; - -/** - * Generic yet ISA-dependent static instruction class. - * - * This class builds on StaticInstBase, defining fields and interfaces - * that are generic across all ISAs but that differ in details - * according to the specific ISA being used. - */ -template -class StaticInst : public StaticInstBase -{ - public: - - /// Binary machine instruction type. - typedef typename ISA::MachInst MachInst; - /// Memory address type. - typedef typename ISA::Addr Addr; - /// Logical register index type. - typedef typename ISA::RegIndex RegIndex; - - enum { - MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs - MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs - }; - - - /// Return logical index (architectural reg num) of i'th destination reg. - /// Only the entries from 0 through numDestRegs()-1 are valid. - RegIndex destRegIdx(int i) { return _destRegIdx[i]; } - - /// Return logical index (architectural reg num) of i'th source reg. - /// Only the entries from 0 through numSrcRegs()-1 are valid. - RegIndex srcRegIdx(int i) { return _srcRegIdx[i]; } - - /// Pointer to a statically allocated "null" instruction object. - /// Used to give eaCompInst() and memAccInst() something to return - /// when called on non-memory instructions. - static StaticInstPtr nullStaticInstPtr; - - /** - * Memory references only: returns "fake" instruction representing - * the effective address part of the memory operation. Used to - * obtain the dependence info (numSrcRegs and srcRegIdx[]) for - * just the EA computation. - */ - virtual StaticInstPtr eaCompInst() { return nullStaticInstPtr; } - - /** - * Memory references only: returns "fake" instruction representing - * the memory access part of the memory operation. Used to - * obtain the dependence info (numSrcRegs and srcRegIdx[]) for - * just the memory access (not the EA computation). - */ - virtual StaticInstPtr memAccInst() { return nullStaticInstPtr; } - - /// The binary machine instruction. - const MachInst machInst; - - protected: - - /// See destRegIdx(). - RegIndex _destRegIdx[MaxInstDestRegs]; - /// See srcRegIdx(). - RegIndex _srcRegIdx[MaxInstSrcRegs]; - - /** - * Base mnemonic (e.g., "add"). Used by generateDisassembly() - * methods. Also useful to readily identify instructions from - * within the debugger when #cachedDisassembly has not been - * initialized. - */ - const char *mnemonic; - - /** - * String representation of disassembly (lazily evaluated via - * disassemble()). - */ - std::string *cachedDisassembly; - - /** - * Internal function to generate disassembly string. - */ - virtual std::string generateDisassembly(Addr pc, - const SymbolTable *symtab) = 0; - - /// Constructor. - StaticInst(const char *_mnemonic, MachInst _machInst, OpClass __opClass) - : StaticInstBase(__opClass), - machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0) - { - } - - public: - - virtual ~StaticInst() - { - if (cachedDisassembly) - delete cachedDisassembly; - } - - /** - * Execute this instruction under SimpleCPU model. - */ - virtual Fault execute(SimpleCPU *cpu, ExecContext *xc, - Trace::InstRecord *traceData) = 0; - - /** - * Execute this instruction under detailed CPU model. - */ - virtual Fault execute(CPU *cpu, SpecExecContext *xc, DynInst *dynInst, - Trace::InstRecord *traceData) = 0; - - /** - * Return the target address for a PC-relative branch. - * Invalid if not a PC-relative branch (i.e. isDirectCtrl() - * should be true). - */ - virtual Addr branchTarget(Addr branchPC) - { - panic("StaticInst::branchTarget() called on instruction " - "that is not a PC-relative branch."); - } - - /** - * Return the target address for an indirect branch (jump). - * The register value is read from the supplied execution context. - * Invalid if not an indirect branch (i.e. isIndirectCtrl() - * should be true). - */ - virtual Addr branchTarget(ExecContext *xc) - { - panic("StaticInst::branchTarget() called on instruction " - "that is not an indirect branch."); - } - - /** - * Return true if the instruction is a control transfer, and if so, - * return the target address as well. - */ - bool hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt); - - /** - * Return string representation of disassembled instruction. - * The default version of this function will call the internal - * virtual generateDisassembly() function to get the string, - * then cache it in #cachedDisassembly. If the disassembly - * should not be cached, this function should be overridden directly. - */ - virtual const std::string &disassemble(Addr pc, - const SymbolTable *symtab = 0) - { - if (!cachedDisassembly) - cachedDisassembly = - new std::string(generateDisassembly(pc, symtab)); - - return *cachedDisassembly; - } - - /// Decoded instruction cache type. - /// For now we're using a generic hash_map; this seems to work - /// pretty well. - typedef m5::hash_map > DecodeCache; - - /// A cache of decoded instruction objects. - static DecodeCache decodeCache; - - /** - * Dump some basic stats on the decode cache hash map. - * Only gets called if DECODE_CACHE_HASH_STATS is defined. - */ - static void dumpDecodeCacheStats(); - - /// Decode a machine instruction. - /// @param mach_inst The binary instruction to decode. - /// @retval A pointer to the corresponding StaticInst object. - static - StaticInstPtr decode(MachInst mach_inst) - { -#ifdef DECODE_CACHE_HASH_STATS - // Simple stats on decode hash_map. Turns out the default - // hash function is as good as anything I could come up with. - const int dump_every_n = 10000000; - static int decodes_til_dump = dump_every_n; - - if (--decodes_til_dump == 0) { - dumpDecodeCacheStats(); - decodes_til_dump = dump_every_n; - } -#endif - - typename DecodeCache::iterator iter = decodeCache.find(mach_inst); - if (iter != decodeCache.end()) { - return iter->second; - } - - StaticInstPtr si = ISA::decodeInst(mach_inst); - decodeCache[mach_inst] = si; - return si; - } -}; - -typedef RefCountingPtr StaticInstBasePtr; - -/// Reference-counted pointer to a StaticInst object. -/// This type should be used instead of "StaticInst *" so that -/// StaticInst objects can be properly reference-counted. -template -class StaticInstPtr : public RefCountingPtr > -{ - public: - /// Constructor. - StaticInstPtr() - : RefCountingPtr >() - { - } - - /// Conversion from "StaticInst *". - StaticInstPtr(StaticInst *p) - : RefCountingPtr >(p) - { - } - - /// Copy constructor. - StaticInstPtr(const StaticInstPtr &r) - : RefCountingPtr >(r) - { - } - - /// Construct directly from machine instruction. - /// Calls StaticInst::decode(). - StaticInstPtr(typename ISA::MachInst mach_inst) - : RefCountingPtr >(StaticInst::decode(mach_inst)) - { - } - - /// Convert to pointer to StaticInstBase class. - operator const StaticInstBasePtr() - { - return get(); - } -}; - -#endif // __STATIC_INST_HH__