Merge zizzer:/bk/newmem
into zazzer.eecs.umich.edu:/.automount/zooks/y/ksewell/research/m5-sim/newmem-release --HG-- extra : convert_revision : 9b5b1419e8e22bce16ed97fc02c2008ca0181afc
This commit is contained in:
commit
2a9becba44
24 changed files with 302 additions and 322 deletions
|
@ -6,12 +6,14 @@
|
||||||
import os, optparse, sys
|
import os, optparse, sys
|
||||||
import m5
|
import m5
|
||||||
from m5.objects import *
|
from m5.objects import *
|
||||||
|
from FullO3Config import *
|
||||||
|
|
||||||
# parse command-line arguments
|
# parse command-line arguments
|
||||||
parser = optparse.OptionParser(option_list=m5.standardOptions)
|
parser = optparse.OptionParser(option_list=m5.standardOptions)
|
||||||
|
|
||||||
parser.add_option("-c", "--cmd", default="hello")
|
parser.add_option("-c", "--cmd", default="hello")
|
||||||
parser.add_option("-t", "--timing", action="store_true")
|
parser.add_option("-t", "--timing", action="store_true")
|
||||||
|
parser.add_option("-f", "--full", action="store_true")
|
||||||
|
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
|
|
||||||
|
@ -31,6 +33,8 @@ mem = PhysicalMemory()
|
||||||
|
|
||||||
if options.timing:
|
if options.timing:
|
||||||
cpu = TimingSimpleCPU()
|
cpu = TimingSimpleCPU()
|
||||||
|
elif options.full:
|
||||||
|
cpu = DetailedCPU()
|
||||||
else:
|
else:
|
||||||
cpu = AtomicSimpleCPU()
|
cpu = AtomicSimpleCPU()
|
||||||
cpu.workload = process
|
cpu.workload = process
|
||||||
|
|
|
@ -59,8 +59,12 @@ AlphaISA::initCPU(ThreadContext *tc, int cpuId)
|
||||||
tc->setIntReg(16, cpuId);
|
tc->setIntReg(16, cpuId);
|
||||||
tc->setIntReg(0, cpuId);
|
tc->setIntReg(0, cpuId);
|
||||||
|
|
||||||
tc->setPC(tc->readMiscReg(IPR_PAL_BASE) + (new ResetFault)->vect());
|
AlphaFault *reset = new ResetFault;
|
||||||
|
|
||||||
|
tc->setPC(tc->readMiscReg(IPR_PAL_BASE) + reset->vect());
|
||||||
tc->setNextPC(tc->readPC() + sizeof(MachInst));
|
tc->setNextPC(tc->readPC() + sizeof(MachInst));
|
||||||
|
|
||||||
|
delete reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -659,11 +659,11 @@ decode OPCODE default Unknown::unknown() {
|
||||||
0xe000: rc({{
|
0xe000: rc({{
|
||||||
Ra = xc->readIntrFlag();
|
Ra = xc->readIntrFlag();
|
||||||
xc->setIntrFlag(0);
|
xc->setIntrFlag(0);
|
||||||
}}, IsNonSpeculative);
|
}}, IsNonSpeculative, IsUnverifiable);
|
||||||
0xf000: rs({{
|
0xf000: rs({{
|
||||||
Ra = xc->readIntrFlag();
|
Ra = xc->readIntrFlag();
|
||||||
xc->setIntrFlag(1);
|
xc->setIntrFlag(1);
|
||||||
}}, IsNonSpeculative);
|
}}, IsNonSpeculative, IsUnverifiable);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
format FailUnimpl {
|
format FailUnimpl {
|
||||||
|
@ -701,7 +701,7 @@ decode OPCODE default Unknown::unknown() {
|
||||||
}}, IsNonSpeculative);
|
}}, IsNonSpeculative);
|
||||||
0x83: callsys({{
|
0x83: callsys({{
|
||||||
xc->syscall(R0);
|
xc->syscall(R0);
|
||||||
}}, IsNonSpeculative);
|
}}, IsSerializeAfter, IsNonSpeculative);
|
||||||
// Read uniq reg into ABI return value register (r0)
|
// Read uniq reg into ABI return value register (r0)
|
||||||
0x9e: rduniq({{ R0 = Runiq; }}, IsIprAccess);
|
0x9e: rduniq({{ R0 = Runiq; }}, IsIprAccess);
|
||||||
// Write uniq reg with value from ABI arg register (r16)
|
// Write uniq reg with value from ABI arg register (r16)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2004-2005 The Regents of The University of Michigan
|
* Copyright (c) 2004-2006 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -103,6 +103,8 @@ BaseDynInst<Impl>::initVars()
|
||||||
|
|
||||||
readyRegs = 0;
|
readyRegs = 0;
|
||||||
|
|
||||||
|
instResult.integer = 0;
|
||||||
|
|
||||||
// May want to turn this into a bit vector or something.
|
// May want to turn this into a bit vector or something.
|
||||||
completed = false;
|
completed = false;
|
||||||
resultReady = false;
|
resultReady = false;
|
||||||
|
@ -242,31 +244,7 @@ template <class Impl>
|
||||||
void
|
void
|
||||||
BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags)
|
BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags)
|
||||||
{
|
{
|
||||||
// Need to create a MemReq here so we can do a translation. This
|
// Not currently supported.
|
||||||
// will casue a TLB miss trap if necessary... not sure whether
|
|
||||||
// that's the best thing to do or not. We don't really need the
|
|
||||||
// MemReq otherwise, since wh64 has no functional effect.
|
|
||||||
/*
|
|
||||||
MemReqPtr req = new MemReq(addr, thread->getXCProxy(), size, flags);
|
|
||||||
req->asid = asid;
|
|
||||||
|
|
||||||
fault = cpu->translateDataWriteReq(req);
|
|
||||||
|
|
||||||
if (fault == NoFault && !(req->flags & UNCACHEABLE)) {
|
|
||||||
// Record key MemReq parameters so we can generate another one
|
|
||||||
// just like it for the timing access without calling translate()
|
|
||||||
// again (which might mess up the TLB).
|
|
||||||
effAddr = req->vaddr;
|
|
||||||
physEffAddr = req->paddr;
|
|
||||||
memReqFlags = req->flags;
|
|
||||||
} else {
|
|
||||||
// ignore faults & accesses to uncacheable space... treat as no-op
|
|
||||||
effAddr = physEffAddr = MemReq::inval_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
storeSize = size;
|
|
||||||
storeData = 0;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -276,22 +254,7 @@ template <class Impl>
|
||||||
Fault
|
Fault
|
||||||
BaseDynInst<Impl>::copySrcTranslate(Addr src)
|
BaseDynInst<Impl>::copySrcTranslate(Addr src)
|
||||||
{
|
{
|
||||||
/*
|
// Not currently supported.
|
||||||
MemReqPtr req = new MemReq(src, thread->getXCProxy(), 64);
|
|
||||||
req->asid = asid;
|
|
||||||
|
|
||||||
// translate to physical address
|
|
||||||
Fault fault = cpu->translateDataReadReq(req);
|
|
||||||
|
|
||||||
if (fault == NoFault) {
|
|
||||||
thread->copySrcAddr = src;
|
|
||||||
thread->copySrcPhysAddr = req->paddr;
|
|
||||||
} else {
|
|
||||||
thread->copySrcAddr = 0;
|
|
||||||
thread->copySrcPhysAddr = 0;
|
|
||||||
}
|
|
||||||
return fault;
|
|
||||||
*/
|
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,26 +265,7 @@ template <class Impl>
|
||||||
Fault
|
Fault
|
||||||
BaseDynInst<Impl>::copy(Addr dest)
|
BaseDynInst<Impl>::copy(Addr dest)
|
||||||
{
|
{
|
||||||
/*
|
// Not currently supported.
|
||||||
uint8_t data[64];
|
|
||||||
FunctionalMemory *mem = thread->mem;
|
|
||||||
assert(thread->copySrcPhysAddr);
|
|
||||||
MemReqPtr req = new MemReq(dest, thread->getXCProxy(), 64);
|
|
||||||
req->asid = asid;
|
|
||||||
|
|
||||||
// translate to physical address
|
|
||||||
Fault fault = cpu->translateDataWriteReq(req);
|
|
||||||
|
|
||||||
if (fault == NoFault) {
|
|
||||||
Addr dest_addr = req->paddr;
|
|
||||||
// Need to read straight from memory since we have more than 8 bytes.
|
|
||||||
req->paddr = thread->copySrcPhysAddr;
|
|
||||||
mem->read(req, data);
|
|
||||||
req->paddr = dest_addr;
|
|
||||||
mem->write(req, data);
|
|
||||||
}
|
|
||||||
return fault;
|
|
||||||
*/
|
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2004-2005 The Regents of The University of Michigan
|
* Copyright (c) 2004-2006 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -44,12 +44,6 @@
|
||||||
#include "cpu/static_inst.hh"
|
#include "cpu/static_inst.hh"
|
||||||
#include "mem/packet.hh"
|
#include "mem/packet.hh"
|
||||||
#include "sim/system.hh"
|
#include "sim/system.hh"
|
||||||
/*
|
|
||||||
#include "encumbered/cpu/full/bpred_update.hh"
|
|
||||||
#include "encumbered/cpu/full/spec_memory.hh"
|
|
||||||
#include "encumbered/cpu/full/spec_state.hh"
|
|
||||||
#include "encumbered/mem/functional/main.hh"
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
|
@ -202,10 +196,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
Fault fault;
|
Fault fault;
|
||||||
|
|
||||||
/** The memory request. */
|
/** The memory request. */
|
||||||
// MemReqPtr req;
|
|
||||||
Request *req;
|
Request *req;
|
||||||
// Packet pkt;
|
|
||||||
|
|
||||||
|
/** Pointer to the data for the memory access. */
|
||||||
uint8_t *memData;
|
uint8_t *memData;
|
||||||
|
|
||||||
/** The effective virtual address (lds & stores only). */
|
/** The effective virtual address (lds & stores only). */
|
||||||
|
@ -288,21 +281,6 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
void initVars();
|
void initVars();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* @todo: Make this function work; currently it is a dummy function.
|
|
||||||
* @param fault Last fault.
|
|
||||||
* @param cmd Last command.
|
|
||||||
* @param addr Virtual address of access.
|
|
||||||
* @param p Memory accessed.
|
|
||||||
* @param nbytes Access size.
|
|
||||||
*/
|
|
||||||
// void
|
|
||||||
// trace_mem(Fault fault,
|
|
||||||
// MemCmd cmd,
|
|
||||||
// Addr addr,
|
|
||||||
// void *p,
|
|
||||||
// int nbytes);
|
|
||||||
|
|
||||||
/** Dumps out contents of this BaseDynInst. */
|
/** Dumps out contents of this BaseDynInst. */
|
||||||
void dump();
|
void dump();
|
||||||
|
|
||||||
|
@ -439,11 +417,13 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
/** Returns the result of a floating point (double) instruction. */
|
/** Returns the result of a floating point (double) instruction. */
|
||||||
double readDoubleResult() { return instResult.dbl; }
|
double readDoubleResult() { return instResult.dbl; }
|
||||||
|
|
||||||
|
/** Records an integer register being set to a value. */
|
||||||
void setIntReg(const StaticInst *si, int idx, uint64_t val)
|
void setIntReg(const StaticInst *si, int idx, uint64_t val)
|
||||||
{
|
{
|
||||||
instResult.integer = val;
|
instResult.integer = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Records an fp register being set to a value. */
|
||||||
void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
|
void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
|
||||||
{
|
{
|
||||||
if (width == 32)
|
if (width == 32)
|
||||||
|
@ -454,16 +434,19 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
panic("Unsupported width!");
|
panic("Unsupported width!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Records an fp register being set to a value. */
|
||||||
void setFloatReg(const StaticInst *si, int idx, FloatReg val)
|
void setFloatReg(const StaticInst *si, int idx, FloatReg val)
|
||||||
{
|
{
|
||||||
instResult.fp = val;
|
instResult.fp = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Records an fp register being set to an integer value. */
|
||||||
void setFloatRegBits(const StaticInst *si, int idx, uint64_t val, int width)
|
void setFloatRegBits(const StaticInst *si, int idx, uint64_t val, int width)
|
||||||
{
|
{
|
||||||
instResult.integer = val;
|
instResult.integer = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Records an fp register being set to an integer value. */
|
||||||
void setFloatRegBits(const StaticInst *si, int idx, uint64_t val)
|
void setFloatRegBits(const StaticInst *si, int idx, uint64_t val)
|
||||||
{
|
{
|
||||||
instResult.integer = val;
|
instResult.integer = val;
|
||||||
|
@ -590,14 +573,15 @@ class BaseDynInst : public FastAlloc, public RefCounted
|
||||||
void setNextPC(uint64_t val)
|
void setNextPC(uint64_t val)
|
||||||
{
|
{
|
||||||
nextPC = val;
|
nextPC = val;
|
||||||
// instResult.integer = val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sets the ASID. */
|
||||||
void setASID(short addr_space_id) { asid = addr_space_id; }
|
void setASID(short addr_space_id) { asid = addr_space_id; }
|
||||||
|
|
||||||
void setThread(unsigned tid) { threadNumber = tid; }
|
/** Sets the thread id. */
|
||||||
|
void setTid(unsigned tid) { threadNumber = tid; }
|
||||||
|
|
||||||
void setState(ImplState *state) { thread = state; }
|
void setThreadState(ImplState *state) { thread = state; }
|
||||||
|
|
||||||
/** Returns the thread context.
|
/** Returns the thread context.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -85,6 +85,8 @@ CheckerCPU::CheckerCPU(Params *p)
|
||||||
#else
|
#else
|
||||||
process = p->process;
|
process = p->process;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
result.integer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckerCPU::~CheckerCPU()
|
CheckerCPU::~CheckerCPU()
|
||||||
|
|
|
@ -92,11 +92,6 @@ Param<unsigned> commitToIEWDelay;
|
||||||
Param<unsigned> renameToIEWDelay;
|
Param<unsigned> renameToIEWDelay;
|
||||||
Param<unsigned> issueToExecuteDelay;
|
Param<unsigned> issueToExecuteDelay;
|
||||||
Param<unsigned> issueWidth;
|
Param<unsigned> issueWidth;
|
||||||
Param<unsigned> executeWidth;
|
|
||||||
Param<unsigned> executeIntWidth;
|
|
||||||
Param<unsigned> executeFloatWidth;
|
|
||||||
Param<unsigned> executeBranchWidth;
|
|
||||||
Param<unsigned> executeMemoryWidth;
|
|
||||||
SimObjectParam<FUPool *> fuPool;
|
SimObjectParam<FUPool *> fuPool;
|
||||||
|
|
||||||
Param<unsigned> iewToCommitDelay;
|
Param<unsigned> iewToCommitDelay;
|
||||||
|
@ -213,11 +208,6 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
|
||||||
INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
|
INIT_PARAM(issueToExecuteDelay, "Issue to execute delay (internal"
|
||||||
"to the IEW stage)"),
|
"to the IEW stage)"),
|
||||||
INIT_PARAM(issueWidth, "Issue width"),
|
INIT_PARAM(issueWidth, "Issue width"),
|
||||||
INIT_PARAM(executeWidth, "Execute width"),
|
|
||||||
INIT_PARAM(executeIntWidth, "Integer execute width"),
|
|
||||||
INIT_PARAM(executeFloatWidth, "Floating point execute width"),
|
|
||||||
INIT_PARAM(executeBranchWidth, "Branch execute width"),
|
|
||||||
INIT_PARAM(executeMemoryWidth, "Memory execute width"),
|
|
||||||
INIT_PARAM_DFLT(fuPool, "Functional unit pool", NULL),
|
INIT_PARAM_DFLT(fuPool, "Functional unit pool", NULL),
|
||||||
|
|
||||||
INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
|
INIT_PARAM(iewToCommitDelay, "Issue/Execute/Writeback to commit "
|
||||||
|
@ -344,11 +334,6 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
|
||||||
params->renameToIEWDelay = renameToIEWDelay;
|
params->renameToIEWDelay = renameToIEWDelay;
|
||||||
params->issueToExecuteDelay = issueToExecuteDelay;
|
params->issueToExecuteDelay = issueToExecuteDelay;
|
||||||
params->issueWidth = issueWidth;
|
params->issueWidth = issueWidth;
|
||||||
params->executeWidth = executeWidth;
|
|
||||||
params->executeIntWidth = executeIntWidth;
|
|
||||||
params->executeFloatWidth = executeFloatWidth;
|
|
||||||
params->executeBranchWidth = executeBranchWidth;
|
|
||||||
params->executeMemoryWidth = executeMemoryWidth;
|
|
||||||
params->fuPool = fuPool;
|
params->fuPool = fuPool;
|
||||||
|
|
||||||
params->iewToCommitDelay = iewToCommitDelay;
|
params->iewToCommitDelay = iewToCommitDelay;
|
||||||
|
|
|
@ -105,11 +105,6 @@ class AlphaSimpleParams : public BaseFullCPU::Params
|
||||||
unsigned renameToIEWDelay;
|
unsigned renameToIEWDelay;
|
||||||
unsigned issueToExecuteDelay;
|
unsigned issueToExecuteDelay;
|
||||||
unsigned issueWidth;
|
unsigned issueWidth;
|
||||||
unsigned executeWidth;
|
|
||||||
unsigned executeIntWidth;
|
|
||||||
unsigned executeFloatWidth;
|
|
||||||
unsigned executeBranchWidth;
|
|
||||||
unsigned executeMemoryWidth;
|
|
||||||
FUPool *fuPool;
|
FUPool *fuPool;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -365,11 +365,6 @@ class DefaultCommit
|
||||||
*/
|
*/
|
||||||
unsigned renameWidth;
|
unsigned renameWidth;
|
||||||
|
|
||||||
/** IEW width, in instructions. Used so ROB knows how many
|
|
||||||
* instructions to get from the IEW instruction queue.
|
|
||||||
*/
|
|
||||||
unsigned iewWidth;
|
|
||||||
|
|
||||||
/** Commit width, in instructions. */
|
/** Commit width, in instructions. */
|
||||||
unsigned commitWidth;
|
unsigned commitWidth;
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,6 @@ DefaultCommit<Impl>::DefaultCommit(Params *params)
|
||||||
renameToROBDelay(params->renameToROBDelay),
|
renameToROBDelay(params->renameToROBDelay),
|
||||||
fetchToCommitDelay(params->commitToFetchDelay),
|
fetchToCommitDelay(params->commitToFetchDelay),
|
||||||
renameWidth(params->renameWidth),
|
renameWidth(params->renameWidth),
|
||||||
iewWidth(params->executeWidth),
|
|
||||||
commitWidth(params->commitWidth),
|
commitWidth(params->commitWidth),
|
||||||
numThreads(params->numberOfThreads),
|
numThreads(params->numberOfThreads),
|
||||||
switchPending(false),
|
switchPending(false),
|
||||||
|
@ -205,19 +204,6 @@ DefaultCommit<Impl>::regStats()
|
||||||
.flags(total)
|
.flags(total)
|
||||||
;
|
;
|
||||||
|
|
||||||
//
|
|
||||||
// Commit-Eligible instructions...
|
|
||||||
//
|
|
||||||
// -> The number of instructions eligible to commit in those
|
|
||||||
// cycles where we reached our commit BW limit (less the number
|
|
||||||
// actually committed)
|
|
||||||
//
|
|
||||||
// -> The average value is computed over ALL CYCLES... not just
|
|
||||||
// the BW limited cycles
|
|
||||||
//
|
|
||||||
// -> The standard deviation is computed only over cycles where
|
|
||||||
// we reached the BW limit
|
|
||||||
//
|
|
||||||
commitEligible
|
commitEligible
|
||||||
.init(cpu->number_of_threads)
|
.init(cpu->number_of_threads)
|
||||||
.name(name() + ".COM:bw_limited")
|
.name(name() + ".COM:bw_limited")
|
||||||
|
@ -434,7 +420,7 @@ DefaultCommit<Impl>::setNextStatus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(squashes == squashCounter);
|
squashCounter = squashes;
|
||||||
|
|
||||||
// If commit is currently squashing, then it will have activity for the
|
// If commit is currently squashing, then it will have activity for the
|
||||||
// next cycle. Set its next status as active.
|
// next cycle. Set its next status as active.
|
||||||
|
@ -539,8 +525,6 @@ DefaultCommit<Impl>::squashFromTrap(unsigned tid)
|
||||||
|
|
||||||
commitStatus[tid] = ROBSquashing;
|
commitStatus[tid] = ROBSquashing;
|
||||||
cpu->activityThisCycle();
|
cpu->activityThisCycle();
|
||||||
|
|
||||||
++squashCounter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
|
@ -558,8 +542,6 @@ DefaultCommit<Impl>::squashFromTC(unsigned tid)
|
||||||
cpu->activityThisCycle();
|
cpu->activityThisCycle();
|
||||||
|
|
||||||
tcSquash[tid] = false;
|
tcSquash[tid] = false;
|
||||||
|
|
||||||
++squashCounter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
|
@ -585,10 +567,12 @@ DefaultCommit<Impl>::tick()
|
||||||
|
|
||||||
if (rob->isDoneSquashing(tid)) {
|
if (rob->isDoneSquashing(tid)) {
|
||||||
commitStatus[tid] = Running;
|
commitStatus[tid] = Running;
|
||||||
--squashCounter;
|
|
||||||
} else {
|
} else {
|
||||||
DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any"
|
DPRINTF(Commit,"[tid:%u]: Still Squashing, cannot commit any"
|
||||||
"insts this cycle.\n", tid);
|
"insts this cycle.\n", tid);
|
||||||
|
rob->doSquash(tid);
|
||||||
|
toIEW->commitInfo[tid].robSquashing = true;
|
||||||
|
wroteToTimeBuffer = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -694,29 +678,7 @@ DefaultCommit<Impl>::commit()
|
||||||
|
|
||||||
while (threads != (*activeThreads).end()) {
|
while (threads != (*activeThreads).end()) {
|
||||||
unsigned tid = *threads++;
|
unsigned tid = *threads++;
|
||||||
/*
|
|
||||||
if (fromFetch->fetchFault && commitStatus[0] != TrapPending) {
|
|
||||||
// Record the fault. Wait until it's empty in the ROB.
|
|
||||||
// Then handle the trap. Ignore it if there's already a
|
|
||||||
// trap pending as fetch will be redirected.
|
|
||||||
fetchFault = fromFetch->fetchFault;
|
|
||||||
fetchFaultTick = curTick + fetchTrapLatency;
|
|
||||||
commitStatus[0] = FetchTrapPending;
|
|
||||||
DPRINTF(Commit, "Fault from fetch recorded. Will trap if the "
|
|
||||||
"ROB empties without squashing the fault.\n");
|
|
||||||
fetchTrapWait = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch may tell commit to clear the trap if it's been squashed.
|
|
||||||
if (fromFetch->clearFetchFault) {
|
|
||||||
DPRINTF(Commit, "Received clear fetch fault signal\n");
|
|
||||||
fetchTrapWait = 0;
|
|
||||||
if (commitStatus[0] == FetchTrapPending) {
|
|
||||||
DPRINTF(Commit, "Clearing fault from fetch\n");
|
|
||||||
commitStatus[0] = Running;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// Not sure which one takes priority. I think if we have
|
// Not sure which one takes priority. I think if we have
|
||||||
// both, that's a bad sign.
|
// both, that's a bad sign.
|
||||||
if (trapSquash[tid] == true) {
|
if (trapSquash[tid] == true) {
|
||||||
|
@ -744,8 +706,6 @@ DefaultCommit<Impl>::commit()
|
||||||
|
|
||||||
commitStatus[tid] = ROBSquashing;
|
commitStatus[tid] = ROBSquashing;
|
||||||
|
|
||||||
++squashCounter;
|
|
||||||
|
|
||||||
// If we want to include the squashing instruction in the squash,
|
// If we want to include the squashing instruction in the squash,
|
||||||
// then use one older sequence number.
|
// then use one older sequence number.
|
||||||
InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
|
InstSeqNum squashed_inst = fromIEW->squashedSeqNum[tid];
|
||||||
|
|
|
@ -515,7 +515,7 @@ DefaultDecode<Impl>::checkSignalsAndUpdate(unsigned tid)
|
||||||
|
|
||||||
// Check ROB squash signals from commit.
|
// Check ROB squash signals from commit.
|
||||||
if (fromCommit->commitInfo[tid].robSquashing) {
|
if (fromCommit->commitInfo[tid].robSquashing) {
|
||||||
DPRINTF(Decode, "[tid:%]: ROB is still squashing.\n",tid);
|
DPRINTF(Decode, "[tid:%u]: ROB is still squashing.\n", tid);
|
||||||
|
|
||||||
// Continue to squash.
|
// Continue to squash.
|
||||||
decodeStatus[tid] = Squashing;
|
decodeStatus[tid] = Squashing;
|
||||||
|
|
|
@ -421,6 +421,7 @@ class DefaultFetch
|
||||||
Stats::Scalar<> icacheStallCycles;
|
Stats::Scalar<> icacheStallCycles;
|
||||||
/** Stat for total number of fetched instructions. */
|
/** Stat for total number of fetched instructions. */
|
||||||
Stats::Scalar<> fetchedInsts;
|
Stats::Scalar<> fetchedInsts;
|
||||||
|
/** Total number of fetched branches. */
|
||||||
Stats::Scalar<> fetchedBranches;
|
Stats::Scalar<> fetchedBranches;
|
||||||
/** Stat for total number of predicted branches. */
|
/** Stat for total number of predicted branches. */
|
||||||
Stats::Scalar<> predictedBranches;
|
Stats::Scalar<> predictedBranches;
|
||||||
|
|
|
@ -817,7 +817,7 @@ DefaultFetch<Impl>::checkSignalsAndUpdate(unsigned tid)
|
||||||
|
|
||||||
// Check ROB squash signals from commit.
|
// Check ROB squash signals from commit.
|
||||||
if (fromCommit->commitInfo[tid].robSquashing) {
|
if (fromCommit->commitInfo[tid].robSquashing) {
|
||||||
DPRINTF(Fetch, "[tid:%u]: ROB is still squashing Thread %u.\n", tid);
|
DPRINTF(Fetch, "[tid:%u]: ROB is still squashing.\n", tid);
|
||||||
|
|
||||||
// Continue to squash.
|
// Continue to squash.
|
||||||
fetchStatus[tid] = Squashing;
|
fetchStatus[tid] = Squashing;
|
||||||
|
@ -915,7 +915,11 @@ DefaultFetch<Impl>::fetch(bool &status_change)
|
||||||
|
|
||||||
bool fetch_success = fetchCacheLine(fetch_PC, fault, tid);
|
bool fetch_success = fetchCacheLine(fetch_PC, fault, tid);
|
||||||
if (!fetch_success) {
|
if (!fetch_success) {
|
||||||
++fetchMiscStallCycles;
|
if (cacheBlocked) {
|
||||||
|
++icacheStallCycles;
|
||||||
|
} else {
|
||||||
|
++fetchMiscStallCycles;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -984,11 +988,11 @@ DefaultFetch<Impl>::fetch(bool &status_change)
|
||||||
DynInstPtr instruction = new DynInst(ext_inst, fetch_PC,
|
DynInstPtr instruction = new DynInst(ext_inst, fetch_PC,
|
||||||
next_PC,
|
next_PC,
|
||||||
inst_seq, cpu);
|
inst_seq, cpu);
|
||||||
instruction->setThread(tid);
|
instruction->setTid(tid);
|
||||||
|
|
||||||
instruction->setASID(tid);
|
instruction->setASID(tid);
|
||||||
|
|
||||||
instruction->setState(cpu->thread[tid]);
|
instruction->setThreadState(cpu->thread[tid]);
|
||||||
|
|
||||||
DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x created "
|
DPRINTF(Fetch, "[tid:%i]: Instruction PC %#x created "
|
||||||
"[sn:%lli]\n",
|
"[sn:%lli]\n",
|
||||||
|
@ -1065,11 +1069,11 @@ DefaultFetch<Impl>::fetch(bool &status_change)
|
||||||
next_PC,
|
next_PC,
|
||||||
inst_seq, cpu);
|
inst_seq, cpu);
|
||||||
instruction->setPredTarg(next_PC + instSize);
|
instruction->setPredTarg(next_PC + instSize);
|
||||||
instruction->setThread(tid);
|
instruction->setTid(tid);
|
||||||
|
|
||||||
instruction->setASID(tid);
|
instruction->setASID(tid);
|
||||||
|
|
||||||
instruction->setState(cpu->thread[tid]);
|
instruction->setThreadState(cpu->thread[tid]);
|
||||||
|
|
||||||
instruction->traceData = NULL;
|
instruction->traceData = NULL;
|
||||||
|
|
||||||
|
|
|
@ -261,6 +261,9 @@ class DefaultIEW
|
||||||
/** Processes inputs and changes state accordingly. */
|
/** Processes inputs and changes state accordingly. */
|
||||||
void checkSignalsAndUpdate(unsigned tid);
|
void checkSignalsAndUpdate(unsigned tid);
|
||||||
|
|
||||||
|
/** Removes instructions from rename from a thread's instruction list. */
|
||||||
|
void emptyRenameInsts(unsigned tid);
|
||||||
|
|
||||||
/** Sorts instructions coming from rename into lists separated by thread. */
|
/** Sorts instructions coming from rename into lists separated by thread. */
|
||||||
void sortInsts();
|
void sortInsts();
|
||||||
|
|
||||||
|
@ -390,11 +393,6 @@ class DefaultIEW
|
||||||
/** Width of issue, in instructions. */
|
/** Width of issue, in instructions. */
|
||||||
unsigned issueWidth;
|
unsigned issueWidth;
|
||||||
|
|
||||||
/** Width of execute, in instructions. Might make more sense to break
|
|
||||||
* down into FP vs int.
|
|
||||||
*/
|
|
||||||
unsigned executeWidth;
|
|
||||||
|
|
||||||
/** Index into queue of instructions being written back. */
|
/** Index into queue of instructions being written back. */
|
||||||
unsigned wbNumInst;
|
unsigned wbNumInst;
|
||||||
|
|
||||||
|
@ -439,14 +437,6 @@ class DefaultIEW
|
||||||
Stats::Scalar<> iewIQFullEvents;
|
Stats::Scalar<> iewIQFullEvents;
|
||||||
/** Stat for number of times the LSQ becomes full. */
|
/** Stat for number of times the LSQ becomes full. */
|
||||||
Stats::Scalar<> iewLSQFullEvents;
|
Stats::Scalar<> iewLSQFullEvents;
|
||||||
/** Stat for total number of executed instructions. */
|
|
||||||
Stats::Scalar<> iewExecutedInsts;
|
|
||||||
/** Stat for total number of executed load instructions. */
|
|
||||||
Stats::Vector<> iewExecLoadInsts;
|
|
||||||
/** Stat for total number of executed store instructions. */
|
|
||||||
// Stats::Scalar<> iewExecStoreInsts;
|
|
||||||
/** Stat for total number of squashed instructions skipped at execute. */
|
|
||||||
Stats::Scalar<> iewExecSquashedInsts;
|
|
||||||
/** Stat for total number of memory ordering violation events. */
|
/** Stat for total number of memory ordering violation events. */
|
||||||
Stats::Scalar<> memOrderViolationEvents;
|
Stats::Scalar<> memOrderViolationEvents;
|
||||||
/** Stat for total number of incorrect predicted taken branches. */
|
/** Stat for total number of incorrect predicted taken branches. */
|
||||||
|
@ -456,28 +446,25 @@ class DefaultIEW
|
||||||
/** Stat for total number of mispredicted branches detected at execute. */
|
/** Stat for total number of mispredicted branches detected at execute. */
|
||||||
Stats::Formula branchMispredicts;
|
Stats::Formula branchMispredicts;
|
||||||
|
|
||||||
|
/** Stat for total number of executed instructions. */
|
||||||
|
Stats::Scalar<> iewExecutedInsts;
|
||||||
|
/** Stat for total number of executed load instructions. */
|
||||||
|
Stats::Vector<> iewExecLoadInsts;
|
||||||
|
/** Stat for total number of squashed instructions skipped at execute. */
|
||||||
|
Stats::Scalar<> iewExecSquashedInsts;
|
||||||
/** Number of executed software prefetches. */
|
/** Number of executed software prefetches. */
|
||||||
Stats::Vector<> exeSwp;
|
Stats::Vector<> iewExecutedSwp;
|
||||||
/** Number of executed nops. */
|
/** Number of executed nops. */
|
||||||
Stats::Vector<> exeNop;
|
Stats::Vector<> iewExecutedNop;
|
||||||
/** Number of executed meomory references. */
|
/** Number of executed meomory references. */
|
||||||
Stats::Vector<> exeRefs;
|
Stats::Vector<> iewExecutedRefs;
|
||||||
/** Number of executed branches. */
|
/** Number of executed branches. */
|
||||||
Stats::Vector<> exeBranches;
|
Stats::Vector<> iewExecutedBranches;
|
||||||
|
|
||||||
// Stats::Vector<> issued_ops;
|
|
||||||
/*
|
|
||||||
Stats::Vector<> stat_fu_busy;
|
|
||||||
Stats::Vector2d<> stat_fuBusy;
|
|
||||||
Stats::Vector<> dist_unissued;
|
|
||||||
Stats::Vector2d<> stat_issued_inst_type;
|
|
||||||
*/
|
|
||||||
/** Number of instructions issued per cycle. */
|
|
||||||
Stats::Formula issueRate;
|
|
||||||
/** Number of executed store instructions. */
|
/** Number of executed store instructions. */
|
||||||
Stats::Formula iewExecStoreInsts;
|
Stats::Formula iewExecStoreInsts;
|
||||||
// Stats::Formula issue_op_rate;
|
/** Number of instructions executed per cycle. */
|
||||||
// Stats::Formula fu_busy_rate;
|
Stats::Formula iewExecRate;
|
||||||
|
|
||||||
/** Number of instructions sent to commit. */
|
/** Number of instructions sent to commit. */
|
||||||
Stats::Vector<> iewInstsToCommit;
|
Stats::Vector<> iewInstsToCommit;
|
||||||
/** Number of instructions that writeback. */
|
/** Number of instructions that writeback. */
|
||||||
|
@ -490,7 +477,6 @@ class DefaultIEW
|
||||||
* to resource contention.
|
* to resource contention.
|
||||||
*/
|
*/
|
||||||
Stats::Vector<> wbPenalized;
|
Stats::Vector<> wbPenalized;
|
||||||
|
|
||||||
/** Number of instructions per cycle written back. */
|
/** Number of instructions per cycle written back. */
|
||||||
Stats::Formula wbRate;
|
Stats::Formula wbRate;
|
||||||
/** Average number of woken instructions per writeback. */
|
/** Average number of woken instructions per writeback. */
|
||||||
|
|
|
@ -52,7 +52,6 @@ DefaultIEW<Impl>::DefaultIEW(Params *params)
|
||||||
issueToExecuteDelay(params->issueToExecuteDelay),
|
issueToExecuteDelay(params->issueToExecuteDelay),
|
||||||
issueReadWidth(params->issueWidth),
|
issueReadWidth(params->issueWidth),
|
||||||
issueWidth(params->issueWidth),
|
issueWidth(params->issueWidth),
|
||||||
executeWidth(params->executeWidth),
|
|
||||||
numThreads(params->numberOfThreads),
|
numThreads(params->numberOfThreads),
|
||||||
switchedOut(false)
|
switchedOut(false)
|
||||||
{
|
{
|
||||||
|
@ -94,6 +93,7 @@ DefaultIEW<Impl>::regStats()
|
||||||
using namespace Stats;
|
using namespace Stats;
|
||||||
|
|
||||||
instQueue.regStats();
|
instQueue.regStats();
|
||||||
|
ldstQueue.regStats();
|
||||||
|
|
||||||
iewIdleCycles
|
iewIdleCycles
|
||||||
.name(name() + ".iewIdleCycles")
|
.name(name() + ".iewIdleCycles")
|
||||||
|
@ -139,20 +139,6 @@ DefaultIEW<Impl>::regStats()
|
||||||
.name(name() + ".iewLSQFullEvents")
|
.name(name() + ".iewLSQFullEvents")
|
||||||
.desc("Number of times the LSQ has become full, causing a stall");
|
.desc("Number of times the LSQ has become full, causing a stall");
|
||||||
|
|
||||||
iewExecutedInsts
|
|
||||||
.name(name() + ".iewExecutedInsts")
|
|
||||||
.desc("Number of executed instructions");
|
|
||||||
|
|
||||||
iewExecLoadInsts
|
|
||||||
.init(cpu->number_of_threads)
|
|
||||||
.name(name() + ".iewExecLoadInsts")
|
|
||||||
.desc("Number of load instructions executed")
|
|
||||||
.flags(total);
|
|
||||||
|
|
||||||
iewExecSquashedInsts
|
|
||||||
.name(name() + ".iewExecSquashedInsts")
|
|
||||||
.desc("Number of squashed instructions skipped in execute");
|
|
||||||
|
|
||||||
memOrderViolationEvents
|
memOrderViolationEvents
|
||||||
.name(name() + ".memOrderViolationEvents")
|
.name(name() + ".memOrderViolationEvents")
|
||||||
.desc("Number of memory order violations");
|
.desc("Number of memory order violations");
|
||||||
|
@ -171,114 +157,105 @@ DefaultIEW<Impl>::regStats()
|
||||||
|
|
||||||
branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect;
|
branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect;
|
||||||
|
|
||||||
exeSwp
|
iewExecutedInsts
|
||||||
|
.name(name() + ".EXEC:insts")
|
||||||
|
.desc("Number of executed instructions");
|
||||||
|
|
||||||
|
iewExecLoadInsts
|
||||||
|
.init(cpu->number_of_threads)
|
||||||
|
.name(name() + ".EXEC:loads")
|
||||||
|
.desc("Number of load instructions executed")
|
||||||
|
.flags(total);
|
||||||
|
|
||||||
|
iewExecSquashedInsts
|
||||||
|
.name(name() + ".EXEC:squashedInsts")
|
||||||
|
.desc("Number of squashed instructions skipped in execute");
|
||||||
|
|
||||||
|
iewExecutedSwp
|
||||||
.init(cpu->number_of_threads)
|
.init(cpu->number_of_threads)
|
||||||
.name(name() + ".EXEC:swp")
|
.name(name() + ".EXEC:swp")
|
||||||
.desc("number of swp insts executed")
|
.desc("number of swp insts executed")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
|
||||||
|
|
||||||
exeNop
|
iewExecutedNop
|
||||||
.init(cpu->number_of_threads)
|
.init(cpu->number_of_threads)
|
||||||
.name(name() + ".EXEC:nop")
|
.name(name() + ".EXEC:nop")
|
||||||
.desc("number of nop insts executed")
|
.desc("number of nop insts executed")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
|
||||||
|
|
||||||
exeRefs
|
iewExecutedRefs
|
||||||
.init(cpu->number_of_threads)
|
.init(cpu->number_of_threads)
|
||||||
.name(name() + ".EXEC:refs")
|
.name(name() + ".EXEC:refs")
|
||||||
.desc("number of memory reference insts executed")
|
.desc("number of memory reference insts executed")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
|
||||||
|
|
||||||
exeBranches
|
iewExecutedBranches
|
||||||
.init(cpu->number_of_threads)
|
.init(cpu->number_of_threads)
|
||||||
.name(name() + ".EXEC:branches")
|
.name(name() + ".EXEC:branches")
|
||||||
.desc("Number of branches executed")
|
.desc("Number of branches executed")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
|
||||||
|
|
||||||
issueRate
|
|
||||||
.name(name() + ".EXEC:rate")
|
|
||||||
.desc("Inst execution rate")
|
|
||||||
.flags(total)
|
|
||||||
;
|
|
||||||
issueRate = iewExecutedInsts / cpu->numCycles;
|
|
||||||
|
|
||||||
iewExecStoreInsts
|
iewExecStoreInsts
|
||||||
.name(name() + ".EXEC:stores")
|
.name(name() + ".EXEC:stores")
|
||||||
.desc("Number of stores executed")
|
.desc("Number of stores executed")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
iewExecStoreInsts = iewExecutedRefs - iewExecLoadInsts;
|
||||||
iewExecStoreInsts = exeRefs - iewExecLoadInsts;
|
|
||||||
/*
|
iewExecRate
|
||||||
for (int i=0; i<Num_OpClasses; ++i) {
|
.name(name() + ".EXEC:rate")
|
||||||
stringstream subname;
|
.desc("Inst execution rate")
|
||||||
subname << opClassStrings[i] << "_delay";
|
.flags(total);
|
||||||
issue_delay_dist.subname(i, subname.str());
|
|
||||||
}
|
iewExecRate = iewExecutedInsts / cpu->numCycles;
|
||||||
*/
|
|
||||||
//
|
|
||||||
// Other stats
|
|
||||||
//
|
|
||||||
|
|
||||||
iewInstsToCommit
|
iewInstsToCommit
|
||||||
.init(cpu->number_of_threads)
|
.init(cpu->number_of_threads)
|
||||||
.name(name() + ".WB:sent")
|
.name(name() + ".WB:sent")
|
||||||
.desc("cumulative count of insts sent to commit")
|
.desc("cumulative count of insts sent to commit")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
|
||||||
|
|
||||||
writebackCount
|
writebackCount
|
||||||
.init(cpu->number_of_threads)
|
.init(cpu->number_of_threads)
|
||||||
.name(name() + ".WB:count")
|
.name(name() + ".WB:count")
|
||||||
.desc("cumulative count of insts written-back")
|
.desc("cumulative count of insts written-back")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
|
||||||
|
|
||||||
producerInst
|
producerInst
|
||||||
.init(cpu->number_of_threads)
|
.init(cpu->number_of_threads)
|
||||||
.name(name() + ".WB:producers")
|
.name(name() + ".WB:producers")
|
||||||
.desc("num instructions producing a value")
|
.desc("num instructions producing a value")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
|
||||||
|
|
||||||
consumerInst
|
consumerInst
|
||||||
.init(cpu->number_of_threads)
|
.init(cpu->number_of_threads)
|
||||||
.name(name() + ".WB:consumers")
|
.name(name() + ".WB:consumers")
|
||||||
.desc("num instructions consuming a value")
|
.desc("num instructions consuming a value")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
|
||||||
|
|
||||||
wbPenalized
|
wbPenalized
|
||||||
.init(cpu->number_of_threads)
|
.init(cpu->number_of_threads)
|
||||||
.name(name() + ".WB:penalized")
|
.name(name() + ".WB:penalized")
|
||||||
.desc("number of instrctions required to write to 'other' IQ")
|
.desc("number of instrctions required to write to 'other' IQ")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
|
||||||
|
|
||||||
wbPenalizedRate
|
wbPenalizedRate
|
||||||
.name(name() + ".WB:penalized_rate")
|
.name(name() + ".WB:penalized_rate")
|
||||||
.desc ("fraction of instructions written-back that wrote to 'other' IQ")
|
.desc ("fraction of instructions written-back that wrote to 'other' IQ")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
|
||||||
|
|
||||||
wbPenalizedRate = wbPenalized / writebackCount;
|
wbPenalizedRate = wbPenalized / writebackCount;
|
||||||
|
|
||||||
wbFanout
|
wbFanout
|
||||||
.name(name() + ".WB:fanout")
|
.name(name() + ".WB:fanout")
|
||||||
.desc("average fanout of values written-back")
|
.desc("average fanout of values written-back")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
|
||||||
|
|
||||||
wbFanout = producerInst / consumerInst;
|
wbFanout = producerInst / consumerInst;
|
||||||
|
|
||||||
wbRate
|
wbRate
|
||||||
.name(name() + ".WB:rate")
|
.name(name() + ".WB:rate")
|
||||||
.desc("insts written-back per cycle")
|
.desc("insts written-back per cycle")
|
||||||
.flags(total)
|
.flags(total);
|
||||||
;
|
|
||||||
wbRate = writebackCount / cpu->numCycles;
|
wbRate = writebackCount / cpu->numCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,16 +433,7 @@ DefaultIEW<Impl>::squash(unsigned tid)
|
||||||
skidBuffer[tid].pop();
|
skidBuffer[tid].pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!insts[tid].empty()) {
|
emptyRenameInsts(tid);
|
||||||
if (insts[tid].front()->isLoad() ||
|
|
||||||
insts[tid].front()->isStore() ) {
|
|
||||||
toRename->iewInfo[tid].dispatchedToLSQ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
toRename->iewInfo[tid].dispatched++;
|
|
||||||
|
|
||||||
insts[tid].pop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Impl>
|
template<class Impl>
|
||||||
|
@ -799,10 +767,12 @@ DefaultIEW<Impl>::checkSignalsAndUpdate(unsigned tid)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fromCommit->commitInfo[tid].robSquashing) {
|
if (fromCommit->commitInfo[tid].robSquashing) {
|
||||||
DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n");
|
DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n", tid);
|
||||||
|
|
||||||
dispatchStatus[tid] = Squashing;
|
dispatchStatus[tid] = Squashing;
|
||||||
|
|
||||||
|
emptyRenameInsts(tid);
|
||||||
|
wroteToTimeBuffer = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -851,6 +821,22 @@ DefaultIEW<Impl>::sortInsts()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Impl>
|
||||||
|
void
|
||||||
|
DefaultIEW<Impl>::emptyRenameInsts(unsigned tid)
|
||||||
|
{
|
||||||
|
while (!insts[tid].empty()) {
|
||||||
|
if (insts[tid].front()->isLoad() ||
|
||||||
|
insts[tid].front()->isStore() ) {
|
||||||
|
toRename->iewInfo[tid].dispatchedToLSQ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
toRename->iewInfo[tid].dispatched++;
|
||||||
|
|
||||||
|
insts[tid].pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
DefaultIEW<Impl>::wakeCPU()
|
DefaultIEW<Impl>::wakeCPU()
|
||||||
|
@ -1090,7 +1076,7 @@ DefaultIEW<Impl>::dispatchInsts(unsigned tid)
|
||||||
|
|
||||||
instQueue.recordProducer(inst);
|
instQueue.recordProducer(inst);
|
||||||
|
|
||||||
exeNop[tid]++;
|
iewExecutedNop[tid]++;
|
||||||
|
|
||||||
add_to_iq = false;
|
add_to_iq = false;
|
||||||
} else if (inst->isExecuted()) {
|
} else if (inst->isExecuted()) {
|
||||||
|
@ -1501,9 +1487,9 @@ DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst)
|
||||||
//
|
//
|
||||||
#ifdef TARGET_ALPHA
|
#ifdef TARGET_ALPHA
|
||||||
if (inst->isDataPrefetch())
|
if (inst->isDataPrefetch())
|
||||||
exeSwp[thread_number]++;
|
iewExecutedSwp[thread_number]++;
|
||||||
else
|
else
|
||||||
iewExecutedInsts++;
|
iewIewExecutedcutedInsts++;
|
||||||
#else
|
#else
|
||||||
iewExecutedInsts++;
|
iewExecutedInsts++;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1512,13 +1498,13 @@ DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst)
|
||||||
// Control operations
|
// Control operations
|
||||||
//
|
//
|
||||||
if (inst->isControl())
|
if (inst->isControl())
|
||||||
exeBranches[thread_number]++;
|
iewExecutedBranches[thread_number]++;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Memory operations
|
// Memory operations
|
||||||
//
|
//
|
||||||
if (inst->isMemRef()) {
|
if (inst->isMemRef()) {
|
||||||
exeRefs[thread_number]++;
|
iewExecutedRefs[thread_number]++;
|
||||||
|
|
||||||
if (inst->isLoad()) {
|
if (inst->isLoad()) {
|
||||||
iewExecLoadInsts[thread_number]++;
|
iewExecLoadInsts[thread_number]++;
|
||||||
|
|
|
@ -474,12 +474,17 @@ class InstructionQueue
|
||||||
/** Stat for number of non-speculative instructions removed due to a squash.
|
/** Stat for number of non-speculative instructions removed due to a squash.
|
||||||
*/
|
*/
|
||||||
Stats::Scalar<> iqSquashedNonSpecRemoved;
|
Stats::Scalar<> iqSquashedNonSpecRemoved;
|
||||||
|
// Also include number of instructions rescheduled and replayed.
|
||||||
|
|
||||||
/** Distribution of number of instructions in the queue. */
|
/** Distribution of number of instructions in the queue.
|
||||||
|
* @todo: Need to create struct to track the entry time for each
|
||||||
|
* instruction. */
|
||||||
Stats::VectorDistribution<> queueResDist;
|
Stats::VectorDistribution<> queueResDist;
|
||||||
/** Distribution of the number of instructions issued. */
|
/** Distribution of the number of instructions issued. */
|
||||||
Stats::Distribution<> numIssuedDist;
|
Stats::Distribution<> numIssuedDist;
|
||||||
/** Distribution of the cycles it takes to issue an instruction. */
|
/** Distribution of the cycles it takes to issue an instruction.
|
||||||
|
* @todo: Need to create struct to track the ready time for each
|
||||||
|
* instruction. */
|
||||||
Stats::VectorDistribution<> issueDelayDist;
|
Stats::VectorDistribution<> issueDelayDist;
|
||||||
|
|
||||||
/** Number of times an instruction could not be issued because a
|
/** Number of times an instruction could not be issued because a
|
||||||
|
@ -492,8 +497,7 @@ class InstructionQueue
|
||||||
|
|
||||||
/** Number of instructions issued per cycle. */
|
/** Number of instructions issued per cycle. */
|
||||||
Stats::Formula issueRate;
|
Stats::Formula issueRate;
|
||||||
// Stats::Formula issue_stores;
|
|
||||||
// Stats::Formula issue_op_rate;
|
|
||||||
/** Number of times the FU was busy. */
|
/** Number of times the FU was busy. */
|
||||||
Stats::Vector<> fuBusy;
|
Stats::Vector<> fuBusy;
|
||||||
/** Number of times the FU was busy per instruction issued. */
|
/** Number of times the FU was busy per instruction issued. */
|
||||||
|
|
|
@ -289,22 +289,7 @@ InstructionQueue<Impl>::regStats()
|
||||||
.flags(total)
|
.flags(total)
|
||||||
;
|
;
|
||||||
issueRate = iqInstsIssued / cpu->numCycles;
|
issueRate = iqInstsIssued / cpu->numCycles;
|
||||||
/*
|
|
||||||
issue_stores
|
|
||||||
.name(name() + ".ISSUE:stores")
|
|
||||||
.desc("Number of stores issued")
|
|
||||||
.flags(total)
|
|
||||||
;
|
|
||||||
issue_stores = exe_refs - exe_loads;
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
issue_op_rate
|
|
||||||
.name(name() + ".ISSUE:op_rate")
|
|
||||||
.desc("Operation issue rate")
|
|
||||||
.flags(total)
|
|
||||||
;
|
|
||||||
issue_op_rate = issued_ops / numCycles;
|
|
||||||
*/
|
|
||||||
statFuBusy
|
statFuBusy
|
||||||
.init(Num_OpClasses)
|
.init(Num_OpClasses)
|
||||||
.name(name() + ".ISSUE:fu_full")
|
.name(name() + ".ISSUE:fu_full")
|
||||||
|
|
|
@ -62,6 +62,9 @@ class LSQ {
|
||||||
/** Returns the name of the LSQ. */
|
/** Returns the name of the LSQ. */
|
||||||
std::string name() const;
|
std::string name() const;
|
||||||
|
|
||||||
|
/** Registers statistics of each LSQ unit. */
|
||||||
|
void regStats();
|
||||||
|
|
||||||
/** Sets the pointer to the list of active threads. */
|
/** Sets the pointer to the list of active threads. */
|
||||||
void setActiveThreads(std::list<unsigned> *at_ptr);
|
void setActiveThreads(std::list<unsigned> *at_ptr);
|
||||||
/** Sets the CPU pointer. */
|
/** Sets the CPU pointer. */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2004-2006 The Regents of The University of Michigan
|
* Copyright (c) 2005-2006 The Regents of The University of Michigan
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -106,6 +106,16 @@ LSQ<Impl>::name() const
|
||||||
return iewStage->name() + ".lsq";
|
return iewStage->name() + ".lsq";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Impl>
|
||||||
|
void
|
||||||
|
LSQ<Impl>::regStats()
|
||||||
|
{
|
||||||
|
//Initialize LSQs
|
||||||
|
for (int tid=0; tid < numThreads; tid++) {
|
||||||
|
thread[tid].regStats();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<class Impl>
|
template<class Impl>
|
||||||
void
|
void
|
||||||
LSQ<Impl>::setActiveThreads(list<unsigned> *at_ptr)
|
LSQ<Impl>::setActiveThreads(list<unsigned> *at_ptr)
|
||||||
|
|
|
@ -77,6 +77,9 @@ class LSQUnit {
|
||||||
/** Returns the name of the LSQ unit. */
|
/** Returns the name of the LSQ unit. */
|
||||||
std::string name() const;
|
std::string name() const;
|
||||||
|
|
||||||
|
/** Registers statistics. */
|
||||||
|
void regStats();
|
||||||
|
|
||||||
/** Sets the CPU pointer. */
|
/** Sets the CPU pointer. */
|
||||||
void setCPU(FullCPU *cpu_ptr);
|
void setCPU(FullCPU *cpu_ptr);
|
||||||
|
|
||||||
|
@ -127,9 +130,6 @@ class LSQUnit {
|
||||||
|
|
||||||
void completeDataAccess(PacketPtr pkt);
|
void completeDataAccess(PacketPtr pkt);
|
||||||
|
|
||||||
// @todo: Include stats in the LSQ unit.
|
|
||||||
//void regStats();
|
|
||||||
|
|
||||||
/** Clears all the entries in the LQ. */
|
/** Clears all the entries in the LQ. */
|
||||||
void clearLQ();
|
void clearLQ();
|
||||||
|
|
||||||
|
@ -443,25 +443,35 @@ class LSQUnit {
|
||||||
// Will also need how many read/write ports the Dcache has. Or keep track
|
// Will also need how many read/write ports the Dcache has. Or keep track
|
||||||
// of that in stage that is one level up, and only call executeLoad/Store
|
// of that in stage that is one level up, and only call executeLoad/Store
|
||||||
// the appropriate number of times.
|
// the appropriate number of times.
|
||||||
/*
|
|
||||||
// total number of loads forwaded from LSQ stores
|
|
||||||
Stats::Vector<> lsq_forw_loads;
|
|
||||||
|
|
||||||
// total number of loads ignored due to invalid addresses
|
/** Total number of loads forwaded from LSQ stores. */
|
||||||
Stats::Vector<> inv_addr_loads;
|
Stats::Scalar<> lsqForwLoads;
|
||||||
|
|
||||||
// total number of software prefetches ignored due to invalid addresses
|
/** Total number of loads ignored due to invalid addresses. */
|
||||||
Stats::Vector<> inv_addr_swpfs;
|
Stats::Scalar<> invAddrLoads;
|
||||||
|
|
||||||
// total non-speculative bogus addresses seen (debug var)
|
/** Total number of squashed loads. */
|
||||||
Counter sim_invalid_addrs;
|
Stats::Scalar<> lsqSquashedLoads;
|
||||||
Stats::Vector<> fu_busy; //cumulative fu busy
|
|
||||||
|
|
||||||
// ready loads blocked due to memory disambiguation
|
/** Total number of responses from the memory system that are
|
||||||
Stats::Vector<> lsq_blocked_loads;
|
* ignored due to the instruction already being squashed. */
|
||||||
|
Stats::Scalar<> lsqIgnoredResponses;
|
||||||
|
|
||||||
|
/** Total number of squashed stores. */
|
||||||
|
Stats::Scalar<> lsqSquashedStores;
|
||||||
|
|
||||||
|
/** Total number of software prefetches ignored due to invalid addresses. */
|
||||||
|
Stats::Scalar<> invAddrSwpfs;
|
||||||
|
|
||||||
|
/** Ready loads blocked due to partial store-forwarding. */
|
||||||
|
Stats::Scalar<> lsqBlockedLoads;
|
||||||
|
|
||||||
|
/** Number of loads that were rescheduled. */
|
||||||
|
Stats::Scalar<> lsqRescheduledLoads;
|
||||||
|
|
||||||
|
/** Number of times the LSQ is blocked due to the cache. */
|
||||||
|
Stats::Scalar<> lsqCacheBlocked;
|
||||||
|
|
||||||
Stats::Scalar<> lsqInversion;
|
|
||||||
*/
|
|
||||||
public:
|
public:
|
||||||
/** Executes the load at the given index. */
|
/** Executes the load at the given index. */
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -519,6 +529,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
if (req->getFlags() & UNCACHEABLE &&
|
if (req->getFlags() & UNCACHEABLE &&
|
||||||
(load_idx != loadHead || !load_inst->reachedCommit)) {
|
(load_idx != loadHead || !load_inst->reachedCommit)) {
|
||||||
iewStage->rescheduleMemInst(load_inst);
|
iewStage->rescheduleMemInst(load_inst);
|
||||||
|
++lsqRescheduledLoads;
|
||||||
return TheISA::genMachineCheckFault();
|
return TheISA::genMachineCheckFault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +609,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
// @todo: Need to make this a parameter.
|
// @todo: Need to make this a parameter.
|
||||||
wb->schedule(curTick);
|
wb->schedule(curTick);
|
||||||
|
|
||||||
// Should keep track of stat for forwarded data
|
++lsqForwLoads;
|
||||||
return NoFault;
|
return NoFault;
|
||||||
} else if ((store_has_lower_limit && lower_load_has_store_part) ||
|
} else if ((store_has_lower_limit && lower_load_has_store_part) ||
|
||||||
(store_has_upper_limit && upper_load_has_store_part) ||
|
(store_has_upper_limit && upper_load_has_store_part) ||
|
||||||
|
@ -626,6 +637,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
// Tell IQ/mem dep unit that this instruction will need to be
|
// Tell IQ/mem dep unit that this instruction will need to be
|
||||||
// rescheduled eventually
|
// rescheduled eventually
|
||||||
iewStage->rescheduleMemInst(load_inst);
|
iewStage->rescheduleMemInst(load_inst);
|
||||||
|
++lsqRescheduledLoads;
|
||||||
|
|
||||||
// Do not generate a writeback event as this instruction is not
|
// Do not generate a writeback event as this instruction is not
|
||||||
// complete.
|
// complete.
|
||||||
|
@ -633,6 +645,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
"Store idx %i to load addr %#x\n",
|
"Store idx %i to load addr %#x\n",
|
||||||
store_idx, req->getVaddr());
|
store_idx, req->getVaddr());
|
||||||
|
|
||||||
|
++lsqBlockedLoads;
|
||||||
return NoFault;
|
return NoFault;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -660,6 +673,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
||||||
|
|
||||||
// if we have a cache, do cache access too
|
// if we have a cache, do cache access too
|
||||||
if (!dcachePort->sendTiming(data_pkt)) {
|
if (!dcachePort->sendTiming(data_pkt)) {
|
||||||
|
++lsqCacheBlocked;
|
||||||
// There's an older load that's already going to squash.
|
// There's an older load that's already going to squash.
|
||||||
if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum)
|
if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum)
|
||||||
return NoFault;
|
return NoFault;
|
||||||
|
|
|
@ -196,6 +196,47 @@ LSQUnit<Impl>::name() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Impl>
|
||||||
|
void
|
||||||
|
LSQUnit<Impl>::regStats()
|
||||||
|
{
|
||||||
|
lsqForwLoads
|
||||||
|
.name(name() + ".forwLoads")
|
||||||
|
.desc("Number of loads that had data forwarded from stores");
|
||||||
|
|
||||||
|
invAddrLoads
|
||||||
|
.name(name() + ".invAddrLoads")
|
||||||
|
.desc("Number of loads ignored due to an invalid address");
|
||||||
|
|
||||||
|
lsqSquashedLoads
|
||||||
|
.name(name() + ".squashedLoads")
|
||||||
|
.desc("Number of loads squashed");
|
||||||
|
|
||||||
|
lsqIgnoredResponses
|
||||||
|
.name(name() + ".ignoredResponses")
|
||||||
|
.desc("Number of memory responses ignored because the instruction is squashed");
|
||||||
|
|
||||||
|
lsqSquashedStores
|
||||||
|
.name(name() + ".squashedStores")
|
||||||
|
.desc("Number of stores squashed");
|
||||||
|
|
||||||
|
invAddrSwpfs
|
||||||
|
.name(name() + ".invAddrSwpfs")
|
||||||
|
.desc("Number of software prefetches ignored due to an invalid address");
|
||||||
|
|
||||||
|
lsqBlockedLoads
|
||||||
|
.name(name() + ".blockedLoads")
|
||||||
|
.desc("Number of blocked loads due to partial load-store forwarding");
|
||||||
|
|
||||||
|
lsqRescheduledLoads
|
||||||
|
.name(name() + ".rescheduledLoads")
|
||||||
|
.desc("Number of loads that were rescheduled");
|
||||||
|
|
||||||
|
lsqCacheBlocked
|
||||||
|
.name(name() + ".cacheBlocked")
|
||||||
|
.desc("Number of times an access to memory failed due to the cache being blocked");
|
||||||
|
}
|
||||||
|
|
||||||
template<class Impl>
|
template<class Impl>
|
||||||
void
|
void
|
||||||
LSQUnit<Impl>::clearLQ()
|
LSQUnit<Impl>::clearLQ()
|
||||||
|
@ -618,7 +659,7 @@ LSQUnit<Impl>::writebackStores()
|
||||||
if (!dcachePort->sendTiming(data_pkt)) {
|
if (!dcachePort->sendTiming(data_pkt)) {
|
||||||
// Need to handle becoming blocked on a store.
|
// Need to handle becoming blocked on a store.
|
||||||
isStoreBlocked = true;
|
isStoreBlocked = true;
|
||||||
|
++lsqCacheBlocked;
|
||||||
assert(retryPkt == NULL);
|
assert(retryPkt == NULL);
|
||||||
retryPkt = data_pkt;
|
retryPkt = data_pkt;
|
||||||
} else {
|
} else {
|
||||||
|
@ -677,6 +718,7 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
|
||||||
loadTail = load_idx;
|
loadTail = load_idx;
|
||||||
|
|
||||||
decrLdIdx(load_idx);
|
decrLdIdx(load_idx);
|
||||||
|
++lsqSquashedLoads;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLoadBlocked) {
|
if (isLoadBlocked) {
|
||||||
|
@ -723,6 +765,7 @@ LSQUnit<Impl>::squash(const InstSeqNum &squashed_num)
|
||||||
storeTail = store_idx;
|
storeTail = store_idx;
|
||||||
|
|
||||||
decrStIdx(store_idx);
|
decrStIdx(store_idx);
|
||||||
|
++lsqSquashedStores;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,6 +825,7 @@ LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt)
|
||||||
// Squashed instructions do not need to complete their access.
|
// Squashed instructions do not need to complete their access.
|
||||||
if (inst->isSquashed()) {
|
if (inst->isSquashed()) {
|
||||||
assert(!inst->isStore());
|
assert(!inst->isStore());
|
||||||
|
++lsqIgnoredResponses;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -858,6 +902,7 @@ LSQUnit<Impl>::recvRetry()
|
||||||
isStoreBlocked = false;
|
isStoreBlocked = false;
|
||||||
} else {
|
} else {
|
||||||
// Still blocked!
|
// Still blocked!
|
||||||
|
++lsqCacheBlocked;
|
||||||
}
|
}
|
||||||
} else if (isLoadBlocked) {
|
} else if (isLoadBlocked) {
|
||||||
DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, "
|
DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, "
|
||||||
|
|
|
@ -1206,7 +1206,7 @@ DefaultRename<Impl>::checkSignalsAndUpdate(unsigned tid)
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(Rename, "[tid:%u]: Instruction must be processed by rename."
|
DPRINTF(Rename, "[tid:%u]: Instruction must be processed by rename."
|
||||||
" Adding to front of list.", tid);
|
" Adding to front of list.\n", tid);
|
||||||
|
|
||||||
serializeInst[tid] = NULL;
|
serializeInst[tid] = NULL;
|
||||||
|
|
||||||
|
|
|
@ -64,11 +64,34 @@ def AddToPath(path):
|
||||||
def setTraceFlags(option, opt_str, value, parser):
|
def setTraceFlags(option, opt_str, value, parser):
|
||||||
objects.Trace.flags = value
|
objects.Trace.flags = value
|
||||||
|
|
||||||
|
def setTraceStart(option, opt_str, value, parser):
|
||||||
|
objects.Trace.start = value
|
||||||
|
|
||||||
|
def clearPCSymbol(option, opt_str, value, parser):
|
||||||
|
objects.ExecutionTrace.pc_symbol = False
|
||||||
|
|
||||||
|
def clearPrintCycle(option, opt_str, value, parser):
|
||||||
|
objects.ExecutionTrace.print_cycle = False
|
||||||
|
|
||||||
|
def statsTextFile(option, opt_str, value, parser):
|
||||||
|
objects.Statistics.text_file = value
|
||||||
|
|
||||||
# Standard optparse options. Need to be explicitly included by the
|
# Standard optparse options. Need to be explicitly included by the
|
||||||
# user script when it calls optparse.OptionParser().
|
# user script when it calls optparse.OptionParser().
|
||||||
standardOptions = [
|
standardOptions = [
|
||||||
optparse.make_option("--traceflags", type="string", action="callback",
|
optparse.make_option("--traceflags", type="string", action="callback",
|
||||||
callback=setTraceFlags)
|
callback=setTraceFlags),
|
||||||
|
optparse.make_option("--tracestart", type="int", action="callback",
|
||||||
|
callback=setTraceStart),
|
||||||
|
optparse.make_option("--nopcsymbol", action="callback",
|
||||||
|
callback=clearPCSymbol,
|
||||||
|
help="Turn off printing PC symbols in trace output"),
|
||||||
|
optparse.make_option("--noprintcycle", action="callback",
|
||||||
|
callback=clearPrintCycle,
|
||||||
|
help="Turn off printing cycles in trace output"),
|
||||||
|
optparse.make_option("--statsfile", type="string", action="callback",
|
||||||
|
callback=statsTextFile, metavar="FILE",
|
||||||
|
help="Sets the output file for the statistics")
|
||||||
]
|
]
|
||||||
|
|
||||||
# make a SmartDict out of the build options for our local use
|
# make a SmartDict out of the build options for our local use
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <getopt.h>
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -113,6 +113,31 @@ abortHandler(int sigtype)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Simulator executable name
|
||||||
|
char *myProgName = "";
|
||||||
|
|
||||||
|
/// Show brief help message.
|
||||||
|
void
|
||||||
|
showBriefHelp(ostream &out)
|
||||||
|
{
|
||||||
|
char *prog = basename(myProgName);
|
||||||
|
|
||||||
|
ccprintf(out, "Usage:\n");
|
||||||
|
ccprintf(out,
|
||||||
|
"%s [-p <path>] [-i ] [-h] <config file>\n"
|
||||||
|
"\n"
|
||||||
|
" -p, --path <path> prepends <path> to PYTHONPATH instead of using\n"
|
||||||
|
" built-in zip archive. Useful when developing/debugging\n"
|
||||||
|
" changes to built-in Python libraries, as the new Python\n"
|
||||||
|
" can be tested without building a new m5 binary.\n\n"
|
||||||
|
" -i, --interactive forces entry into interactive mode after the supplied\n"
|
||||||
|
" script is executed (just like the -i option to the\n"
|
||||||
|
" Python interpreter).\n\n"
|
||||||
|
" -h Prints this help\n\n"
|
||||||
|
" <configfile> config file name (ends in .py)\n\n",
|
||||||
|
prog);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
const char *briefCopyright =
|
const char *briefCopyright =
|
||||||
"Copyright (c) 2001-2006\n"
|
"Copyright (c) 2001-2006\n"
|
||||||
|
@ -145,6 +170,9 @@ extern "C" { void init_main(); }
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
// Saze off program name
|
||||||
|
myProgName = argv[0];
|
||||||
|
|
||||||
sayHello(cerr);
|
sayHello(cerr);
|
||||||
|
|
||||||
signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths
|
signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths
|
||||||
|
@ -161,9 +189,19 @@ main(int argc, char **argv)
|
||||||
char *pythonpath = argv[0];
|
char *pythonpath = argv[0];
|
||||||
|
|
||||||
bool interactive = false;
|
bool interactive = false;
|
||||||
|
bool show_help = false;
|
||||||
bool getopt_done = false;
|
bool getopt_done = false;
|
||||||
|
int opt_index = 0;
|
||||||
|
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"python", 1, 0, 'p'},
|
||||||
|
{"interactive", 0, 0, 'i'},
|
||||||
|
{"help", 0, 0, 'h'},
|
||||||
|
{0,0,0,0}
|
||||||
|
};
|
||||||
|
|
||||||
do {
|
do {
|
||||||
switch (getopt(argc, argv, "+p:i")) {
|
switch (getopt_long(argc, argv, "+p:ih", long_options, &opt_index)) {
|
||||||
// -p <path> prepends <path> to PYTHONPATH instead of
|
// -p <path> prepends <path> to PYTHONPATH instead of
|
||||||
// using built-in zip archive. Useful when
|
// using built-in zip archive. Useful when
|
||||||
// developing/debugging changes to built-in Python
|
// developing/debugging changes to built-in Python
|
||||||
|
@ -180,6 +218,9 @@ main(int argc, char **argv)
|
||||||
interactive = true;
|
interactive = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
show_help = true;
|
||||||
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
getopt_done = true;
|
getopt_done = true;
|
||||||
break;
|
break;
|
||||||
|
@ -189,6 +230,11 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
} while (!getopt_done);
|
} while (!getopt_done);
|
||||||
|
|
||||||
|
if (show_help) {
|
||||||
|
showBriefHelp(cerr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
// Fix up argc & argv to hide arguments we just processed.
|
// Fix up argc & argv to hide arguments we just processed.
|
||||||
// getopt() sets optind to the index of the first non-processed
|
// getopt() sets optind to the index of the first non-processed
|
||||||
// argv element.
|
// argv element.
|
||||||
|
|
Loading…
Reference in a new issue