gem5/cpu/ozone/front_end_impl.hh

921 lines
24 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2006 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 "arch/faults.hh"
#include "arch/isa_traits.hh"
#include "base/statistics.hh"
#include "cpu/exec_context.hh"
#include "cpu/exetrace.hh"
#include "cpu/ozone/front_end.hh"
#include "mem/mem_interface.hh"
#include "sim/byte_swap.hh"
using namespace TheISA;
template <class Impl>
FrontEnd<Impl>::FrontEnd(Params *params)
: branchPred(params),
icacheInterface(params->icacheInterface),
instBufferSize(0),
maxInstBufferSize(params->maxInstBufferSize),
width(params->frontEndWidth),
freeRegs(params->numPhysicalRegs),
numPhysRegs(params->numPhysicalRegs),
Fixes for ozone CPU to successfully boot and run linux. cpu/base_dyn_inst.hh: Remove snoop function (did not mean to commit it). cpu/ozone/back_end_impl.hh: Set instruction as having its result ready, not completed. cpu/ozone/cpu.hh: Fixes for store conditionals. Use an additional lock addr list to make sure that the access is valid. I don't know if this is fully necessary, but it gives me a peace of mind (at some performance cost). Make sure to schedule for cycles(1) and not just 1 cycle in the future as tick = 1ps. Also support the new Checker. cpu/ozone/cpu_builder.cc: Add parameter for maxOutstandingMemOps so it can be set through the config. Also add in the checker. Right now it's a BaseCPU simobject, but that may change in the future. cpu/ozone/cpu_impl.hh: Add support for the checker. For now there's a dynamic cast to convert the simobject passed back from the builder to the proper Checker type. It's ugly, but only happens at startup, and is probably a justified use of dynamic cast. Support switching out/taking over from other CPUs. Correct indexing problem for float registers. cpu/ozone/dyn_inst.hh: Add ability for instructions to wait on memory instructions in addition to source register instructions. This is needed for memory dependence predictors and memory barriers. cpu/ozone/dyn_inst_impl.hh: Support waiting on memory operations. Use "resultReady" to differentiate an instruction having its registers produced vs being totally completed. cpu/ozone/front_end.hh: Support switching out. Also record if an interrupt is pending. cpu/ozone/front_end_impl.hh: Support switching out. Also support stalling the front end if an interrupt is pending. cpu/ozone/lw_back_end.hh: Add checker in. Support switching out. Support memory barriers. cpu/ozone/lw_back_end_impl.hh: Lots of changes to get things to work right. Faults, traps, interrupts all wait until all stores have written back (important). Memory barriers are supported, as is the general ability for instructions to be dependent on other memory instructions. cpu/ozone/lw_lsq.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. cpu/ozone/lw_lsq_impl.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. Support the checker CPU. Marks instructions as completed once the functional access is done (which has to be done for the checker to be able to verify results). cpu/ozone/simple_params.hh: Add max outstanding mem ops parameter. python/m5/objects/OzoneCPU.py: Add max outstanding mem ops, checker. --HG-- extra : convert_revision : f4d408e1bb1f25836a097b6abe3856111e950c59
2006-05-12 01:18:36 +02:00
serializeNext(false),
interruptPending(false)
{
Fixes for ozone CPU to successfully boot and run linux. cpu/base_dyn_inst.hh: Remove snoop function (did not mean to commit it). cpu/ozone/back_end_impl.hh: Set instruction as having its result ready, not completed. cpu/ozone/cpu.hh: Fixes for store conditionals. Use an additional lock addr list to make sure that the access is valid. I don't know if this is fully necessary, but it gives me a peace of mind (at some performance cost). Make sure to schedule for cycles(1) and not just 1 cycle in the future as tick = 1ps. Also support the new Checker. cpu/ozone/cpu_builder.cc: Add parameter for maxOutstandingMemOps so it can be set through the config. Also add in the checker. Right now it's a BaseCPU simobject, but that may change in the future. cpu/ozone/cpu_impl.hh: Add support for the checker. For now there's a dynamic cast to convert the simobject passed back from the builder to the proper Checker type. It's ugly, but only happens at startup, and is probably a justified use of dynamic cast. Support switching out/taking over from other CPUs. Correct indexing problem for float registers. cpu/ozone/dyn_inst.hh: Add ability for instructions to wait on memory instructions in addition to source register instructions. This is needed for memory dependence predictors and memory barriers. cpu/ozone/dyn_inst_impl.hh: Support waiting on memory operations. Use "resultReady" to differentiate an instruction having its registers produced vs being totally completed. cpu/ozone/front_end.hh: Support switching out. Also record if an interrupt is pending. cpu/ozone/front_end_impl.hh: Support switching out. Also support stalling the front end if an interrupt is pending. cpu/ozone/lw_back_end.hh: Add checker in. Support switching out. Support memory barriers. cpu/ozone/lw_back_end_impl.hh: Lots of changes to get things to work right. Faults, traps, interrupts all wait until all stores have written back (important). Memory barriers are supported, as is the general ability for instructions to be dependent on other memory instructions. cpu/ozone/lw_lsq.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. cpu/ozone/lw_lsq_impl.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. Support the checker CPU. Marks instructions as completed once the functional access is done (which has to be done for the checker to be able to verify results). cpu/ozone/simple_params.hh: Add max outstanding mem ops parameter. python/m5/objects/OzoneCPU.py: Add max outstanding mem ops, checker. --HG-- extra : convert_revision : f4d408e1bb1f25836a097b6abe3856111e950c59
2006-05-12 01:18:36 +02:00
switchedOut = false;
status = Idle;
memReq = NULL;
// Size of cache block.
cacheBlkSize = icacheInterface ? icacheInterface->getBlockSize() : 64;
assert(isPowerOf2(cacheBlkSize));
// Create mask to get rid of offset bits.
cacheBlkMask = (cacheBlkSize - 1);
// Create space to store a cache line.
cacheData = new uint8_t[cacheBlkSize];
fetchCacheLineNextCycle = true;
cacheBlkValid = false;
#if !FULL_SYSTEM
// pTable = params->pTable;
#endif
fetchFault = NoFault;
}
template <class Impl>
std::string
FrontEnd<Impl>::name() const
{
return cpu->name() + ".frontend";
}
template <class Impl>
void
FrontEnd<Impl>::setCommBuffer(TimeBuffer<CommStruct> *_comm)
{
comm = _comm;
// @todo: Hardcoded for now. Allow this to be set by a latency.
fromCommit = comm->getWire(-1);
}
template <class Impl>
void
FrontEnd<Impl>::setXC(ExecContext *xc_ptr)
{
xc = xc_ptr;
}
template <class Impl>
void
FrontEnd<Impl>::regStats()
{
icacheStallCycles
.name(name() + ".icacheStallCycles")
.desc("Number of cycles fetch is stalled on an Icache miss")
.prereq(icacheStallCycles);
fetchedInsts
.name(name() + ".fetchedInsts")
.desc("Number of instructions fetch has processed")
.prereq(fetchedInsts);
fetchedBranches
.name(name() + ".fetchedBranches")
.desc("Number of fetched branches")
.prereq(fetchedBranches);
predictedBranches
.name(name() + ".predictedBranches")
.desc("Number of branches that fetch has predicted taken")
.prereq(predictedBranches);
fetchCycles
.name(name() + ".fetchCycles")
.desc("Number of cycles fetch has run and was not squashing or"
" blocked")
.prereq(fetchCycles);
fetchIdleCycles
.name(name() + ".fetchIdleCycles")
.desc("Number of cycles fetch was idle")
.prereq(fetchIdleCycles);
fetchSquashCycles
.name(name() + ".fetchSquashCycles")
.desc("Number of cycles fetch has spent squashing")
.prereq(fetchSquashCycles);
fetchBlockedCycles
.name(name() + ".fetchBlockedCycles")
.desc("Number of cycles fetch has spent blocked")
.prereq(fetchBlockedCycles);
fetchedCacheLines
.name(name() + ".fetchedCacheLines")
.desc("Number of cache lines fetched")
.prereq(fetchedCacheLines);
Fixes for ozone CPU to successfully boot and run linux. cpu/base_dyn_inst.hh: Remove snoop function (did not mean to commit it). cpu/ozone/back_end_impl.hh: Set instruction as having its result ready, not completed. cpu/ozone/cpu.hh: Fixes for store conditionals. Use an additional lock addr list to make sure that the access is valid. I don't know if this is fully necessary, but it gives me a peace of mind (at some performance cost). Make sure to schedule for cycles(1) and not just 1 cycle in the future as tick = 1ps. Also support the new Checker. cpu/ozone/cpu_builder.cc: Add parameter for maxOutstandingMemOps so it can be set through the config. Also add in the checker. Right now it's a BaseCPU simobject, but that may change in the future. cpu/ozone/cpu_impl.hh: Add support for the checker. For now there's a dynamic cast to convert the simobject passed back from the builder to the proper Checker type. It's ugly, but only happens at startup, and is probably a justified use of dynamic cast. Support switching out/taking over from other CPUs. Correct indexing problem for float registers. cpu/ozone/dyn_inst.hh: Add ability for instructions to wait on memory instructions in addition to source register instructions. This is needed for memory dependence predictors and memory barriers. cpu/ozone/dyn_inst_impl.hh: Support waiting on memory operations. Use "resultReady" to differentiate an instruction having its registers produced vs being totally completed. cpu/ozone/front_end.hh: Support switching out. Also record if an interrupt is pending. cpu/ozone/front_end_impl.hh: Support switching out. Also support stalling the front end if an interrupt is pending. cpu/ozone/lw_back_end.hh: Add checker in. Support switching out. Support memory barriers. cpu/ozone/lw_back_end_impl.hh: Lots of changes to get things to work right. Faults, traps, interrupts all wait until all stores have written back (important). Memory barriers are supported, as is the general ability for instructions to be dependent on other memory instructions. cpu/ozone/lw_lsq.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. cpu/ozone/lw_lsq_impl.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. Support the checker CPU. Marks instructions as completed once the functional access is done (which has to be done for the checker to be able to verify results). cpu/ozone/simple_params.hh: Add max outstanding mem ops parameter. python/m5/objects/OzoneCPU.py: Add max outstanding mem ops, checker. --HG-- extra : convert_revision : f4d408e1bb1f25836a097b6abe3856111e950c59
2006-05-12 01:18:36 +02:00
fetchIcacheSquashes
.name(name() + ".fetchIcacheSquashes")
.desc("Number of outstanding Icache misses that were squashed")
.prereq(fetchIcacheSquashes);
fetchNisnDist
.init(/* base value */ 0,
/* last value */ width,
/* bucket size */ 1)
.name(name() + ".rateDist")
.desc("Number of instructions fetched each cycle (Total)")
.flags(Stats::pdf);
idleRate
.name(name() + ".idleRate")
.desc("Percent of cycles fetch was idle")
.prereq(idleRate);
idleRate = fetchIdleCycles * 100 / cpu->numCycles;
branchRate
.name(name() + ".branchRate")
.desc("Number of branch fetches per cycle")
.flags(Stats::total);
branchRate = fetchedBranches / cpu->numCycles;
fetchRate
.name(name() + ".rate")
.desc("Number of inst fetches per cycle")
.flags(Stats::total);
fetchRate = fetchedInsts / cpu->numCycles;
IFQCount
.name(name() + ".IFQ:count")
.desc("cumulative IFQ occupancy")
;
IFQFcount
.name(name() + ".IFQ:fullCount")
.desc("cumulative IFQ full count")
.flags(Stats::total)
;
IFQOccupancy
.name(name() + ".IFQ:occupancy")
.desc("avg IFQ occupancy (inst's)")
;
IFQOccupancy = IFQCount / cpu->numCycles;
IFQLatency
.name(name() + ".IFQ:latency")
.desc("avg IFQ occupant latency (cycle's)")
.flags(Stats::total)
;
IFQFullRate
.name(name() + ".IFQ:fullRate")
.desc("fraction of time (cycles) IFQ was full")
.flags(Stats::total);
;
IFQFullRate = IFQFcount * Stats::constant(100) / cpu->numCycles;
dispatchCountStat
.name(name() + ".DIS:count")
.desc("cumulative count of dispatched insts")
.flags(Stats::total)
;
dispatchedSerializing
.name(name() + ".DIS:serializingInsts")
.desc("count of serializing insts dispatched")
.flags(Stats::total)
;
dispatchedTempSerializing
.name(name() + ".DIS:tempSerializingInsts")
.desc("count of temporary serializing insts dispatched")
.flags(Stats::total)
;
dispatchSerializeStallCycles
.name(name() + ".DIS:serializeStallCycles")
.desc("count of cycles dispatch stalled for serializing inst")
.flags(Stats::total)
;
dispatchRate
.name(name() + ".DIS:rate")
.desc("dispatched insts per cycle")
.flags(Stats::total)
;
dispatchRate = dispatchCountStat / cpu->numCycles;
regIntFull
.name(name() + ".REG:int:full")
.desc("number of cycles where there were no INT registers")
;
regFpFull
.name(name() + ".REG:fp:full")
.desc("number of cycles where there were no FP registers")
;
IFQLatency = IFQOccupancy / dispatchRate;
branchPred.regStats();
}
template <class Impl>
void
FrontEnd<Impl>::tick()
{
if (switchedOut)
return;
// @todo: Maybe I want to just have direct communication...
if (fromCommit->doneSeqNum) {
branchPred.update(fromCommit->doneSeqNum, 0);
}
IFQCount += instBufferSize;
IFQFcount += instBufferSize == maxInstBufferSize;
// Fetch cache line
if (status == IcacheMissComplete) {
cacheBlkValid = true;
status = Running;
if (barrierInst)
status = SerializeBlocked;
if (freeRegs <= 0)
status = RenameBlocked;
checkBE();
} else if (status == IcacheMissStall) {
DPRINTF(FE, "Still in Icache miss stall.\n");
icacheStallCycles++;
return;
}
if (status == RenameBlocked || status == SerializeBlocked ||
status == TrapPending || status == BEBlocked) {
// Will cause a one cycle bubble between changing state and
// restarting.
DPRINTF(FE, "In blocked status.\n");
fetchBlockedCycles++;
if (status == SerializeBlocked) {
dispatchSerializeStallCycles++;
}
updateStatus();
return;
} else if (status == QuiescePending) {
DPRINTF(FE, "Waiting for quiesce to execute or get squashed.\n");
return;
} else if (status != IcacheMissComplete) {
if (fetchCacheLineNextCycle) {
Fault fault = fetchCacheLine();
if (fault != NoFault) {
handleFault(fault);
fetchFault = fault;
return;
}
fetchCacheLineNextCycle = false;
}
// If miss, stall until it returns.
if (status == IcacheMissStall) {
// Tell CPU to not tick me for now.
return;
}
}
fetchCycles++;
int num_inst = 0;
// Otherwise loop and process instructions.
// One way to hack infinite width is to set width and maxInstBufferSize
// both really high. Inelegant, but probably will work.
while (num_inst < width &&
instBufferSize < maxInstBufferSize) {
// Get instruction from cache line.
DynInstPtr inst = getInstFromCacheline();
if (!inst) {
// PC is no longer in the cache line, end fetch.
// Might want to check this at the end of the cycle so that
// there's no cycle lost to checking for a new cache line.
DPRINTF(FE, "Need to get new cache line\n");
fetchCacheLineNextCycle = true;
break;
}
processInst(inst);
if (status == SerializeBlocked) {
break;
}
// Possibly push into a time buffer that estimates the front end
// latency
instBuffer.push_back(inst);
++instBufferSize;
++num_inst;
#if FULL_SYSTEM
if (inst->isQuiesce()) {
warn("%lli: Quiesce instruction encountered, halting fetch!", curTick);
status = QuiescePending;
break;
}
#endif
if (inst->predTaken()) {
// Start over with tick?
break;
} else if (freeRegs <= 0) {
DPRINTF(FE, "Ran out of free registers to rename to!\n");
status = RenameBlocked;
break;
} else if (serializeNext) {
break;
}
}
fetchNisnDist.sample(num_inst);
checkBE();
DPRINTF(FE, "Num insts processed: %i, Inst Buffer size: %i, Free "
"Regs %i\n", num_inst, instBufferSize, freeRegs);
}
template <class Impl>
Fault
FrontEnd<Impl>::fetchCacheLine()
{
// Read a cache line, based on the current PC.
#if FULL_SYSTEM
// Flag to say whether or not address is physical addr.
unsigned flags = cpu->inPalMode(PC) ? PHYSICAL : 0;
#else
unsigned flags = 0;
#endif // FULL_SYSTEM
Fault fault = NoFault;
Fixes for ozone CPU to successfully boot and run linux. cpu/base_dyn_inst.hh: Remove snoop function (did not mean to commit it). cpu/ozone/back_end_impl.hh: Set instruction as having its result ready, not completed. cpu/ozone/cpu.hh: Fixes for store conditionals. Use an additional lock addr list to make sure that the access is valid. I don't know if this is fully necessary, but it gives me a peace of mind (at some performance cost). Make sure to schedule for cycles(1) and not just 1 cycle in the future as tick = 1ps. Also support the new Checker. cpu/ozone/cpu_builder.cc: Add parameter for maxOutstandingMemOps so it can be set through the config. Also add in the checker. Right now it's a BaseCPU simobject, but that may change in the future. cpu/ozone/cpu_impl.hh: Add support for the checker. For now there's a dynamic cast to convert the simobject passed back from the builder to the proper Checker type. It's ugly, but only happens at startup, and is probably a justified use of dynamic cast. Support switching out/taking over from other CPUs. Correct indexing problem for float registers. cpu/ozone/dyn_inst.hh: Add ability for instructions to wait on memory instructions in addition to source register instructions. This is needed for memory dependence predictors and memory barriers. cpu/ozone/dyn_inst_impl.hh: Support waiting on memory operations. Use "resultReady" to differentiate an instruction having its registers produced vs being totally completed. cpu/ozone/front_end.hh: Support switching out. Also record if an interrupt is pending. cpu/ozone/front_end_impl.hh: Support switching out. Also support stalling the front end if an interrupt is pending. cpu/ozone/lw_back_end.hh: Add checker in. Support switching out. Support memory barriers. cpu/ozone/lw_back_end_impl.hh: Lots of changes to get things to work right. Faults, traps, interrupts all wait until all stores have written back (important). Memory barriers are supported, as is the general ability for instructions to be dependent on other memory instructions. cpu/ozone/lw_lsq.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. cpu/ozone/lw_lsq_impl.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. Support the checker CPU. Marks instructions as completed once the functional access is done (which has to be done for the checker to be able to verify results). cpu/ozone/simple_params.hh: Add max outstanding mem ops parameter. python/m5/objects/OzoneCPU.py: Add max outstanding mem ops, checker. --HG-- extra : convert_revision : f4d408e1bb1f25836a097b6abe3856111e950c59
2006-05-12 01:18:36 +02:00
if (interruptPending && flags == 0) {
return fault;
}
// Align the fetch PC so it's at the start of a cache block.
Addr fetch_PC = icacheBlockAlignPC(PC);
DPRINTF(FE, "Fetching cache line starting at %#x.\n", fetch_PC);
// Setup the memReq to do a read of the first isntruction's address.
// Set the appropriate read size and flags as well.
memReq = new MemReq();
memReq->asid = 0;
memReq->thread_num = 0;
memReq->data = new uint8_t[64];
memReq->xc = xc;
memReq->cmd = Read;
memReq->reset(fetch_PC, cacheBlkSize, flags);
// Translate the instruction request.
fault = cpu->translateInstReq(memReq);
// Now do the timing access to see whether or not the instruction
// exists within the cache.
if (icacheInterface && fault == NoFault) {
#if FULL_SYSTEM
Fixes for ozone CPU to successfully boot and run linux. cpu/base_dyn_inst.hh: Remove snoop function (did not mean to commit it). cpu/ozone/back_end_impl.hh: Set instruction as having its result ready, not completed. cpu/ozone/cpu.hh: Fixes for store conditionals. Use an additional lock addr list to make sure that the access is valid. I don't know if this is fully necessary, but it gives me a peace of mind (at some performance cost). Make sure to schedule for cycles(1) and not just 1 cycle in the future as tick = 1ps. Also support the new Checker. cpu/ozone/cpu_builder.cc: Add parameter for maxOutstandingMemOps so it can be set through the config. Also add in the checker. Right now it's a BaseCPU simobject, but that may change in the future. cpu/ozone/cpu_impl.hh: Add support for the checker. For now there's a dynamic cast to convert the simobject passed back from the builder to the proper Checker type. It's ugly, but only happens at startup, and is probably a justified use of dynamic cast. Support switching out/taking over from other CPUs. Correct indexing problem for float registers. cpu/ozone/dyn_inst.hh: Add ability for instructions to wait on memory instructions in addition to source register instructions. This is needed for memory dependence predictors and memory barriers. cpu/ozone/dyn_inst_impl.hh: Support waiting on memory operations. Use "resultReady" to differentiate an instruction having its registers produced vs being totally completed. cpu/ozone/front_end.hh: Support switching out. Also record if an interrupt is pending. cpu/ozone/front_end_impl.hh: Support switching out. Also support stalling the front end if an interrupt is pending. cpu/ozone/lw_back_end.hh: Add checker in. Support switching out. Support memory barriers. cpu/ozone/lw_back_end_impl.hh: Lots of changes to get things to work right. Faults, traps, interrupts all wait until all stores have written back (important). Memory barriers are supported, as is the general ability for instructions to be dependent on other memory instructions. cpu/ozone/lw_lsq.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. cpu/ozone/lw_lsq_impl.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. Support the checker CPU. Marks instructions as completed once the functional access is done (which has to be done for the checker to be able to verify results). cpu/ozone/simple_params.hh: Add max outstanding mem ops parameter. python/m5/objects/OzoneCPU.py: Add max outstanding mem ops, checker. --HG-- extra : convert_revision : f4d408e1bb1f25836a097b6abe3856111e950c59
2006-05-12 01:18:36 +02:00
if (cpu->system->memctrl->badaddr(memReq->paddr) ||
memReq->flags & UNCACHEABLE) {
DPRINTF(FE, "Fetch: Bad address %#x (hopefully on a "
"misspeculating path!",
memReq->paddr);
return TheISA::genMachineCheckFault();
}
#endif
memReq->completionEvent = NULL;
memReq->time = curTick;
fault = cpu->mem->read(memReq, cacheData);
MemAccessResult res = icacheInterface->access(memReq);
// If the cache missed then schedule an event to wake
// up this stage once the cache miss completes.
if (icacheInterface->doEvents() && res != MA_HIT) {
memReq->completionEvent = new ICacheCompletionEvent(memReq, this);
status = IcacheMissStall;
cacheBlkValid = false;
DPRINTF(FE, "Cache miss.\n");
} else {
DPRINTF(FE, "Cache hit.\n");
cacheBlkValid = true;
// memcpy(cacheData, memReq->data, memReq->size);
}
}
// Note that this will set the cache block PC a bit earlier than it should
// be set.
cacheBlkPC = fetch_PC;
++fetchedCacheLines;
DPRINTF(FE, "Done fetching cache line.\n");
return fault;
}
template <class Impl>
void
FrontEnd<Impl>::processInst(DynInstPtr &inst)
{
if (processBarriers(inst)) {
return;
}
Addr inst_PC = inst->readPC();
if (!inst->isControl()) {
inst->setPredTarg(inst->readNextPC());
} else {
fetchedBranches++;
if (branchPred.predict(inst, inst_PC, inst->threadNumber)) {
predictedBranches++;
}
}
Addr next_PC = inst->readPredTarg();
DPRINTF(FE, "[sn:%lli] Predicted and processed inst PC %#x, next PC "
"%#x\n", inst->seqNum, inst_PC, next_PC);
// inst->setNextPC(next_PC);
// Not sure where I should set this
PC = next_PC;
renameInst(inst);
}
template <class Impl>
bool
FrontEnd<Impl>::processBarriers(DynInstPtr &inst)
{
if (serializeNext) {
inst->setSerializeBefore();
serializeNext = false;
} else if (!inst->isSerializing() &&
!inst->isIprAccess() &&
!inst->isStoreConditional()) {
return false;
}
if ((inst->isIprAccess() || inst->isSerializeBefore()) &&
!inst->isSerializeHandled()) {
DPRINTF(FE, "Serialize before instruction encountered.\n");
if (!inst->isTempSerializeBefore()) {
dispatchedSerializing++;
inst->setSerializeHandled();
} else {
dispatchedTempSerializing++;
}
Fixes for ozone CPU to successfully boot and run linux. cpu/base_dyn_inst.hh: Remove snoop function (did not mean to commit it). cpu/ozone/back_end_impl.hh: Set instruction as having its result ready, not completed. cpu/ozone/cpu.hh: Fixes for store conditionals. Use an additional lock addr list to make sure that the access is valid. I don't know if this is fully necessary, but it gives me a peace of mind (at some performance cost). Make sure to schedule for cycles(1) and not just 1 cycle in the future as tick = 1ps. Also support the new Checker. cpu/ozone/cpu_builder.cc: Add parameter for maxOutstandingMemOps so it can be set through the config. Also add in the checker. Right now it's a BaseCPU simobject, but that may change in the future. cpu/ozone/cpu_impl.hh: Add support for the checker. For now there's a dynamic cast to convert the simobject passed back from the builder to the proper Checker type. It's ugly, but only happens at startup, and is probably a justified use of dynamic cast. Support switching out/taking over from other CPUs. Correct indexing problem for float registers. cpu/ozone/dyn_inst.hh: Add ability for instructions to wait on memory instructions in addition to source register instructions. This is needed for memory dependence predictors and memory barriers. cpu/ozone/dyn_inst_impl.hh: Support waiting on memory operations. Use "resultReady" to differentiate an instruction having its registers produced vs being totally completed. cpu/ozone/front_end.hh: Support switching out. Also record if an interrupt is pending. cpu/ozone/front_end_impl.hh: Support switching out. Also support stalling the front end if an interrupt is pending. cpu/ozone/lw_back_end.hh: Add checker in. Support switching out. Support memory barriers. cpu/ozone/lw_back_end_impl.hh: Lots of changes to get things to work right. Faults, traps, interrupts all wait until all stores have written back (important). Memory barriers are supported, as is the general ability for instructions to be dependent on other memory instructions. cpu/ozone/lw_lsq.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. cpu/ozone/lw_lsq_impl.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. Support the checker CPU. Marks instructions as completed once the functional access is done (which has to be done for the checker to be able to verify results). cpu/ozone/simple_params.hh: Add max outstanding mem ops parameter. python/m5/objects/OzoneCPU.py: Add max outstanding mem ops, checker. --HG-- extra : convert_revision : f4d408e1bb1f25836a097b6abe3856111e950c59
2006-05-12 01:18:36 +02:00
// Change status over to SerializeBlocked so that other stages know
// what this is blocked on.
status = SerializeBlocked;
barrierInst = inst;
return true;
} else if ((inst->isStoreConditional() || inst->isSerializeAfter())
&& !inst->isSerializeHandled()) {
DPRINTF(FE, "Serialize after instruction encountered.\n");
inst->setSerializeHandled();
dispatchedSerializing++;
serializeNext = true;
return false;
}
return false;
}
template <class Impl>
void
FrontEnd<Impl>::handleFault(Fault &fault)
{
DPRINTF(FE, "Fault at fetch, telling commit\n");
// We're blocked on the back end until it handles this fault.
status = TrapPending;
// Get a sequence number.
InstSeqNum inst_seq = getAndIncrementInstSeq();
// We will use a nop in order to carry the fault.
ExtMachInst ext_inst = TheISA::NoopMachInst;
// Create a new DynInst from the dummy nop.
DynInstPtr instruction = new DynInst(ext_inst, PC,
PC+sizeof(MachInst),
inst_seq, cpu);
instruction->setPredTarg(instruction->readNextPC());
// instruction->setThread(tid);
// instruction->setASID(tid);
instruction->setState(thread);
instruction->traceData = NULL;
instruction->fault = fault;
instruction->setCanIssue();
instBuffer.push_back(instruction);
++instBufferSize;
}
template <class Impl>
void
FrontEnd<Impl>::squash(const InstSeqNum &squash_num, const Addr &next_PC,
const bool is_branch, const bool branch_taken)
{
DPRINTF(FE, "Squashing from [sn:%lli], setting PC to %#x\n",
squash_num, next_PC);
if (fetchFault != NoFault)
fetchFault = NoFault;
while (!instBuffer.empty() &&
instBuffer.back()->seqNum > squash_num) {
DynInstPtr inst = instBuffer.back();
DPRINTF(FE, "Squashing instruction [sn:%lli] PC %#x\n",
inst->seqNum, inst->readPC());
inst->clearDependents();
instBuffer.pop_back();
--instBufferSize;
freeRegs+= inst->numDestRegs();
}
// Copy over rename table from the back end.
renameTable.copyFrom(backEnd->renameTable);
PC = next_PC;
// Update BP with proper information.
if (is_branch) {
branchPred.squash(squash_num, next_PC, branch_taken, 0);
} else {
branchPred.squash(squash_num, 0);
}
// Clear the icache miss if it's outstanding.
if (status == IcacheMissStall && icacheInterface) {
DPRINTF(FE, "Squashing outstanding Icache miss.\n");
memReq = NULL;
}
if (status == SerializeBlocked) {
assert(barrierInst->seqNum > squash_num);
barrierInst = NULL;
}
// Unless this squash originated from the front end, we're probably
// in running mode now.
// Actually might want to make this latency dependent.
status = Running;
fetchCacheLineNextCycle = true;
}
template <class Impl>
typename Impl::DynInstPtr
FrontEnd<Impl>::getInst()
{
if (instBufferSize == 0) {
return NULL;
}
DynInstPtr inst = instBuffer.front();
instBuffer.pop_front();
--instBufferSize;
dispatchCountStat++;
return inst;
}
template <class Impl>
void
FrontEnd<Impl>::processCacheCompletion(MemReqPtr &req)
{
DPRINTF(FE, "Processing cache completion\n");
// Do something here.
if (status != IcacheMissStall ||
Fixes for ozone CPU to successfully boot and run linux. cpu/base_dyn_inst.hh: Remove snoop function (did not mean to commit it). cpu/ozone/back_end_impl.hh: Set instruction as having its result ready, not completed. cpu/ozone/cpu.hh: Fixes for store conditionals. Use an additional lock addr list to make sure that the access is valid. I don't know if this is fully necessary, but it gives me a peace of mind (at some performance cost). Make sure to schedule for cycles(1) and not just 1 cycle in the future as tick = 1ps. Also support the new Checker. cpu/ozone/cpu_builder.cc: Add parameter for maxOutstandingMemOps so it can be set through the config. Also add in the checker. Right now it's a BaseCPU simobject, but that may change in the future. cpu/ozone/cpu_impl.hh: Add support for the checker. For now there's a dynamic cast to convert the simobject passed back from the builder to the proper Checker type. It's ugly, but only happens at startup, and is probably a justified use of dynamic cast. Support switching out/taking over from other CPUs. Correct indexing problem for float registers. cpu/ozone/dyn_inst.hh: Add ability for instructions to wait on memory instructions in addition to source register instructions. This is needed for memory dependence predictors and memory barriers. cpu/ozone/dyn_inst_impl.hh: Support waiting on memory operations. Use "resultReady" to differentiate an instruction having its registers produced vs being totally completed. cpu/ozone/front_end.hh: Support switching out. Also record if an interrupt is pending. cpu/ozone/front_end_impl.hh: Support switching out. Also support stalling the front end if an interrupt is pending. cpu/ozone/lw_back_end.hh: Add checker in. Support switching out. Support memory barriers. cpu/ozone/lw_back_end_impl.hh: Lots of changes to get things to work right. Faults, traps, interrupts all wait until all stores have written back (important). Memory barriers are supported, as is the general ability for instructions to be dependent on other memory instructions. cpu/ozone/lw_lsq.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. cpu/ozone/lw_lsq_impl.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. Support the checker CPU. Marks instructions as completed once the functional access is done (which has to be done for the checker to be able to verify results). cpu/ozone/simple_params.hh: Add max outstanding mem ops parameter. python/m5/objects/OzoneCPU.py: Add max outstanding mem ops, checker. --HG-- extra : convert_revision : f4d408e1bb1f25836a097b6abe3856111e950c59
2006-05-12 01:18:36 +02:00
req != memReq ||
switchedOut) {
DPRINTF(FE, "Previous fetch was squashed.\n");
Fixes for ozone CPU to successfully boot and run linux. cpu/base_dyn_inst.hh: Remove snoop function (did not mean to commit it). cpu/ozone/back_end_impl.hh: Set instruction as having its result ready, not completed. cpu/ozone/cpu.hh: Fixes for store conditionals. Use an additional lock addr list to make sure that the access is valid. I don't know if this is fully necessary, but it gives me a peace of mind (at some performance cost). Make sure to schedule for cycles(1) and not just 1 cycle in the future as tick = 1ps. Also support the new Checker. cpu/ozone/cpu_builder.cc: Add parameter for maxOutstandingMemOps so it can be set through the config. Also add in the checker. Right now it's a BaseCPU simobject, but that may change in the future. cpu/ozone/cpu_impl.hh: Add support for the checker. For now there's a dynamic cast to convert the simobject passed back from the builder to the proper Checker type. It's ugly, but only happens at startup, and is probably a justified use of dynamic cast. Support switching out/taking over from other CPUs. Correct indexing problem for float registers. cpu/ozone/dyn_inst.hh: Add ability for instructions to wait on memory instructions in addition to source register instructions. This is needed for memory dependence predictors and memory barriers. cpu/ozone/dyn_inst_impl.hh: Support waiting on memory operations. Use "resultReady" to differentiate an instruction having its registers produced vs being totally completed. cpu/ozone/front_end.hh: Support switching out. Also record if an interrupt is pending. cpu/ozone/front_end_impl.hh: Support switching out. Also support stalling the front end if an interrupt is pending. cpu/ozone/lw_back_end.hh: Add checker in. Support switching out. Support memory barriers. cpu/ozone/lw_back_end_impl.hh: Lots of changes to get things to work right. Faults, traps, interrupts all wait until all stores have written back (important). Memory barriers are supported, as is the general ability for instructions to be dependent on other memory instructions. cpu/ozone/lw_lsq.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. cpu/ozone/lw_lsq_impl.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. Support the checker CPU. Marks instructions as completed once the functional access is done (which has to be done for the checker to be able to verify results). cpu/ozone/simple_params.hh: Add max outstanding mem ops parameter. python/m5/objects/OzoneCPU.py: Add max outstanding mem ops, checker. --HG-- extra : convert_revision : f4d408e1bb1f25836a097b6abe3856111e950c59
2006-05-12 01:18:36 +02:00
fetchIcacheSquashes++;
return;
}
status = IcacheMissComplete;
/* if (checkStall(tid)) {
fetchStatus[tid] = Blocked;
} else {
fetchStatus[tid] = IcacheMissComplete;
}
*/
// memcpy(cacheData, memReq->data, memReq->size);
// Reset the completion event to NULL.
// memReq->completionEvent = NULL;
memReq = NULL;
}
template <class Impl>
void
FrontEnd<Impl>::addFreeRegs(int num_freed)
{
if (status == RenameBlocked && freeRegs + num_freed > 0) {
status = Running;
}
DPRINTF(FE, "Adding %i freed registers\n", num_freed);
freeRegs+= num_freed;
// assert(freeRegs <= numPhysRegs);
if (freeRegs > numPhysRegs)
freeRegs = numPhysRegs;
}
template <class Impl>
bool
FrontEnd<Impl>::updateStatus()
{
bool serialize_block = !backEnd->robEmpty() || instBufferSize;
bool be_block = cpu->decoupledFrontEnd ? false : backEnd->isBlocked();
bool ret_val = false;
if (status == SerializeBlocked && !serialize_block) {
status = SerializeComplete;
ret_val = true;
}
if (status == BEBlocked && !be_block) {
if (barrierInst) {
status = SerializeBlocked;
} else {
status = Running;
}
ret_val = true;
}
return ret_val;
}
template <class Impl>
void
FrontEnd<Impl>::checkBE()
{
bool be_block = cpu->decoupledFrontEnd ? false : backEnd->isBlocked();
if (be_block) {
if (status == Running || status == Idle) {
status = BEBlocked;
}
}
}
template <class Impl>
typename Impl::DynInstPtr
FrontEnd<Impl>::getInstFromCacheline()
{
if (status == SerializeComplete) {
DynInstPtr inst = barrierInst;
status = Running;
barrierInst = NULL;
Fixes for ozone CPU to successfully boot and run linux. cpu/base_dyn_inst.hh: Remove snoop function (did not mean to commit it). cpu/ozone/back_end_impl.hh: Set instruction as having its result ready, not completed. cpu/ozone/cpu.hh: Fixes for store conditionals. Use an additional lock addr list to make sure that the access is valid. I don't know if this is fully necessary, but it gives me a peace of mind (at some performance cost). Make sure to schedule for cycles(1) and not just 1 cycle in the future as tick = 1ps. Also support the new Checker. cpu/ozone/cpu_builder.cc: Add parameter for maxOutstandingMemOps so it can be set through the config. Also add in the checker. Right now it's a BaseCPU simobject, but that may change in the future. cpu/ozone/cpu_impl.hh: Add support for the checker. For now there's a dynamic cast to convert the simobject passed back from the builder to the proper Checker type. It's ugly, but only happens at startup, and is probably a justified use of dynamic cast. Support switching out/taking over from other CPUs. Correct indexing problem for float registers. cpu/ozone/dyn_inst.hh: Add ability for instructions to wait on memory instructions in addition to source register instructions. This is needed for memory dependence predictors and memory barriers. cpu/ozone/dyn_inst_impl.hh: Support waiting on memory operations. Use "resultReady" to differentiate an instruction having its registers produced vs being totally completed. cpu/ozone/front_end.hh: Support switching out. Also record if an interrupt is pending. cpu/ozone/front_end_impl.hh: Support switching out. Also support stalling the front end if an interrupt is pending. cpu/ozone/lw_back_end.hh: Add checker in. Support switching out. Support memory barriers. cpu/ozone/lw_back_end_impl.hh: Lots of changes to get things to work right. Faults, traps, interrupts all wait until all stores have written back (important). Memory barriers are supported, as is the general ability for instructions to be dependent on other memory instructions. cpu/ozone/lw_lsq.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. cpu/ozone/lw_lsq_impl.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. Support the checker CPU. Marks instructions as completed once the functional access is done (which has to be done for the checker to be able to verify results). cpu/ozone/simple_params.hh: Add max outstanding mem ops parameter. python/m5/objects/OzoneCPU.py: Add max outstanding mem ops, checker. --HG-- extra : convert_revision : f4d408e1bb1f25836a097b6abe3856111e950c59
2006-05-12 01:18:36 +02:00
inst->clearSerializeBefore();
return inst;
}
InstSeqNum inst_seq;
MachInst inst;
// @todo: Fix this magic number used here to handle word offset (and
// getting rid of PAL bit)
unsigned offset = (PC & cacheBlkMask) & ~3;
// PC of inst is not in this cache block
if (PC >= (cacheBlkPC + cacheBlkSize) || PC < cacheBlkPC || !cacheBlkValid) {
return NULL;
}
//////////////////////////
// Fetch one instruction
//////////////////////////
// Get a sequence number.
inst_seq = getAndIncrementInstSeq();
// Make sure this is a valid index.
assert(offset <= cacheBlkSize - sizeof(MachInst));
// Get the instruction from the array of the cache line.
inst = htog(*reinterpret_cast<MachInst *>(&cacheData[offset]));
ExtMachInst decode_inst = TheISA::makeExtMI(inst, PC);
// Create a new DynInst from the instruction fetched.
DynInstPtr instruction = new DynInst(decode_inst, PC, PC+sizeof(MachInst),
inst_seq, cpu);
instruction->setState(thread);
DPRINTF(FE, "Instruction [sn:%lli] created, with PC %#x\n%s\n",
inst_seq, instruction->readPC(),
instruction->staticInst->disassemble(PC));
instruction->traceData =
Trace::getInstRecord(curTick, xc, cpu,
instruction->staticInst,
instruction->readPC(), 0);
// Increment stat of fetched instructions.
++fetchedInsts;
return instruction;
}
template <class Impl>
void
FrontEnd<Impl>::renameInst(DynInstPtr &inst)
{
DynInstPtr src_inst = NULL;
int num_src_regs = inst->numSrcRegs();
if (num_src_regs == 0) {
inst->setCanIssue();
} else {
for (int i = 0; i < num_src_regs; ++i) {
src_inst = renameTable[inst->srcRegIdx(i)];
inst->setSrcInst(src_inst, i);
DPRINTF(FE, "[sn:%lli]: Src reg %i is inst [sn:%lli]\n",
inst->seqNum, (int)inst->srcRegIdx(i), src_inst->seqNum);
Fixes for ozone CPU to successfully boot and run linux. cpu/base_dyn_inst.hh: Remove snoop function (did not mean to commit it). cpu/ozone/back_end_impl.hh: Set instruction as having its result ready, not completed. cpu/ozone/cpu.hh: Fixes for store conditionals. Use an additional lock addr list to make sure that the access is valid. I don't know if this is fully necessary, but it gives me a peace of mind (at some performance cost). Make sure to schedule for cycles(1) and not just 1 cycle in the future as tick = 1ps. Also support the new Checker. cpu/ozone/cpu_builder.cc: Add parameter for maxOutstandingMemOps so it can be set through the config. Also add in the checker. Right now it's a BaseCPU simobject, but that may change in the future. cpu/ozone/cpu_impl.hh: Add support for the checker. For now there's a dynamic cast to convert the simobject passed back from the builder to the proper Checker type. It's ugly, but only happens at startup, and is probably a justified use of dynamic cast. Support switching out/taking over from other CPUs. Correct indexing problem for float registers. cpu/ozone/dyn_inst.hh: Add ability for instructions to wait on memory instructions in addition to source register instructions. This is needed for memory dependence predictors and memory barriers. cpu/ozone/dyn_inst_impl.hh: Support waiting on memory operations. Use "resultReady" to differentiate an instruction having its registers produced vs being totally completed. cpu/ozone/front_end.hh: Support switching out. Also record if an interrupt is pending. cpu/ozone/front_end_impl.hh: Support switching out. Also support stalling the front end if an interrupt is pending. cpu/ozone/lw_back_end.hh: Add checker in. Support switching out. Support memory barriers. cpu/ozone/lw_back_end_impl.hh: Lots of changes to get things to work right. Faults, traps, interrupts all wait until all stores have written back (important). Memory barriers are supported, as is the general ability for instructions to be dependent on other memory instructions. cpu/ozone/lw_lsq.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. cpu/ozone/lw_lsq_impl.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. Support the checker CPU. Marks instructions as completed once the functional access is done (which has to be done for the checker to be able to verify results). cpu/ozone/simple_params.hh: Add max outstanding mem ops parameter. python/m5/objects/OzoneCPU.py: Add max outstanding mem ops, checker. --HG-- extra : convert_revision : f4d408e1bb1f25836a097b6abe3856111e950c59
2006-05-12 01:18:36 +02:00
if (src_inst->isResultReady()) {
DPRINTF(FE, "Reg ready.\n");
inst->markSrcRegReady(i);
} else {
DPRINTF(FE, "Adding to dependent list.\n");
src_inst->addDependent(inst);
}
}
}
for (int i = 0; i < inst->numDestRegs(); ++i) {
RegIndex idx = inst->destRegIdx(i);
DPRINTF(FE, "Dest reg %i is now inst [sn:%lli], was previously "
"[sn:%lli]\n",
(int)inst->destRegIdx(i), inst->seqNum,
renameTable[idx]->seqNum);
inst->setPrevDestInst(renameTable[idx], i);
renameTable[idx] = inst;
--freeRegs;
}
}
template <class Impl>
void
FrontEnd<Impl>::wakeFromQuiesce()
{
DPRINTF(FE, "Waking up from quiesce\n");
// Hopefully this is safe
status = Running;
}
Fixes for ozone CPU to successfully boot and run linux. cpu/base_dyn_inst.hh: Remove snoop function (did not mean to commit it). cpu/ozone/back_end_impl.hh: Set instruction as having its result ready, not completed. cpu/ozone/cpu.hh: Fixes for store conditionals. Use an additional lock addr list to make sure that the access is valid. I don't know if this is fully necessary, but it gives me a peace of mind (at some performance cost). Make sure to schedule for cycles(1) and not just 1 cycle in the future as tick = 1ps. Also support the new Checker. cpu/ozone/cpu_builder.cc: Add parameter for maxOutstandingMemOps so it can be set through the config. Also add in the checker. Right now it's a BaseCPU simobject, but that may change in the future. cpu/ozone/cpu_impl.hh: Add support for the checker. For now there's a dynamic cast to convert the simobject passed back from the builder to the proper Checker type. It's ugly, but only happens at startup, and is probably a justified use of dynamic cast. Support switching out/taking over from other CPUs. Correct indexing problem for float registers. cpu/ozone/dyn_inst.hh: Add ability for instructions to wait on memory instructions in addition to source register instructions. This is needed for memory dependence predictors and memory barriers. cpu/ozone/dyn_inst_impl.hh: Support waiting on memory operations. Use "resultReady" to differentiate an instruction having its registers produced vs being totally completed. cpu/ozone/front_end.hh: Support switching out. Also record if an interrupt is pending. cpu/ozone/front_end_impl.hh: Support switching out. Also support stalling the front end if an interrupt is pending. cpu/ozone/lw_back_end.hh: Add checker in. Support switching out. Support memory barriers. cpu/ozone/lw_back_end_impl.hh: Lots of changes to get things to work right. Faults, traps, interrupts all wait until all stores have written back (important). Memory barriers are supported, as is the general ability for instructions to be dependent on other memory instructions. cpu/ozone/lw_lsq.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. cpu/ozone/lw_lsq_impl.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. Support the checker CPU. Marks instructions as completed once the functional access is done (which has to be done for the checker to be able to verify results). cpu/ozone/simple_params.hh: Add max outstanding mem ops parameter. python/m5/objects/OzoneCPU.py: Add max outstanding mem ops, checker. --HG-- extra : convert_revision : f4d408e1bb1f25836a097b6abe3856111e950c59
2006-05-12 01:18:36 +02:00
template <class Impl>
void
FrontEnd<Impl>::switchOut()
{
switchedOut = true;
cpu->signalSwitched();
}
template <class Impl>
void
FrontEnd<Impl>::doSwitchOut()
{
Fixes for ozone CPU to successfully boot and run linux. cpu/base_dyn_inst.hh: Remove snoop function (did not mean to commit it). cpu/ozone/back_end_impl.hh: Set instruction as having its result ready, not completed. cpu/ozone/cpu.hh: Fixes for store conditionals. Use an additional lock addr list to make sure that the access is valid. I don't know if this is fully necessary, but it gives me a peace of mind (at some performance cost). Make sure to schedule for cycles(1) and not just 1 cycle in the future as tick = 1ps. Also support the new Checker. cpu/ozone/cpu_builder.cc: Add parameter for maxOutstandingMemOps so it can be set through the config. Also add in the checker. Right now it's a BaseCPU simobject, but that may change in the future. cpu/ozone/cpu_impl.hh: Add support for the checker. For now there's a dynamic cast to convert the simobject passed back from the builder to the proper Checker type. It's ugly, but only happens at startup, and is probably a justified use of dynamic cast. Support switching out/taking over from other CPUs. Correct indexing problem for float registers. cpu/ozone/dyn_inst.hh: Add ability for instructions to wait on memory instructions in addition to source register instructions. This is needed for memory dependence predictors and memory barriers. cpu/ozone/dyn_inst_impl.hh: Support waiting on memory operations. Use "resultReady" to differentiate an instruction having its registers produced vs being totally completed. cpu/ozone/front_end.hh: Support switching out. Also record if an interrupt is pending. cpu/ozone/front_end_impl.hh: Support switching out. Also support stalling the front end if an interrupt is pending. cpu/ozone/lw_back_end.hh: Add checker in. Support switching out. Support memory barriers. cpu/ozone/lw_back_end_impl.hh: Lots of changes to get things to work right. Faults, traps, interrupts all wait until all stores have written back (important). Memory barriers are supported, as is the general ability for instructions to be dependent on other memory instructions. cpu/ozone/lw_lsq.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. cpu/ozone/lw_lsq_impl.hh: Support switching out. Also use store writeback events in all cases, not just dcache misses. Support the checker CPU. Marks instructions as completed once the functional access is done (which has to be done for the checker to be able to verify results). cpu/ozone/simple_params.hh: Add max outstanding mem ops parameter. python/m5/objects/OzoneCPU.py: Add max outstanding mem ops, checker. --HG-- extra : convert_revision : f4d408e1bb1f25836a097b6abe3856111e950c59
2006-05-12 01:18:36 +02:00
memReq = NULL;
squash(0, 0);
instBuffer.clear();
instBufferSize = 0;
status = Idle;
}
template <class Impl>
void
FrontEnd<Impl>::takeOverFrom(ExecContext *old_xc)
{
assert(freeRegs == numPhysRegs);
fetchCacheLineNextCycle = true;
cacheBlkValid = false;
#if !FULL_SYSTEM
// pTable = params->pTable;
#endif
fetchFault = NoFault;
serializeNext = false;
barrierInst = NULL;
status = Running;
switchedOut = false;
interruptPending = false;
}
template <class Impl>
void
FrontEnd<Impl>::dumpInsts()
{
cprintf("instBuffer size: %i\n", instBuffer.size());
InstBuffIt buff_it = instBuffer.begin();
for (int num = 0; buff_it != instBuffer.end(); num++) {
cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
"Squashed:%i\n\n",
num, (*buff_it)->readPC(), (*buff_it)->threadNumber,
(*buff_it)->seqNum, (*buff_it)->isIssued(),
(*buff_it)->isSquashed());
buff_it++;
}
}
template <class Impl>
FrontEnd<Impl>::ICacheCompletionEvent::ICacheCompletionEvent(MemReqPtr &_req, FrontEnd *fe)
: Event(&mainEventQueue, Delayed_Writeback_Pri), req(_req), frontEnd(fe)
{
this->setFlags(Event::AutoDelete);
}
template <class Impl>
void
FrontEnd<Impl>::ICacheCompletionEvent::process()
{
frontEnd->processCacheCompletion(req);
}
template <class Impl>
const char *
FrontEnd<Impl>::ICacheCompletionEvent::description()
{
return "ICache completion event";
}