summaryrefslogtreecommitdiff
path: root/src/cpu/inorder/resources/fetch_unit.cc
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2015-04-20 12:46:35 -0400
committerAndreas Hansson <andreas.hansson@arm.com>2015-04-20 12:46:35 -0400
commitcd76e34056afab83697beef1d1ced94ee671a20d (patch)
tree8adaa80ba72593bdf67103ad5cd0a072b95e8acb /src/cpu/inorder/resources/fetch_unit.cc
parent076ea249ae47b935bea424954174f33fdecb7fcc (diff)
downloadgem5-cd76e34056afab83697beef1d1ced94ee671a20d.tar.xz
cpu: Remove the InOrderCPU from the tree
This patch takes the final step in removing the InOrderCPU from the tree. Rest in peace. The MinorCPU is now used to model an in-order microarchitecture, and long term the MinorCPU will eventually be renamed InOrderCPU.
Diffstat (limited to 'src/cpu/inorder/resources/fetch_unit.cc')
-rw-r--r--src/cpu/inorder/resources/fetch_unit.cc591
1 files changed, 0 insertions, 591 deletions
diff --git a/src/cpu/inorder/resources/fetch_unit.cc b/src/cpu/inorder/resources/fetch_unit.cc
deleted file mode 100644
index 13864e589..000000000
--- a/src/cpu/inorder/resources/fetch_unit.cc
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- * 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 <list>
-#include <vector>
-
-#include "arch/isa_traits.hh"
-#include "arch/locked_mem.hh"
-#include "arch/utility.hh"
-#include "config/the_isa.hh"
-#include "cpu/inorder/resources/cache_unit.hh"
-#include "cpu/inorder/resources/fetch_unit.hh"
-#include "cpu/inorder/cpu.hh"
-#include "cpu/inorder/pipeline_traits.hh"
-#include "cpu/inorder/resource_pool.hh"
-#include "debug/Activity.hh"
-#include "debug/InOrderCachePort.hh"
-#include "debug/InOrderStall.hh"
-#include "debug/RefCount.hh"
-#include "debug/ThreadModel.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,
- Cycles res_latency, InOrderCPU *_cpu,
- ThePipeline::Params *params)
- : CacheUnit(res_name, res_id, res_width, res_latency, _cpu, params),
- instSize(sizeof(TheISA::MachInst)), fetchBuffSize(params->fetchBuffSize)
-{
- for (int tid = 0; tid < MaxThreads; tid++)
- decoder[tid] = new Decoder;
-}
-
-FetchUnit::~FetchUnit()
-{
- std::list<FetchBlock*>::iterator fetch_it = fetchBuffer.begin();
- std::list<FetchBlock*>::iterator end_it = fetchBuffer.end();
- while (fetch_it != end_it) {
- delete (*fetch_it)->block;
- delete *fetch_it;
- fetch_it++;
- }
- fetchBuffer.clear();
-
-
- std::list<FetchBlock*>::iterator pend_it = pendingFetch.begin();
- std::list<FetchBlock*>::iterator pend_end = pendingFetch.end();
- while (pend_it != pend_end) {
- if ((*pend_it)->block) {
- delete (*pend_it)->block;
- }
-
- delete *pend_it;
- pend_it++;
- }
- pendingFetch.clear();
-}
-
-void
-FetchUnit::createMachInst(std::list<FetchBlock*>::iterator fetch_it,
- DynInstPtr inst)
-{
- Addr block_addr = cacheBlockAlign(inst->getMemAddr());
- Addr fetch_addr = inst->getMemAddr();
- unsigned fetch_offset = (fetch_addr - block_addr) / instSize;
- ThreadID tid = inst->readTid();
- TheISA::PCState instPC = inst->pcState();
-
-
- DPRINTF(InOrderCachePort, "Creating instruction [sn:%i] w/fetch data @"
- "addr:%08p block:%08p\n", inst->seqNum, fetch_addr, block_addr);
-
- assert((*fetch_it)->valid);
-
- TheISA::MachInst *fetchInsts =
- reinterpret_cast<TheISA::MachInst *>((*fetch_it)->block);
-
- MachInst mach_inst =
- TheISA::gtoh(fetchInsts[fetch_offset]);
-
- decoder[tid]->moreBytes(instPC, inst->instAddr(), mach_inst);
- assert(decoder[tid]->instReady());
- inst->setStaticInst(decoder[tid]->decode(instPC));
- inst->pcState(instPC);
-}
-
-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->curSkedEntry;
- CacheRequest* cache_req = dynamic_cast<CacheRequest*>(reqs[slot_num]);
-
- if (!inst->validMemAddr()) {
- panic("Mem. Addr. must be set before requesting cache access\n");
- }
-
- assert(sched_entry->cmd == InitiateFetch);
-
- DPRINTF(InOrderCachePort,
- "[tid:%i]: Fetch request from [sn:%i] for addr %08p\n",
- inst->readTid(), inst->seqNum, inst->getMemAddr());
-
- cache_req->setRequest(inst, stage_num, id, slot_num,
- sched_entry->cmd, MemCmd::ReadReq,
- inst->curSkedEntry->idx);
-
- return cache_req;
-}
-
-void
-FetchUnit::setupMemRequest(DynInstPtr inst, CacheReqPtr cache_req,
- int acc_size, int flags)
-{
- ThreadID tid = inst->readTid();
- Addr aligned_addr = cacheBlockAlign(inst->getMemAddr());
- if (cache_req->memReq == NULL) {
- cache_req->memReq =
- new Request(tid, aligned_addr, acc_size, flags,
- cpu->instMasterId(), inst->instAddr(), cpu->readCpuId(),
- tid);
- DPRINTF(InOrderCachePort, "[sn:%i] Created memReq @%x, ->%x\n",
- inst->seqNum, &cache_req->memReq, cache_req->memReq);
- }
-}
-
-std::list<FetchUnit::FetchBlock*>::iterator
-FetchUnit::findBlock(std::list<FetchBlock*> &fetch_blocks, int asid,
- Addr block_addr)
-{
- std::list<FetchBlock*>::iterator fetch_it = fetch_blocks.begin();
- std::list<FetchBlock*>::iterator end_it = fetch_blocks.end();
-
- while (fetch_it != end_it) {
- if ((*fetch_it)->asid == asid &&
- (*fetch_it)->addr == block_addr) {
- return fetch_it;
- }
-
- fetch_it++;
- }
-
- return fetch_it;
-}
-
-std::list<FetchUnit::FetchBlock*>::iterator
-FetchUnit::findReplacementBlock()
-{
- std::list<FetchBlock*>::iterator fetch_it = fetchBuffer.begin();
- std::list<FetchBlock*>::iterator end_it = fetchBuffer.end();
-
- while (fetch_it != end_it) {
- if ((*fetch_it)->cnt == 0) {
- return fetch_it;
- } else {
- DPRINTF(InOrderCachePort, "Block %08p has %i insts pending.\n",
- (*fetch_it)->addr, (*fetch_it)->cnt);
- }
- fetch_it++;
- }
-
- return fetch_it;
-}
-
-void
-FetchUnit::markBlockUsed(std::list<FetchBlock*>::iterator block_it)
-{
- // Move block from whatever location it is in fetch buffer
- // to the back (represents most-recently-used location)
- if (block_it != fetchBuffer.end()) {
- FetchBlock *mru_blk = *block_it;
- fetchBuffer.erase(block_it);
- fetchBuffer.push_back(mru_blk);
- }
-}
-
-int
-FetchUnit::blocksInUse()
-{
- std::list<FetchBlock*>::iterator fetch_it = fetchBuffer.begin();
- std::list<FetchBlock*>::iterator end_it = fetchBuffer.end();
-
- int cnt = 0;
- while (fetch_it != end_it) {
- if ((*fetch_it)->cnt > 0)
- cnt++;
-
- fetch_it++;
- }
-
- return cnt;
-}
-
-void
-FetchUnit::clearFetchBuffer()
-{
- std::list<FetchBlock*>::iterator fetch_it = fetchBuffer.begin();
- std::list<FetchBlock*>::iterator end_it = fetchBuffer.end();
-
- while (fetch_it != end_it) {
- if ((*fetch_it)->block) {
- delete [] (*fetch_it)->block;
- }
- delete *fetch_it;
- fetch_it++;
- }
- fetchBuffer.clear();
-}
-
-void
-FetchUnit::execute(int slot_num)
-{
- CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(reqs[slot_num]);
- assert(cache_req);
-
- if (cachePortBlocked && cache_req->cmd == InitiateFetch) {
- DPRINTF(InOrderCachePort, "Cache Port Blocked. Cannot Access\n");
- cache_req->done(false);
- return;
- }
-
- DynInstPtr inst = cache_req->inst;
- ThreadID tid = inst->readTid();
- Addr block_addr = cacheBlockAlign(inst->getMemAddr());
- int asid = cpu->asid[tid];
-
- if (inst->fault != NoFault) {
- DPRINTF(InOrderCachePort,
- "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
- "next stage.\n", tid, inst->seqNum, inst->fault->name(),
- cacheBlockAlign(inst->getMemAddr()));
- finishCacheUnitReq(inst, cache_req);
- return;
- }
-
- switch (cache_req->cmd)
- {
- case InitiateFetch:
- {
- // Check to see if we've already got this request buffered
- // or pending to be buffered
- bool do_fetch = true;
- int total_pending = pendingFetch.size() + blocksInUse();
-
- std::list<FetchBlock*>::iterator pending_it;
- pending_it = findBlock(pendingFetch, asid, block_addr);
- if (pending_it != pendingFetch.end()) {
- (*pending_it)->cnt++;
- do_fetch = false;
-
- DPRINTF(InOrderCachePort, "%08p is a pending fetch block "
- "(pending:%i).\n", block_addr,
- (*pending_it)->cnt);
- } else if (total_pending < fetchBuffSize) {
- std::list<FetchBlock*>::iterator buff_it;
- buff_it = findBlock(fetchBuffer, asid, block_addr);
- if (buff_it != fetchBuffer.end()) {
- (*buff_it)->cnt++;
- do_fetch = false;
-
- DPRINTF(InOrderCachePort, "%08p is in fetch buffer "
- "(pending:%i).\n", block_addr, (*buff_it)->cnt);
- }
- }
-
- if (!do_fetch) {
- DPRINTF(InOrderCachePort, "Inst. [sn:%i] marked to be filled "
- "through fetch buffer.\n", inst->seqNum);
- cache_req->fetchBufferFill = true;
- cache_req->setCompleted(true);
- return;
- }
-
- // Check to see if there is room in the fetchbuffer for this instruction.
- // If not, block this request.
- if (total_pending >= fetchBuffSize) {
- DPRINTF(InOrderCachePort, "No room available in fetch buffer.\n");
- cache_req->done(false);
- return;
- }
-
- doTLBAccess(inst, cache_req, cacheBlkSize, Request::INST_FETCH, TheISA::TLB::Execute);
-
- if (inst->fault == NoFault) {
- DPRINTF(InOrderCachePort,
- "[tid:%u]: Initiating fetch access to %s for "
- "addr:%#x (block:%#x)\n", tid, name(),
- cache_req->inst->getMemAddr(), block_addr);
-
- cache_req->reqData = new uint8_t[cacheBlkSize];
-
- inst->setCurResSlot(slot_num);
-
- doCacheAccess(inst);
-
- if (cache_req->isMemAccPending()) {
- pendingFetch.push_back(new FetchBlock(asid, block_addr));
-
- // mark replacement block
- }
- }
-
- break;
- }
-
- case CompleteFetch:
- if (inst->fault != NoFault) {
- DPRINTF(InOrderCachePort,
- "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
- "next stage.\n", tid, inst->seqNum, inst->fault->name(),
- inst->getMemAddr());
- finishCacheUnitReq(inst, cache_req);
- return;
- }
-
- if (cache_req->fetchBufferFill) {
- // Block request if it's depending on a previous fetch, but it hasnt made it yet
- std::list<FetchBlock*>::iterator fetch_it = findBlock(fetchBuffer, asid, block_addr);
- if (fetch_it == fetchBuffer.end()) {
- DPRINTF(InOrderCachePort, "%#x not available yet\n",
- block_addr);
- cache_req->setCompleted(false);
- return;
- }
-
- // Make New Instruction
- createMachInst(fetch_it, inst);
- if (inst->traceData) {
- inst->traceData->setStaticInst(inst->staticInst);
- inst->traceData->setPC(inst->pcState());
- }
-
- // FetchBuffer Book-Keeping
- (*fetch_it)->cnt--;
- assert((*fetch_it)->cnt >= 0);
- markBlockUsed(fetch_it);
-
- cache_req->done();
- return;
- }
-
- if (cache_req->isMemAccComplete()) {
- if (fetchBuffer.size() >= fetchBuffSize) {
- // If there is no replacement block, then we'll just have
- // to wait till that gets cleared before satisfying the fetch
- // for this instruction
- std::list<FetchBlock*>::iterator repl_it =
- findReplacementBlock();
- if (repl_it == fetchBuffer.end()) {
- DPRINTF(InOrderCachePort, "Unable to find replacement block"
- " and complete fetch.\n");
- cache_req->setCompleted(false);
- return;
- }
-
- delete [] (*repl_it)->block;
- delete *repl_it;
- fetchBuffer.erase(repl_it);
- }
-
- DPRINTF(InOrderCachePort,
- "[tid:%i]: Completing Fetch Access for [sn:%i]\n",
- tid, inst->seqNum);
-
- // Make New Instruction
- std::list<FetchBlock*>::iterator fetch_it =
- findBlock(pendingFetch, asid, block_addr);
-
- assert(fetch_it != pendingFetch.end());
- assert((*fetch_it)->valid);
-
- createMachInst(fetch_it, inst);
- if (inst->traceData) {
- inst->traceData->setStaticInst(inst->staticInst);
- inst->traceData->setPC(inst->pcState());
- }
-
-
- // Update instructions waiting on new fetch block
- FetchBlock *new_block = (*fetch_it);
- new_block->cnt--;
- assert(new_block->cnt >= 0);
-
- // Finally, update FetchBuffer w/Pending Block into the
- // MRU location
- pendingFetch.erase(fetch_it);
- fetchBuffer.push_back(new_block);
-
- DPRINTF(InOrderCachePort, "[tid:%i]: Instruction [sn:%i] is: %s\n",
- tid, inst->seqNum,
- inst->staticInst->disassemble(inst->instAddr()));
-
- inst->unsetMemAddr();
-
- 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);
- // NOTE: For SwitchOnCacheMiss ThreadModel, we *don't* switch on
- // fetch miss, but we could ...
- // cache_req->setMemStall(true);
- }
- break;
-
- default:
- fatal("Unrecognized command to %s", resName);
- }
-}
-
-void
-FetchUnit::processCacheCompletion(PacketPtr pkt)
-{
- // Cast to correct packet type
- // @todo: use pkt Sender state here to be consistent with other
- // cpu models
- CacheReqPacket* cache_pkt = dynamic_cast<CacheReqPacket*>(pkt);
- assert(cache_pkt);
-
- DPRINTF(InOrderCachePort, "Finished request for %x\n",
- cache_pkt->getAddr());
-
- if (processSquash(cache_pkt))
- return;
-
- Addr block_addr = cacheBlockAlign(cache_pkt->cacheReq->
- getInst()->getMemAddr());
-
- DPRINTF(InOrderCachePort,
- "[tid:%u]: [sn:%i]: Waking from fetch access to addr:%#x(phys:%#x), size:%i\n",
- cache_pkt->cacheReq->getInst()->readTid(),
- cache_pkt->cacheReq->getInst()->seqNum,
- block_addr, cache_pkt->getAddr(), cache_pkt->getSize());
-
- // 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 fetch access to "
- "addr. %08p\n", cache_pkt->cacheReq->getInst()->readTid(),
- cache_pkt->cacheReq->getInst()->seqNum,
- block_addr);
- }
-
- // Get resource request info
- unsigned stage_num = cache_req->getStageNum();
- DynInstPtr inst = cache_req->inst;
- ThreadID tid = cache_req->inst->readTid();
- short asid = cpu->asid[tid];
-
- assert(!cache_req->isSquashed());
- assert(inst->curSkedEntry->cmd == CompleteFetch);
-
- DPRINTF(InOrderCachePort,
- "[tid:%u]: [sn:%i]: Processing fetch access for block %#x\n",
- tid, inst->seqNum, block_addr);
-
- std::list<FetchBlock*>::iterator pend_it = findBlock(pendingFetch, asid,
- block_addr);
- assert(pend_it != pendingFetch.end());
-
- // Copy Data to pendingFetch queue...
- (*pend_it)->block = new uint8_t[cacheBlkSize];
- memcpy((*pend_it)->block, cache_pkt->getConstPtr<uint8_t>(), cacheBlkSize);
- (*pend_it)->valid = true;
-
- 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);
-}
-
-void
-FetchUnit::squashCacheRequest(CacheReqPtr req_ptr)
-{
- DynInstPtr inst = req_ptr->getInst();
- ThreadID tid = inst->readTid();
- Addr block_addr = cacheBlockAlign(inst->getMemAddr());
- int asid = cpu->asid[tid];
-
- // Check Fetch Buffer (or pending fetch) for this block and
- // update pending counts
- std::list<FetchBlock*>::iterator buff_it = findBlock(fetchBuffer,
- asid,
- block_addr);
- if (buff_it != fetchBuffer.end()) {
- (*buff_it)->cnt--;
- DPRINTF(InOrderCachePort, "[sn:%i] Removing Pending Access "
- "for Fetch Buffer block %08p (cnt=%i)\n", inst->seqNum,
- block_addr, (*buff_it)->cnt);
- assert((*buff_it)->cnt >= 0);
- } else {
- std::list<FetchBlock*>::iterator block_it = findBlock(pendingFetch,
- asid,
- block_addr);
- if (block_it != pendingFetch.end()) {
- (*block_it)->cnt--;
- DPRINTF(InOrderCachePort, "[sn:%i] Removing Pending Access "
- "for Pending Buffer Block %08p (cnt=%i)\n",
- inst->seqNum,
- block_addr, (*block_it)->cnt);
- assert((*block_it)->cnt >= 0);
- if ((*block_it)->cnt == 0) {
- if ((*block_it)->block) {
- delete [] (*block_it)->block;
- }
- delete *block_it;
- pendingFetch.erase(block_it);
- }
- }
- }
-
- CacheUnit::squashCacheRequest(req_ptr);
-}
-
-void
-FetchUnit::trap(const Fault &fault, ThreadID tid, DynInstPtr inst)
-{
- //@todo: per thread?
- decoder[tid]->reset();
-
- //@todo: squash using dummy inst seq num
- squash(NULL, NumStages - 1, 0, tid);
-
- //@todo: make sure no blocks are in use
- assert(blocksInUse() == 0);
- assert(pendingFetch.size() == 0);
-
- //@todo: clear pendingFetch and fetchBuffer
- clearFetchBuffer();
-}