* Authors: Kevin Lim
*/
-#include "config/use_checker.hh"
-
-#include "arch/faults.hh"
+#include "sim/faults.hh"
#include "arch/isa_traits.hh"
+#include "arch/utility.hh"
#include "base/statistics.hh"
+#include "config/the_isa.hh"
+#include "config/use_checker.hh"
#include "cpu/thread_context.hh"
#include "cpu/exetrace.hh"
#include "cpu/ozone/front_end.hh"
+#include "mem/mem_object.hh"
#include "mem/packet.hh"
#include "mem/request.hh"
void
FrontEnd<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
{
- panic("FrontEnd doesn't expect recvFunctional callback!");
+ warn("FrontEnd doesn't update state from functional calls");
}
template<class Impl>
template<class Impl>
bool
-FrontEnd<Impl>::IcachePort::recvTiming(Packet *pkt)
+FrontEnd<Impl>::IcachePort::recvTiming(PacketPtr pkt)
{
fe->processCacheCompletion(pkt);
return true;
FrontEnd<Impl>::FrontEnd(Params *params)
: branchPred(params),
icachePort(this),
- mem(params->mem),
+ numInstsReady(params->frontEndLatency, 0),
instBufferSize(0),
maxInstBufferSize(params->maxInstBufferSize),
+ latency(params->frontEndLatency),
width(params->frontEndWidth),
freeRegs(params->numPhysicalRegs),
numPhysRegs(params->numPhysicalRegs),
icachePort.setName(this->name() + "-iport");
- Port *mem_dport = mem->getPort("");
- icachePort.setPeer(mem_dport);
- mem_dport->setPeer(&icachePort);
-
#if USE_CHECKER
if (cpu->checker) {
cpu->checker->setIcachePort(&icachePort);
if (switchedOut)
return;
+ for (int insts_to_queue = numInstsReady[-latency];
+ !instBuffer.empty() && insts_to_queue;
+ --insts_to_queue)
+ {
+ DPRINTF(FE, "Transferring instruction [sn:%lli] to the feBuffer\n",
+ instBuffer.front()->seqNum);
+ feBuffer.push_back(instBuffer.front());
+ instBuffer.pop_front();
+ }
+
+ numInstsReady.advance();
+
// @todo: Maybe I want to just have direct communication...
if (fromCommit->doneSeqNum) {
branchPred.update(fromCommit->doneSeqNum, 0);
cacheBlkValid = true;
status = Running;
- if (barrierInst)
- status = SerializeBlocked;
+// if (barrierInst)
+// status = SerializeBlocked;
if (freeRegs <= 0)
status = RenameBlocked;
checkBE();
// latency
instBuffer.push_back(inst);
++instBufferSize;
+ numInstsReady[0]++;
++num_inst;
#if FULL_SYSTEM
if (inst->isQuiesce()) {
- warn("%lli: Quiesce instruction encountered, halting fetch!", curTick);
+// warn("%lli: Quiesce instruction encountered, halting fetch!", curTick);
status = QuiescePending;
break;
}
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;
- if (interruptPending && flags == 0) {
+ //AlphaDep
+ if (interruptPending && (PC & 0x3)) {
return fault;
}
// Setup the memReq to do a read of the first isntruction's address.
// Set the appropriate read size and flags as well.
- memReq = new Request(0, fetch_PC, cacheBlkSize, flags,
- fetch_PC, cpu->readCpuId(), 0);
+ memReq = new Request(0, fetch_PC, cacheBlkSize, 0,
+ PC, cpu->thread->contextId());
// Translate the instruction request.
- fault = cpu->translateInstReq(memReq, thread);
+ fault = cpu->itb->translateAtomic(memReq, thread, false, true);
// Now do the timing access to see whether or not the instruction
// exists within the cache.
if (fault == NoFault) {
#if 0
if (cpu->system->memctrl->badaddr(memReq->paddr) ||
- memReq->flags & UNCACHEABLE) {
+ memReq->isUncacheable()) {
DPRINTF(FE, "Fetch: Bad address %#x (hopefully on a "
"misspeculating path!",
memReq->paddr);
// Change status over to SerializeBlocked so that other stages know
// what this is blocked on.
- status = SerializeBlocked;
+// status = SerializeBlocked;
- barrierInst = inst;
- return true;
+// barrierInst = inst;
+// return true;
} else if ((inst->isStoreConditional() || inst->isSerializeAfter())
&& !inst->isSerializeHandled()) {
DPRINTF(FE, "Serialize after instruction encountered.\n");
instruction->fault = fault;
instruction->setCanIssue();
instBuffer.push_back(instruction);
+ numInstsReady[0]++;
++instBufferSize;
}
freeRegs+= inst->numDestRegs();
}
+ while (!feBuffer.empty() &&
+ feBuffer.back()->seqNum > squash_num) {
+ DynInstPtr inst = feBuffer.back();
+
+ DPRINTF(FE, "Squashing instruction [sn:%lli] PC %#x\n",
+ inst->seqNum, inst->readPC());
+
+ inst->clearDependents();
+
+ feBuffer.pop_back();
+ --instBufferSize;
+
+ freeRegs+= inst->numDestRegs();
+ }
+
// Copy over rename table from the back end.
renameTable.copyFrom(backEnd->renameTable);
DPRINTF(FE, "Squashing outstanding Icache access.\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.
typename Impl::DynInstPtr
FrontEnd<Impl>::getInst()
{
- if (instBufferSize == 0) {
+ if (feBuffer.empty()) {
return NULL;
}
- DynInstPtr inst = instBuffer.front();
+ DynInstPtr inst = feBuffer.front();
+
+ if (inst->isSerializeBefore() || inst->isIprAccess()) {
+ DPRINTF(FE, "Back end is getting a serialize before inst\n");
+ if (!backEnd->robEmpty()) {
+ DPRINTF(FE, "Rob is not empty yet, not returning inst\n");
+ return NULL;
+ }
+ inst->clearSerializeBefore();
+ }
- instBuffer.pop_front();
+ feBuffer.pop_front();
--instBufferSize;
}
if (status == BEBlocked && !be_block) {
- if (barrierInst) {
- status = SerializeBlocked;
- } else {
+// if (barrierInst) {
+// status = SerializeBlocked;
+// } else {
status = Running;
- }
+// }
ret_val = true;
}
return ret_val;
typename Impl::DynInstPtr
FrontEnd<Impl>::getInstFromCacheline()
{
+/*
if (status == SerializeComplete) {
DynInstPtr inst = barrierInst;
status = Running;
inst->clearSerializeBefore();
return inst;
}
-
+*/
InstSeqNum inst_seq;
MachInst inst;
// @todo: Fix this magic number used here to handle word offset (and
// Get the instruction from the array of the cache line.
inst = htog(*reinterpret_cast<MachInst *>(&cacheData[offset]));
+#if THE_ISA == ALPHA_ISA
ExtMachInst decode_inst = TheISA::makeExtMI(inst, PC);
+#elif THE_ISA == SPARC_ISA
+ ExtMachInst decode_inst = TheISA::makeExtMI(inst, tc);
+#endif
// Create a new DynInst from the instruction fetched.
DynInstPtr instruction = new DynInst(decode_inst, PC, PC+sizeof(MachInst),
instruction->staticInst->disassemble(PC));
instruction->traceData =
- Trace::getInstRecord(curTick, tc, cpu,
+ Trace::getInstRecord(curTick, tc,
instruction->staticInst,
- instruction->readPC(), 0);
+ instruction->readPC());
// Increment stat of fetched instructions.
++fetchedInsts;
squash(0, 0);
instBuffer.clear();
instBufferSize = 0;
+ feBuffer.clear();
status = Idle;
}