summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/inorder/SConscript1
-rw-r--r--src/cpu/inorder/pipeline_traits.cc4
-rw-r--r--src/cpu/inorder/resource_pool.cc2
-rw-r--r--src/cpu/inorder/resources/cache_unit.cc101
-rw-r--r--src/cpu/inorder/resources/cache_unit.hh41
-rw-r--r--src/cpu/inorder/resources/fetch_unit.cc333
-rw-r--r--src/cpu/inorder/resources/fetch_unit.hh107
-rw-r--r--src/cpu/inorder/resources/resource_list.hh1
8 files changed, 456 insertions, 134 deletions
diff --git a/src/cpu/inorder/SConscript b/src/cpu/inorder/SConscript
index 37c235759..ae5ec0257 100644
--- a/src/cpu/inorder/SConscript
+++ b/src/cpu/inorder/SConscript
@@ -75,6 +75,7 @@ if 'InOrderCPU' in env['CPU_MODELS']:
Source('resources/bpred_unit.cc')
Source('resources/branch_predictor.cc')
Source('resources/cache_unit.cc')
+ Source('resources/fetch_unit.cc')
Source('resources/use_def.cc')
Source('resources/decode_unit.cc')
Source('resources/inst_buffer.cc')
diff --git a/src/cpu/inorder/pipeline_traits.cc b/src/cpu/inorder/pipeline_traits.cc
index fe400471a..a6fad68f7 100644
--- a/src/cpu/inorder/pipeline_traits.cc
+++ b/src/cpu/inorder/pipeline_traits.cc
@@ -70,10 +70,10 @@ void createFrontEndSchedule(DynInstPtr &inst)
// FETCH
F->needs(FetchSeq, FetchSeqUnit::AssignNextPC);
- F->needs(ICache, CacheUnit::InitiateFetch);
+ F->needs(ICache, FetchUnit::InitiateFetch);
// DECODE
- D->needs(ICache, CacheUnit::CompleteFetch);
+ D->needs(ICache, FetchUnit::CompleteFetch);
D->needs(Decode, DecodeUnit::DecodeInst);
D->needs(BPred, BranchPredictor::PredictBranch);
D->needs(FetchSeq, FetchSeqUnit::UpdateTargetPC);
diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc
index a0ec910f5..a037cbe9e 100644
--- a/src/cpu/inorder/resource_pool.cc
+++ b/src/cpu/inorder/resource_pool.cc
@@ -54,7 +54,7 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params)
stage_width * 2, 0, _cpu, params));
memObjects.push_back(ICache);
- resources.push_back(new CacheUnit("icache_port", ICache,
+ resources.push_back(new FetchUnit("icache_port", ICache,
stage_width * MaxThreads, 0, _cpu,
params));
diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc
index d36de23f9..9f3c99356 100644
--- a/src/cpu/inorder/resources/cache_unit.cc
+++ b/src/cpu/inorder/resources/cache_unit.cc
@@ -335,14 +335,6 @@ CacheUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx,
inst->readTid(), inst->seqNum, inst->getMemAddr());
break;
- case InitiateFetch:
- pkt_cmd = MemCmd::ReadReq;
-
- DPRINTF(InOrderCachePort,
- "[tid:%i]: Fetch request from [sn:%i] for addr %08p\n",
- inst->readTid(), inst->seqNum, inst->getMemAddr());
- break;
-
default:
panic("%i: Unexpected request type (%i) to %s", curTick(),
sched_entry->cmd, name());
@@ -672,38 +664,13 @@ CacheUnit::execute(int slot_num)
DynInstPtr inst = cache_req->inst;
#if TRACING_ON
ThreadID tid = inst->readTid();
- int seq_num = inst->seqNum;
std::string acc_type = "write";
-
#endif
cache_req->fault = NoFault;
switch (cache_req->cmd)
{
- case InitiateFetch:
- {
- //@TODO: Switch to size of full cache block. Store in fetch buffer
- int acc_size = sizeof(TheISA::MachInst);
-
- doTLBAccess(inst, cache_req, acc_size, 0, TheISA::TLB::Execute);
-
- // Only Do Access if no fault from TLB
- if (cache_req->fault == NoFault) {
-
- DPRINTF(InOrderCachePort,
- "[tid:%u]: Initiating fetch access to %s for addr. %08p\n",
- tid, name(), cache_req->inst->getMemAddr());
-
- cache_req->reqData = new uint8_t[acc_size];
-
- inst->setCurResSlot(slot_num);
-
- doCacheAccess(inst);
- }
-
- break;
- }
case InitiateReadData:
#if TRACING_ON
@@ -749,39 +716,6 @@ CacheUnit::execute(int slot_num)
inst->split2ndAddr, inst->split2ndFlags, NULL);
break;
-
- case CompleteFetch:
- if (cache_req->isMemAccComplete()) {
- DPRINTF(InOrderCachePort,
- "[tid:%i]: Completing Fetch Access for [sn:%i]\n",
- tid, inst->seqNum);
-
-
- DPRINTF(InOrderCachePort, "[tid:%i]: Instruction [sn:%i] is: %s\n",
- tid, seq_num,
- inst->staticInst->disassemble(inst->instAddr()));
-
- removeAddrDependency(inst);
-
- delete cache_req->dataPkt;
-
- // Do not stall and switch threads for fetch... for now..
- // TODO: We need to detect cache misses for latencies > 1
- // cache_req->setMemStall(false);
-
- cache_req->done();
- } else {
- DPRINTF(InOrderCachePort,
- "[tid:%i]: [sn:%i]: Unable to Complete Fetch Access\n",
- tid, inst->seqNum);
- DPRINTF(InOrderStall,
- "STALL: [tid:%i]: Fetch miss from %08p\n",
- tid, cache_req->inst->instAddr());
- cache_req->setCompleted(false);
- //cache_req->setMemStall(true);
- }
- break;
-
case CompleteReadData:
case CompleteWriteData:
DPRINTF(InOrderCachePort,
@@ -999,40 +933,7 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
ThreadID tid = cache_req->inst->readTid();
if (!cache_req->isSquashed()) {
- if (inst->resSched.top()->cmd == CompleteFetch) {
- DPRINTF(InOrderCachePort,
- "[tid:%u]: [sn:%i]: Processing fetch access\n",
- tid, inst->seqNum);
-
- // NOTE: This is only allowing a thread to fetch one line
- // at a time. Re-examine when/if prefetching
- // gets implemented.
- //memcpy(fetchData[tid], cache_pkt->getPtr<uint8_t>(),
- // cache_pkt->getSize());
-
- // Get the instruction from the array of the cache line.
- // @todo: update thsi
- ExtMachInst ext_inst;
- StaticInstPtr staticInst = NULL;
- TheISA::PCState instPC = inst->pcState();
- MachInst mach_inst =
- TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *>
- (cache_pkt->getPtr<uint8_t>()));
-
- predecoder.setTC(cpu->thread[tid]->getTC());
- predecoder.moreBytes(instPC, inst->instAddr(), mach_inst);
- ext_inst = predecoder.getExtMachInst(instPC);
- inst->pcState(instPC);
-
- inst->setMachInst(ext_inst);
-
- // Set Up More TraceData info
- if (inst->traceData) {
- inst->traceData->setStaticInst(inst->staticInst);
- inst->traceData->setPC(instPC);
- }
-
- } else if (inst->staticInst && inst->isMemRef()) {
+ if (inst->staticInst && inst->isMemRef()) {
DPRINTF(InOrderCachePort,
"[tid:%u]: [sn:%i]: Processing cache access\n",
tid, inst->seqNum);
diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh
index af8c4892c..69c1dbd9e 100644
--- a/src/cpu/inorder/resources/cache_unit.hh
+++ b/src/cpu/inorder/resources/cache_unit.hh
@@ -64,15 +64,10 @@ class CacheUnit : public Resource
int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params);
enum Command {
- InitiateFetch,
- CompleteFetch,
InitiateReadData,
CompleteReadData,
InitiateWriteData,
CompleteWriteData,
- Fetch,
- ReadData,
- WriteData,
InitSecondSplitRead,
InitSecondSplitWrite,
CompleteSecondSplitRead,
@@ -125,39 +120,32 @@ class CacheUnit : public Resource
void init();
ResourceRequest* getRequest(DynInstPtr _inst, int stage_num,
- int res_idx, int slot_num,
- unsigned cmd);
+ int res_idx, int slot_num,
+ unsigned cmd);
ResReqPtr findRequest(DynInstPtr inst);
ResReqPtr findSplitRequest(DynInstPtr inst, int idx);
void requestAgain(DynInstPtr inst, bool &try_request);
- int getSlot(DynInstPtr inst);
+ virtual int getSlot(DynInstPtr inst);
- /** Execute the function of this resource. The Default is action
- * is to do nothing. More specific models will derive from this
- * class and define their own execute function.
- */
- void execute(int slot_num);
+ /** Executes one of the commands from the "Command" enum */
+ virtual void execute(int slot_num);
- void squash(DynInstPtr inst, int stage_num,
+ virtual void squash(DynInstPtr inst, int stage_num,
InstSeqNum squash_seq_num, ThreadID tid);
void squashDueToMemStall(DynInstPtr inst, int stage_num,
InstSeqNum squash_seq_num, ThreadID tid);
- /** Processes cache completion event. */
- void processCacheCompletion(PacketPtr pkt);
+ /** After memory request is completedd in the cache, then do final
+ processing to complete the request in the CPU.
+ */
+ virtual void processCacheCompletion(PacketPtr pkt);
void recvRetry();
- /** Align a PC to the start of an I-cache block. */
- Addr cacheBlockAlignPC(Addr addr)
- {
- return (addr & ~(cacheBlkMask));
- }
-
/** Returns a specific port. */
Port *getPort(const std::string &if_name, int idx);
@@ -202,15 +190,6 @@ class CacheUnit : public Resource
return (addr & ~(cacheBlkMask));
}
- /** The mem line being fetched. */
- uint8_t *fetchData[ThePipeline::MaxThreads];
-
- /** @TODO: Move functionaly of fetching more than
- one instruction to 'fetch unit'*/
- /** The Addr of the cacheline that has been loaded. */
- //Addr cacheBlockAddr[ThePipeline::MaxThreads];
- //unsigned fetchOffset[ThePipeline::MaxThreads];
-
TheISA::Predecoder predecoder;
bool tlbBlocked[ThePipeline::MaxThreads];
diff --git a/src/cpu/inorder/resources/fetch_unit.cc b/src/cpu/inorder/resources/fetch_unit.cc
new file mode 100644
index 000000000..877d23375
--- /dev/null
+++ b/src/cpu/inorder/resources/fetch_unit.cc
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2011 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.
+ *
+ * Authors: Korey Sewell
+ *
+ */
+
+#include <vector>
+#include <list>
+
+#include "arch/isa_traits.hh"
+#include "arch/locked_mem.hh"
+#include "arch/utility.hh"
+#include "arch/predecoder.hh"
+#include "config/the_isa.hh"
+#include "cpu/inorder/resources/fetch_unit.hh"
+#include "cpu/inorder/pipeline_traits.hh"
+#include "cpu/inorder/cpu.hh"
+#include "cpu/inorder/resource_pool.hh"
+#include "mem/request.hh"
+
+using namespace std;
+using namespace TheISA;
+using namespace ThePipeline;
+
+FetchUnit::FetchUnit(string res_name, int res_id, int res_width,
+ int res_latency, InOrderCPU *_cpu,
+ ThePipeline::Params *params)
+ : CacheUnit(res_name, res_id, res_width, res_latency, _cpu,
+ params)
+{ }
+
+int
+FetchUnit::getSlot(DynInstPtr inst)
+{
+ if (tlbBlocked[inst->threadNumber]) {
+ return -1;
+ }
+
+ if (!inst->validMemAddr()) {
+ panic("[tid:%i][sn:%i] Mem. Addr. must be set before requesting "
+ "cache access\n", inst->readTid(), inst->seqNum);
+ }
+
+ int new_slot = Resource::getSlot(inst);
+
+ if (new_slot == -1)
+ return -1;
+
+ inst->memTime = curTick();
+ return new_slot;
+}
+
+void
+FetchUnit::removeAddrDependency(DynInstPtr inst)
+{
+ inst->unsetMemAddr();
+}
+
+ResReqPtr
+FetchUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx,
+ int slot_num, unsigned cmd)
+{
+ ScheduleEntry* sched_entry = inst->resSched.top();
+
+ if (!inst->validMemAddr()) {
+ panic("Mem. Addr. must be set before requesting cache access\n");
+ }
+
+ MemCmd::Command pkt_cmd;
+
+ switch (sched_entry->cmd)
+ {
+ case InitiateFetch:
+ pkt_cmd = MemCmd::ReadReq;
+
+ DPRINTF(InOrderCachePort,
+ "[tid:%i]: Fetch request from [sn:%i] for addr %08p\n",
+ inst->readTid(), inst->seqNum, inst->getMemAddr());
+ break;
+
+ default:
+ panic("%i: Unexpected request type (%i) to %s", curTick(),
+ sched_entry->cmd, name());
+ }
+
+ return new CacheRequest(this, inst, stage_num, id, slot_num,
+ sched_entry->cmd, 0, pkt_cmd,
+ 0/*flags*/, this->cpu->readCpuId(),
+ inst->resSched.top()->idx);
+}
+
+void
+FetchUnit::setupMemRequest(DynInstPtr inst, CacheReqPtr cache_req,
+ int acc_size, int flags)
+{
+ ThreadID tid = inst->readTid();
+ Addr aligned_addr = inst->getMemAddr();
+
+ inst->fetchMemReq =
+ new Request(inst->readTid(), aligned_addr, acc_size, flags,
+ inst->instAddr(), cpu->readCpuId(), inst->readTid());
+
+ cache_req->memReq = inst->fetchMemReq;
+}
+
+
+void
+FetchUnit::execute(int slot_num)
+{
+ CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(reqMap[slot_num]);
+ assert(cache_req);
+
+ if (cachePortBlocked) {
+ DPRINTF(InOrderCachePort, "Cache Port Blocked. Cannot Access\n");
+ cache_req->setCompleted(false);
+ return;
+ }
+
+ DynInstPtr inst = cache_req->inst;
+#if TRACING_ON
+ ThreadID tid = inst->readTid();
+ int seq_num = inst->seqNum;
+ std::string acc_type = "write";
+#endif
+
+ cache_req->fault = NoFault;
+
+ switch (cache_req->cmd)
+ {
+ case InitiateFetch:
+ {
+ doTLBAccess(inst, cache_req, cacheBlkSize, 0, TheISA::TLB::Execute);
+
+ if (cache_req->fault == NoFault) {
+ DPRINTF(InOrderCachePort,
+ "[tid:%u]: Initiating fetch access to %s for addr. %08p\n",
+ tid, name(), cache_req->inst->getMemAddr());
+
+ cache_req->reqData = new uint8_t[cacheBlksize];
+
+ inst->setCurResSlot(slot_num);
+
+ doCacheAccess(inst);
+ }
+
+ break;
+ }
+
+ case CompleteFetch:
+ if (cache_req->isMemAccComplete()) {
+ DPRINTF(InOrderCachePort,
+ "[tid:%i]: Completing Fetch Access for [sn:%i]\n",
+ tid, inst->seqNum);
+
+
+ DPRINTF(InOrderCachePort, "[tid:%i]: Instruction [sn:%i] is: %s\n",
+ tid, seq_num,
+ inst->staticInst->disassemble(inst->instAddr()));
+
+ removeAddrDependency(inst);
+
+ delete cache_req->dataPkt;
+
+ // Do not stall and switch threads for fetch... for now..
+ // TODO: We need to detect cache misses for latencies > 1
+ // cache_req->setMemStall(false);
+
+ cache_req->done();
+ } else {
+ DPRINTF(InOrderCachePort,
+ "[tid:%i]: [sn:%i]: Unable to Complete Fetch Access\n",
+ tid, inst->seqNum);
+ DPRINTF(InOrderStall,
+ "STALL: [tid:%i]: Fetch miss from %08p\n",
+ tid, cache_req->inst->instAddr());
+ cache_req->setCompleted(false);
+ //cache_req->setMemStall(true);
+ }
+ break;
+
+ default:
+ fatal("Unrecognized command to %s", resName);
+ }
+}
+
+void
+FetchUnit::processCacheCompletion(PacketPtr pkt)
+{
+ // Cast to correct packet type
+ CacheReqPacket* cache_pkt = dynamic_cast<CacheReqPacket*>(pkt);
+
+ assert(cache_pkt);
+
+ if (cache_pkt->cacheReq->isSquashed()) {
+ DPRINTF(InOrderCachePort,
+ "Ignoring completion of squashed access, [tid:%i] [sn:%i]\n",
+ cache_pkt->cacheReq->getInst()->readTid(),
+ cache_pkt->cacheReq->getInst()->seqNum);
+ DPRINTF(RefCount,
+ "Ignoring completion of squashed access, [tid:%i] [sn:%i]\n",
+ cache_pkt->cacheReq->getTid(),
+ cache_pkt->cacheReq->seqNum);
+
+ cache_pkt->cacheReq->done();
+ delete cache_pkt;
+
+ cpu->wakeCPU();
+
+ return;
+ }
+
+ DPRINTF(InOrderCachePort,
+ "[tid:%u]: [sn:%i]: Waking from cache access to addr. %08p\n",
+ cache_pkt->cacheReq->getInst()->readTid(),
+ cache_pkt->cacheReq->getInst()->seqNum,
+ cache_pkt->cacheReq->getInst()->getMemAddr());
+
+ // Cast to correct request type
+ CacheRequest *cache_req = dynamic_cast<CacheReqPtr>(
+ findRequest(cache_pkt->cacheReq->getInst(), cache_pkt->instIdx));
+
+ if (!cache_req) {
+ panic("[tid:%u]: [sn:%i]: Can't find slot for cache access to "
+ "addr. %08p\n", cache_pkt->cacheReq->getInst()->readTid(),
+ cache_pkt->cacheReq->getInst()->seqNum,
+ cache_pkt->cacheReq->getInst()->getMemAddr());
+ }
+
+ assert(cache_req);
+
+
+ // Get resource request info
+ unsigned stage_num = cache_req->getStageNum();
+ DynInstPtr inst = cache_req->inst;
+ ThreadID tid = cache_req->inst->readTid();
+
+ if (!cache_req->isSquashed()) {
+ assert(inst->resSched.top()->cmd == CompleteFetch);
+
+ DPRINTF(InOrderCachePort,
+ "[tid:%u]: [sn:%i]: Processing fetch access\n",
+ tid, inst->seqNum);
+
+ // NOTE: This is only allowing a thread to fetch one line
+ // at a time. Re-examine when/if prefetching
+ // gets implemented.
+ // memcpy(fetchData[tid], cache_pkt->getPtr<uint8_t>(),
+ // cache_pkt->getSize());
+
+ // Get the instruction from the array of the cache line.
+ // @todo: update this
+ ExtMachInst ext_inst;
+ StaticInstPtr staticInst = NULL;
+ TheISA::PCState instPC = inst->pcState();
+ MachInst mach_inst =
+ TheISA::gtoh(*reinterpret_cast<TheISA::MachInst *>
+ (cache_pkt->getPtr<uint8_t>()));
+
+ predecoder.setTC(cpu->thread[tid]->getTC());
+ predecoder.moreBytes(instPC, inst->instAddr(), mach_inst);
+ ext_inst = predecoder.getExtMachInst(instPC);
+ inst->pcState(instPC);
+
+ inst->setMachInst(ext_inst);
+
+ // Set Up More TraceData info
+ if (inst->traceData) {
+ inst->traceData->setStaticInst(inst->staticInst);
+ inst->traceData->setPC(instPC);
+ }
+
+ cache_req->setMemAccPending(false);
+ cache_req->setMemAccCompleted();
+
+ if (cache_req->isMemStall() &&
+ cpu->threadModel == InOrderCPU::SwitchOnCacheMiss) {
+ DPRINTF(InOrderCachePort, "[tid:%u] Waking up from Cache Miss.\n",
+ tid);
+
+ cpu->activateContext(tid);
+
+ DPRINTF(ThreadModel, "Activating [tid:%i] after return from cache"
+ "miss.\n", tid);
+ }
+
+ // Wake up the CPU (if it went to sleep and was waiting on this
+ // completion event).
+ cpu->wakeCPU();
+
+ DPRINTF(Activity, "[tid:%u] Activating %s due to cache completion\n",
+ tid, cpu->pipelineStage[stage_num]->name());
+
+ cpu->switchToActive(stage_num);
+ } else {
+ DPRINTF(InOrderCachePort,
+ "[tid:%u] Miss on block @ %08p completed, but squashed\n",
+ tid, cache_req->inst->instAddr());
+ cache_req->setMemAccCompleted();
+ }
+}
+
+void
+FetchUnit::squash(DynInstPtr inst, int stage_num,
+ InstSeqNum squash_seq_num, ThreadID tid)
+{
+ CacheUnit::squash(inst, stage_num, squash_seq_num, tid);
+}
+
diff --git a/src/cpu/inorder/resources/fetch_unit.hh b/src/cpu/inorder/resources/fetch_unit.hh
new file mode 100644
index 000000000..257a8c50a
--- /dev/null
+++ b/src/cpu/inorder/resources/fetch_unit.hh
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2011 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.
+ *
+ * Authors: Korey Sewell
+ *
+ */
+
+#ifndef __CPU_INORDER_FETCH_UNIT_HH__
+#define __CPU_INORDER_FETCH_UNIT_HH__
+
+#include <vector>
+#include <list>
+#include <string>
+
+#include "arch/predecoder.hh"
+#include "arch/tlb.hh"
+#include "config/the_isa.hh"
+#include "cpu/inorder/inorder_dyn_inst.hh"
+#include "cpu/inorder/pipeline_traits.hh"
+#include "cpu/inorder/resource.hh"
+#include "cpu/inorder/resources/cache_unit.hh"
+#include "mem/packet.hh"
+#include "mem/packet_access.hh"
+#include "mem/port.hh"
+#include "params/InOrderCPU.hh"
+#include "sim/sim_object.hh"
+
+class FetchUnit : public CacheUnit
+{
+ public:
+ typedef ThePipeline::DynInstPtr DynInstPtr;
+
+ public:
+ FetchUnit(std::string res_name, int res_id, int res_width,
+ int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params);
+
+ /** Actions that this resources can take on an instruction */
+ enum Command {
+ InitiateFetch,
+ CompleteFetch
+ };
+
+ public:
+ ResourceRequest* getRequest(DynInstPtr _inst, int stage_num,
+ int res_idx, int slot_num,
+ unsigned cmd);
+
+ int getSlot(DynInstPtr inst);
+
+ /** Executes one of the commands from the "Command" enum */
+ void execute(int slot_num);
+
+ void squash(DynInstPtr inst, int stage_num,
+ InstSeqNum squash_seq_num, ThreadID tid);
+
+ /** After memory request is completed, then turn the fetched data
+ into an instruction.
+ */
+ void processCacheCompletion(PacketPtr pkt);
+
+ /** Create request that will interface w/TLB and Memory objects */
+ virtual void setupMemRequest(DynInstPtr inst, CacheReqPtr cache_req,
+ int acc_size, int flags);
+
+ /** Align a PC to the start of an I-cache block. */
+ Addr cacheBlockAlignPC(Addr addr)
+ {
+ return (addr & ~(cacheBlkMask));
+ }
+
+ void removeAddrDependency(DynInstPtr inst);
+
+ public:
+ /** The mem line being fetched. */
+ uint8_t *fetchData[ThePipeline::MaxThreads];
+
+
+ /** The Addr of the cacheline that has been loaded. */
+ //Addr cacheBlockAddr[ThePipeline::MaxThreads];
+ //unsigned fetchOffset[ThePipeline::MaxThreads];
+};
+
+#endif //__CPU_FETCH_UNIT_HH__
diff --git a/src/cpu/inorder/resources/resource_list.hh b/src/cpu/inorder/resources/resource_list.hh
index cbe2ad8c3..5568ad470 100644
--- a/src/cpu/inorder/resources/resource_list.hh
+++ b/src/cpu/inorder/resources/resource_list.hh
@@ -33,6 +33,7 @@
#define CPU_INORDER_RESOURCE_LIST_HH
#include "cpu/inorder/resources/cache_unit.hh"
+#include "cpu/inorder/resources/fetch_unit.hh"
#include "cpu/inorder/resources/execution_unit.hh"
#include "cpu/inorder/resources/use_def.hh"
#include "cpu/inorder/resources/inst_buffer.hh"