--- /dev/null
+Steven K. Reinhardt
+-----------------------
+
+Nathan L. Binkert
+-----------------------
+
+Erik G. Hallnor
+-----------------------
+
+Steve E. Raasch
+-----------------------
+
+Lisa R. Hsu
+-----------------------
+
+Ali G. Saidi
+-----------------------
+
+Andrew L. Schultz
+-----------------------
+
+Kevin T. Lim
+-----------------------
+
+Ronald G. Dreslinski Jr
+-----------------------
+
+Gabriel Black
+-----------------------
+
+Korey Sewell
+-----------------------
+
+David Green
+-----------------------
+
+Benjamin S. Nash
+-----------------------
+
+Miguel J. Serrano
+-----------------------
+
-This is release m5_1.1 of the M5 simulator.
+This is release 2.0 of the M5 simulator.
-This file contains brief "getting started" instructions. For more
-information, see http://m5.eecs.umich.edu. If you have questions,
-please send mail to m5sim-users@lists.sourceforge.net.
+For information about building the simulator and getting started please refer
+to: http://m5.eecs.umich.edu/
+
+Specific Pages of Interest are:
+http://m5.eecs.umich.edu/wiki/index.php/Compiling_M5
+http://m5.eecs.umich.edu/wiki/index.php/Running_M5
+
+If you have questions, please send mail to m5sim-users@lists.sourceforge.net.
WHAT'S INCLUDED (AND NOT)
-------------------------
The basic source release includes these subdirectories:
- - m5: the simulator itself
- - m5-test: regression tests
- - ext: less-common external packages needed to build m5
- - alpha-system: source for Alpha console and PALcode
+ - m5:
+ - src: source code of the m5 simulator
+ - test: regression tests
+ - ext: less-common external packages needed to build m5
+ - system/alpha: source for Alpha console and PALcode
To run full-system simulations, you will need compiled console,
PALcode, and kernel binaries and one or more disk images. These files
-are collected in a separate archive, m5_system_1.1.tar.bz2. This file
+are collected in a separate archive, m5_system_2.0.tar.bz2. This file
is included on the CD release, or you can download it separately from
Sourceforge.
program needed to build M5. If you do not have the CD, the same HTML
documentation is available online at http://m5.eecs.umich.edu/docs,
the Linux source patches are available at
-http://m5.eecs.umich.edu/dist/linux_m5-2.6.8.1.diff, and the scons
-program is available from http://www.scons.org.
-
-WHAT'S NEEDED
--------------
-- GCC version 3.3 or newer
-- Python 2.3 or newer
-- SCons 0.96.1 or newer (see http://www.scons.org)
-
-WHAT'S RECOMMENDED
-------------------
-- MySQL (for statistics complex statistics storage/retrieval)
-- Python-MysqlDB (for statistics analysis)
-
-GETTING STARTED
----------------
-
-There are two different build targets and three optimizations levels:
-
-Target:
--------
-ALPHA_SE - Syscall emulation simulation
-ALPHA_FS - Full system simulation
-
-Optimization:
--------------
-m5.debug - debug version of the code with tracing and without optimization
-m5.opt - optimized version of code with tracing
-m5.fast - optimized version of the code without tracing and asserts
-
-Different targets are built in different subdirectories of m5/build.
-Binaries with the same target but different optimization levels share
-the same directory. Note that you can build m5 in any directory you
-choose;p just configure the target directory using the 'mkbuilddir'
-script in m5/build.
-
-The following steps will build and test the simulator. The variable
-"$top" refers to the top directory where you've unpacked the files,
-i.e., the one containing the m5, m5-test, and ext directories. If you
-have a multiprocessor system, you should give scons a "-j N" argument (like
-make) to run N jobs in parallel.
-
-To build and test the syscall-emulation simulator:
-
- cd $top/m5/build
- scons ALPHA_SE/test/opt/quick
-
-This process takes under 10 minutes on a dual 3GHz Xeon system (using
-the '-j 4' option).
-
-To build and test the full-system simulator:
-
-1. Unpack the full-system binaries from m5_system_1.1.tar.bz2. (See
- above for directions on obtaining this file if you don't have it.)
- This package includes disk images and kernel, palcode, and console
- binaries for Linux and FreeBSD.
-2. Edit the SYSTEMDIR search path in $top/m5-test/SysPaths.py to
- include the path to your local copy of the binaries.
-3. In $top/m5/build, run "scons ALPHA_FS/test/opt/quick".
+http://m5.eecs.umich.edu/dist/linux_m5-2.6.8.1.diff, the scons
+program is available from http://www.scons.org, and swig is available from
+http://www.swig.org.
-This process also takes under 10 minutes on a dual 3GHz Xeon system
-(again using the '-j 4' option).
+XXX. X, 2006: m5_2.0
+--------------------
+Major update to M5 including:
+- New CPU model
+- Sew memory system
+- More extensive python integration
+- Preliminary syscall emulation support for MIPS and SPARC
+
Oct. 8, 2005: m5_1.1
--------------------
Update release for IOSCA workshop mini-tutorial. New features include:
# parse command-line arguments
parser = optparse.OptionParser(option_list=m5.standardOptions)
-parser.add_option("-c", "--cmd", default="hello")
-parser.add_option("-t", "--timing", action="store_true")
-parser.add_option("-d", "--detailed", action="store_true")
-parser.add_option("-m", "--maxtick", type="int")
+parser.add_option("-c", "--cmd", default="hello",
+ help="The binary to run in syscall emulation mode.")
+parser.add_option("-o", "--options", default="",
+ help="The options to pass to the binary, use \" \" around the entire\
+ string.")
+parser.add_option("-i", "--input", default="",
+ help="A file of input to give to the binary.")
+parser.add_option("-t", "--timing", action="store_true",
+ help="Use simple timing CPU.")
+parser.add_option("-d", "--detailed", action="store_true",
+ help="Use detailed CPU.")
+parser.add_option("-m", "--maxtick", type="int",
+ help="Set the maximum number of ticks to run for")
(options, args) = parser.parse_args()
m5.setStandardOptions(options)
process = LiveProcess()
process.executable = os.path.join(this_dir, options.cmd)
-process.cmd = options.cmd
+process.cmd = options.cmd + " " + options.options
+if options.input != "":
+ process.input = options.input
magicbus = Bus()
mem = PhysicalMemory()
+if options.timing and options.detailed:
+ print "Error: you may only specify one cpu model";
+ sys.exit(1)
+
if options.timing:
cpu = TimingSimpleCPU()
elif options.detailed:
#include "base/trace.hh"
#if FULL_SYSTEM
#include "arch/alpha/ev5.hh"
+#else
+#include "sim/process.hh"
+#include "mem/page_table.hh"
#endif
namespace AlphaISA
FaultVect ArithmeticFault::_vect = 0x0501;
FaultStat ArithmeticFault::_count;
+#if !FULL_SYSTEM
+FaultName PageTableFault::_name = "page_table_fault";
+FaultVect PageTableFault::_vect = 0x0000;
+FaultStat PageTableFault::_count;
+#endif
+
FaultName InterruptFault::_name = "interrupt";
FaultVect InterruptFault::_vect = 0x0101;
FaultStat InterruptFault::_count;
AlphaFault::invoke(tc);
}
+#else //!FULL_SYSTEM
+
+void PageTableFault::invoke(ThreadContext *tc)
+{
+ Process *p = tc->getProcessPtr();
+
+ // address is higher than the stack region or in the current stack region
+ if (vaddr > p->stack_base || vaddr > p->stack_min)
+ FaultBase::invoke(tc);
+
+ // We've accessed the next page
+ if (vaddr > p->stack_min - PageBytes) {
+ warn("Increasing stack %#x:%#x to %#x:%#x because of access to %#x",
+ p->stack_min, p->stack_base, p->stack_min - PageBytes,
+ p->stack_base, vaddr);
+ p->stack_min -= PageBytes;
+ if (p->stack_base - p->stack_min > 8*1024*1024)
+ fatal("Over max stack size for one thread\n");
+ p->pTable->allocate(p->stack_min, PageBytes);
+ } else {
+ FaultBase::invoke(tc);
+ }
+}
+
#endif
} // namespace AlphaISA
bool isAlignmentFault() {return true;}
};
+#if !FULL_SYSTEM
+class PageTableFault : public AlphaFault
+{
+ private:
+ Addr vaddr;
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ PageTableFault(Addr va)
+ : vaddr(va) {}
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+ void invoke(ThreadContext * tc);
+};
+
+static inline Fault genPageTableFault(Addr va)
+{
+ return new PageTableFault(va);
+}
+#endif
+
static inline Fault genMachineCheckFault()
{
return new MachineCheckFault;
#include "cpu/thread_context.hh"
#include "cpu/base.hh"
#include "base/trace.hh"
+#if !FULL_SYSTEM
+#include "sim/process.hh"
+#include "mem/page_table.hh"
+#endif
namespace MipsISA
{
FaultVect ArithmeticFault::_vect = 0x0501;
FaultStat ArithmeticFault::_count;
+#if !FULL_SYSTEM
+FaultName PageTableFault::_name = "page_table_fault";
+FaultVect PageTableFault::_vect = 0x0000;
+FaultStat PageTableFault::_count;
+#endif
+
FaultName InterruptFault::_name = "interrupt";
FaultVect InterruptFault::_vect = 0x0101;
FaultStat InterruptFault::_count;
panic("Arithmetic traps are unimplemented!");
}
-#endif
+#else //!FULL_SYSTEM
+void PageTableFault::invoke(ThreadContext *tc)
+{
+ Process *p = tc->getProcessPtr();
+
+ // address is higher than the stack region or in the current stack region
+ if (vaddr > p->stack_base || vaddr > p->stack_min)
+ FaultBase::invoke(tc);
+
+ // We've accessed the next page
+ if (vaddr > p->stack_min - PageBytes) {
+ p->stack_min -= PageBytes;
+ if (p->stack_base - p->stack_min > 8*1024*1024)
+ fatal("Over max stack size for one thread\n");
+ p->pTable->allocate(p->stack_min, PageBytes);
+ warn("Increasing stack size by one page.");
+ } else {
+ FaultBase::invoke(tc);
+ }
+}
+
+#endif
} // namespace MipsISA
bool isAlignmentFault() {return true;}
};
+#if !FULL_SYSTEM
+class PageTableFault : public MipsFault
+{
+ private:
+ Addr vaddr;
+ static FaultName _name;
+ static FaultVect _vect;
+ static FaultStat _count;
+ public:
+ PageTableFault(Addr va)
+ : vaddr(va) {}
+ FaultName name() {return _name;}
+ FaultVect vect() {return _vect;}
+ FaultStat & countStat() {return _count;}
+ void invoke(ThreadContext * tc);
+};
+
+static inline Fault genPageTableFault(Addr va)
+{
+ return new PageTableFault(va);
+}
+#endif
+
+
static inline Fault genMachineCheckFault()
{
return new MachineCheckFault;
#include "cpu/thread_context.hh"
#include "cpu/base.hh"
#include "base/trace.hh"
+#if !FULL_SYSTEM
+#include "sim/process.hh"
+#include "mem/page_table.hh"
+#endif
namespace SparcISA
{
FaultPriority TrapInstruction::_priority = 16;
FaultStat TrapInstruction::_count;
+#if !FULL_SYSTEM
+FaultName PageTableFault::_name = "page_table_fault";
+TrapType PageTableFault::_trapType = 0x0000;
+FaultPriority PageTableFault::_priority = 0;
+FaultStat PageTableFault::_count;
+#endif
+
#if FULL_SYSTEM
void SparcFault::invoke(ThreadContext * tc)
// Should be handled in ISA.
}
+void PageTableFault::invoke(ThreadContext *tc)
+{
+ Process *p = tc->getProcessPtr();
+
+ // address is higher than the stack region or in the current stack region
+ if (vaddr > p->stack_base || vaddr > p->stack_min)
+ FaultBase::invoke(tc);
+
+ // We've accessed the next page
+ if (vaddr > p->stack_min - PageBytes) {
+ p->stack_min -= PageBytes;
+ if (p->stack_base - p->stack_min > 8*1024*1024)
+ fatal("Over max stack size for one thread\n");
+ p->pTable->allocate(p->stack_min, PageBytes);
+ warn("Increasing stack size by one page.");
+ } else {
+ FaultBase::invoke(tc);
+ }
+}
#endif
} // namespace SparcISA
bool isAlignmentFault() {return true;}
};
+#if !FULL_SYSTEM
+class PageTableFault : public SparcFault
+{
+ private:
+ Addr vaddr;
+ static FaultName _name;
+ static TrapType _trapType;
+ static FaultPriority _priority;
+ static FaultStat _count;
+ public:
+ PageTableFault(Addr va)
+ : vaddr(va) {}
+ FaultName name() {return _name;}
+ TrapType trapType() {return _trapType;}
+ FaultPriority priority() {return _priority;}
+ FaultStat & countStat() {return _count;}
+ void invoke(ThreadContext * tc);
+};
+
+static inline Fault genPageTableFault(Addr va)
+{
+ return new PageTableFault(va);
+}
+#endif
+
static inline Fault genMachineCheckFault()
{
return new InternalProcessorError;
#endif
};
+
} // SparcISA namespace
#endif // __FAULTS_HH__
// C interfaces to FastAlloc::dump_summary() and FastAlloc::dump_oldest().
// gdb seems to have trouble with calling C++ functions directly.
//
-extern "C" void
fast_alloc_summary()
{
FastAlloc::dump_summary();
}
-extern "C" void
fast_alloc_oldest(int n)
{
FastAlloc::dump_oldest(n);
//
// Dump trace buffer to specified file (cout if NULL)
//
-extern "C"
void
dumpTrace(const char *filename)
{
// same facility as the "trace to file" feature, and will print error
// messages rather than clobbering an existing ostream pointer.
//
-extern "C"
void
echoTrace(bool on)
{
}
}
-extern "C"
void
printTraceFlags()
{
cprintf("could not find flag %s\n", string);
}
-extern "C"
void
setTraceFlag(const char *string)
{
tweakTraceFlag(string, true);
}
-extern "C"
void
clearTraceFlag(const char *string)
{
bool inPalMode(uint64_t PC)
{ return AlphaISA::PcPAL(PC); }
- /** Traps to handle given fault. */
- void trap(Fault fault, unsigned tid);
bool simPalCheck(int palFunc, unsigned tid);
/** Processes any interrupts. */
void halt() { panic("Halt not implemented!\n"); }
#endif
+ /** Traps to handle given fault. */
+ void trap(Fault fault, unsigned tid);
#if !FULL_SYSTEM
/** Executes a syscall.
return true;
}
-template <class Impl>
-void
-AlphaO3CPU<Impl>::trap(Fault fault, unsigned tid)
-{
- // Pass the thread's TC into the invoke method.
- fault->invoke(this->threadContexts[tid]);
-}
-
template <class Impl>
void
AlphaO3CPU<Impl>::processInterrupts()
#endif // FULL_SYSTEM
+template <class Impl>
+void
+AlphaO3CPU<Impl>::trap(Fault fault, unsigned tid)
+{
+ // Pass the thread's TC into the invoke method.
+ fault->invoke(this->threadContexts[tid]);
+}
+
#if !FULL_SYSTEM
template <class Impl>
if (inst_fault != NoFault) {
head_inst->setCompleted();
-#if FULL_SYSTEM
DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",
head_inst->seqNum, head_inst->readPC());
generateTrapEvent(tid);
return false;
-#else // !FULL_SYSTEM
- panic("fault (%d) detected @ PC %08p", inst_fault,
- head_inst->PC);
-#endif // FULL_SYSTEM
}
updateComInstStats(head_inst);
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "cpu/pc_event.hh"
-#include "mem/packet.hh"
+#include "mem/packet_impl.hh"
#include "mem/port.hh"
#include "sim/eventq.hh"
#include "config/full_system.hh"
#include "base/hashmap.hh"
#include "cpu/inst_seq.hh"
-#include "mem/packet.hh"
+#include "mem/packet_impl.hh"
#include "mem/port.hh"
/**
postExecute();
if (simulate_stalls) {
- // This calculation assumes that the icache and dcache
- // access latencies are always a multiple of the CPU's
- // cycle time. If not, the next tick event may get
- // scheduled at a non-integer multiple of the CPU
- // cycle time.
Tick icache_stall = icache_latency - cycles(1);
Tick dcache_stall =
dcache_access ? dcache_latency - cycles(1) : 0;
- latency += icache_stall + dcache_stall;
+ Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1);
+ if (cycles(stall_cycles) < (icache_stall + dcache_stall))
+ latency += cycles(stall_cycles+1);
+ else
+ latency += cycles(stall_cycles);
}
}
BaseSimpleCPU::advancePC(Fault fault)
{
if (fault != NoFault) {
-#if FULL_SYSTEM
fault->invoke(tc);
-#else // !FULL_SYSTEM
- fatal("fault (%s) detected @ PC %08p", fault->name(), thread->readPC());
-#endif // FULL_SYSTEM
}
else {
// go to the next instruction
system(_system)
{
assert(isPowerOf2(pageSize));
+ pTableCache[0].vaddr = 0;
+ pTableCache[1].vaddr = 0;
+ pTableCache[2].vaddr = 0;
}
PageTable::~PageTable()
assert(pageOffset(vaddr) == 0);
for (; size > 0; size -= pageSize, vaddr += pageSize) {
- std::map<Addr,Addr>::iterator iter = pTable.find(vaddr);
+ m5::hash_map<Addr,Addr>::iterator iter = pTable.find(vaddr);
if (iter != pTable.end()) {
// already mapped
}
pTable[vaddr] = system->new_page();
+ pTableCache[2].paddr = pTableCache[1].paddr;
+ pTableCache[2].vaddr = pTableCache[1].vaddr;
+ pTableCache[1].paddr = pTableCache[0].paddr;
+ pTableCache[1].vaddr = pTableCache[0].vaddr;
+ pTableCache[0].paddr = pTable[vaddr];
+ pTableCache[0].vaddr = vaddr;
}
}
PageTable::translate(Addr vaddr, Addr &paddr)
{
Addr page_addr = pageAlign(vaddr);
- std::map<Addr,Addr>::iterator iter = pTable.find(page_addr);
+ paddr = 0;
+
+ if (pTableCache[0].vaddr == vaddr) {
+ paddr = pTableCache[0].paddr;
+ return true;
+ }
+ if (pTableCache[1].vaddr == vaddr) {
+ paddr = pTableCache[1].paddr;
+ return true;
+ }
+ if (pTableCache[2].vaddr == vaddr) {
+ paddr = pTableCache[2].paddr;
+ return true;
+ }
+
+ m5::hash_map<Addr,Addr>::iterator iter = pTable.find(page_addr);
if (iter == pTable.end()) {
return false;
assert(pageAlign(req->getVaddr() + req->getSize() - 1)
== pageAlign(req->getVaddr()));
if (!translate(req->getVaddr(), paddr)) {
- return genMachineCheckFault();
+ return genPageTableFault(req->getVaddr());
}
req->setPaddr(paddr);
return page_check(req->getPaddr(), req->getSize());
#define __PAGE_TABLE__
#include <string>
-#include <map>
#include "arch/isa_traits.hh"
+#include "base/hashmap.hh"
#include "base/trace.hh"
#include "mem/request.hh"
#include "mem/packet.hh"
class PageTable
{
protected:
- std::map<Addr,Addr> pTable;
+ m5::hash_map<Addr,Addr> pTable;
+
+ struct cacheElement {
+ Addr paddr;
+ Addr vaddr;
+ } ;
+
+ struct cacheElement pTableCache[3];
const Addr pageSize;
const Addr offsetMask;
// handy function to schedule DebugBreakEvent on main event queue
// (callable from debugger)
//
-extern "C" void sched_break_cycle(Tick when)
+void sched_break_cycle(Tick when)
{
new DebugBreakEvent(&mainEventQueue, when);
}
-extern "C" void eventq_dump()
+void eventq_dump()
{
mainEventQueue.dump();
}
{
public:
virtual FaultName name() = 0;
-#if FULL_SYSTEM
virtual void invoke(ThreadContext * tc);
-#else
- virtual void invoke(ThreadContext * tc);
-#endif
// template<typename T>
// bool isA() {return dynamic_cast<T *>(this);}
virtual bool isMachineCheckFault() {return false;}
// set bottom of stack
stack_min = stack_base - space_needed;
// align it
- stack_min &= ~(intSize-1);
+ stack_min = roundDown(stack_min, pageSize);
stack_size = stack_base - stack_min;
// map memory
- pTable->allocate(roundDown(stack_min, pageSize),
- roundUp(stack_size, pageSize));
+ pTable->allocate(stack_min, roundUp(stack_size, pageSize));
// map out initial stack contents
Addr argv_array_base = stack_min + intSize; // room for argc
}
}
-extern "C"
void
debugObjectBreak(const char *objs)
{
/* namespace Stats */ }
-extern "C" void
-debugDumpStats()
+void debugDumpStats()
{
Stats::DumpNow();
}
}
}
-extern "C"
void
printSystems()
{