📄 memunit.cc
字号:
/* * Copyright (c) 2002 The Board of Trustees of the University of Illinois and * William Marsh Rice University * Copyright (c) 2002 The University of Utah * Copyright (c) 2002 The University of Notre Dame du Lac * * All rights reserved. * * Based on RSIM 1.0, developed by: * Professor Sarita Adve's RSIM research group * University of Illinois at Urbana-Champaign and William Marsh Rice University * http://www.cs.uiuc.edu/rsim and http://www.ece.rice.edu/~rsim/dist.html * ML-RSIM/URSIM extensions by: * The Impulse Research Group, University of Utah * http://www.cs.utah.edu/impulse * Lambert Schaelicke, University of Utah and University of Notre Dame du Lac * http://www.cse.nd.edu/~lambert * Mike Parker, University of Utah * http://www.cs.utah.edu/~map * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal with the Software without restriction, including without * limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, subject to the following * conditions: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimers. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimers in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of Professor Sarita Adve's RSIM research group, * the University of Illinois at Urbana-Champaign, William Marsh Rice * University, nor the names of its contributors may be used to endorse * or promote products derived from this Software without specific prior * written permission. * 4. Neither the names of the ML-RSIM project, the URSIM project, the * Impulse research group, the University of Utah, the University of * Notre Dame du Lac, nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS WITH THE SOFTWARE. */#include <sys/time.h>#include <limits.h>extern "C"{#include "sim_main/simsys.h"#include "Caches/system.h"#include "Caches/ubuf.h"} #include "Processor/procstate.h"#include "Processor/exec.h"#include "Processor/memunit.h"#include "Processor/memq.h"#include "Processor/mainsim.h"#include "Processor/branchpred.h"#include "Processor/simio.h"#include "Processor/fastnews.h"#include "Processor/memunit.hh"#include "Processor/tagcvt.hh"#include "Processor/stallq.hh"#include "Processor/active.hh"#include "Processor/procstate.hh"#ifdef sgi#define LLONG_MAX LONGLONG_MAX#endif#if !defined(LLONG_MAX)# define LLONG_MAX 9223372036854775807LL#endifstatic int MemMatch (instance * ld, instance * st);static void IssueOp (instance * memop, ProcState * proc);static void IssueOpMessage (ProcState *proc, instance *memop);int INSTANT_ADDRESS_GENERATE = 0;/* * Overlap: returns 1 if there is overlap between addresse * : accessed by references a and b. */#define overlap(a,b) ((a->finish_addr >= b->finish_addr && \ b->finish_addr >= a->addr) || \ (b->finish_addr >= a->finish_addr && \ a->finish_addr >= b->addr))/* * What inst->memprogress means * 2 flushed * 1 completed * 0 unissued * -1 issued * -3 to -inf forwarded *//*#######################################################################*/#ifdef STORE_ORDERING/**************************************************************************//* IssueMem : Get elements from memory queue and check for dependences, *//* : resource availability and issue it *//**************************************************************************/int IssueMem(ProcState * proc){ instance *memop; MemQLink<instance *> *index, *confindex; int ctr = 0, readctr = 0; proc->prefs = 0; // zero prefetches so far this cycle index = proc->MemQueue.GetNext(NULL); do { ctr++; memop = index->d; if ((IsLoad(memop) || IsRMW(memop)) && (memop->code.instruction != iPREFETCH)) readctr++; if (memop->memprogress) { // already issued or dead if (!Speculative_Loads) break; else continue; } /* address has to be ready before going to memory unit */ if (!memop->addr_ready || memop->truedep) continue; if (IsStore(memop)) { /* treat stores a certain way -- need to be at head of active list. make sure that not only is st_ready set, but also store should be at top of memory unit. */ if (memop->mem_ready && ctr == 1) { if (L1Q_FULL[proc->proc_id]) break; else { if (simulate_ilp && Processor_Consistency) proc->ReadyUnissuedStores--; IssueOp(memop, proc); if (CanPrefetch(proc, memop)) proc->prefrdy[proc->prefs++] = memop; } } if (!Speculative_Loads) break; } else { // this is where we handle loads if (memop->code.instruction == iPREFETCH) { /* software prefetch */ if (L1Q_FULL[proc->proc_id]) break; else { // do this because we're going to be removing this entry // in the MemQueue in the IssueOp() function. */ index = proc->MemQueue.GetPrev(index); ctr--; IssueOp(memop, proc); continue; } } if (!(Speculative_Loads || (Processor_Consistency && readctr == 1))) { if (ctr == 1) { if (L1Q_FULL[proc->proc_id]) break; else { IssueOp(memop, proc); if (CanPrefetch(proc, memop)) proc->prefrdy[proc->prefs++] = memop; } } else break; } else { // in this case, we do have speculative load execution or this is // processor consistency but there are only writes ahead of us. int canissue = 1; int specing = 0; unsigned instaddr; unsigned confaddr; instance *conf; confindex = NULL; confindex = index; while (confindex = proc->MemQueue.GetPrev(confindex)) { conf = confindex->d; if (IsLoad(conf)) continue; if (conf->addrdep || !conf->addr_ready) { specing = 1; continue; } /* either stall or have a chance for a quick forwarding */ if (overlap(conf, memop)) { confaddr = conf->addr; instaddr = memop->addr; if (confaddr == instaddr && conf->truedep == 0 && MemMatch(memop, conf)) { // varies from -3 on down! memop->memprogress = -3 - conf->tag; canissue = 1; } else if (conf->code.instruction == iSTDF && memop->code.instruction == iLDUW && conf->truedep == 0 && ((instaddr == confaddr) || (instaddr == confaddr + sizeof(int)))) { /* here's a case where we can forward just like the regular case, even if it's a partial overlap. */ if (instaddr == confaddr) { unsigned *p = (unsigned*)&(conf->rs1valf); memop->rdvali = *p; } else // (instaddr == confaddr + sizeof(int)) { unsigned int *p = (unsigned*)&(conf->rs1valf); memop->rdvali = *(p + 1); } memop->memprogress = -3 - conf->tag; canissue = 1; // we can definitely use it } else { // we would be expecting a partial forward at the cache memop->partial_overlap = 1; memop->memprogress = 0; canissue = 0; } break; } } if (canissue && memop->memprogress > -3) { if (L1Q_FULL[proc->proc_id]) { memop->memprogress = 0; canissue = 0; break; } } if (canissue) { proc->ldissues++; if (specing) proc->ldspecs++; if (memop->memprogress < 0) { // we got a quick forward memop->issuetime = proc->curr_cycle; proc->MemDoneHeap.insert(proc->curr_cycle + 1, memop, memop->tag); } else { IssueOp(memop, proc); if (CanPrefetch(proc, memop)) proc->prefrdy[proc->prefs++] = memop; } } } } /* load */ } while ((index = proc->MemQueue.GetNext(index)) && proc->UnitsFree[uMEM]); if (Prefetch) StartPrefetch(proc); return 0;}#endif /* StoreOrdering ##################################################*//* * Check for match between load and store and also forward values where * possible. Returns 1 on success, 0 on failure call this function after * matching load and store's address. */static int MemMatch(instance * ld, instance * st) { INSTRUCTION load = ld->code.instruction; INSTRUCTION store = st->code.instruction; switch (store) { case iSTW: if ((load == iLDUW) || (load == iLDSW) || (load == iLDUWA)) { if (load == iLDSW) ld->rdvali = (int)st->rs1vali; else ld->rdvali = (unsigned)st->rs1vali; return 1; } else if (load == iLDF) { int *addr = (int *) &(st->rs1vali); *((int*)&(ld->rdvalfh)) = *addr; return 1; } return 0; case iSTD: if (load == iLDD) { ld->rdvalipair.a = st->rs1valipair.a; ld->rdvalipair.b = st->rs1valipair.b; return 1; } else return 0; case iSTB: if ((load == iLDUB) || (load == iLDSB)) { if (load == iLDSB) ld->rdvali=(char)st->rs1vali; else ld->rdvali=(unsigned char)st->rs1vali; return 1; } else return 0; case iLDSTUB: if (load == iLDUB) { ld->rdvali = 255; return 1; } else return 0; case iSTH: if ((load == iLDUH) || (load == iLDSH)) { if (load == iLDSH) ld->rdvali=(short)st->rs1vali; else ld->rdvali=(unsigned short)st->rs1vali; return 1; } else return 0; case iSTDF: if (load == iLDDF) { ld->rdvalf = st->rs1valf; return 1; } else return 0; case iSTF: if (load == iLDF) { ld->rdvalfh = st->rs1valfh; return 1; } else if (load == iLDSW || load == iLDUW) { int *p = (int*)&(st->rs1valfh); if (load == iLDSW) ld->rdvali = *p; else ld->rdvali = (unsigned int)*p; return 1; } else return 0; default: break; } return 0;}/*************************************************************************//* IssueOp : Issue a memory operation to the cache or the perfect memory *//* : system *//*************************************************************************/static void IssueOp(instance * memop, ProcState * proc){ if (memop->vsbfwd < 0) proc->vsbfwds++; proc->UnitsFree[uMEM]--; memop->memprogress = -1; memop->issuetime = proc->curr_cycle; memop->time_issued = YS__Simtime;#ifdef COREFILE IssueOpMessage(proc, memop);#endif memory_latency(memop, proc);}struct MemoryRequestState{ instance *inst; ProcState*proc; MemoryRequestState(instance * i, ProcState * p):inst(i), proc(p) {}};/*************************************************************************//* memory_latency : models the effect of latency spent on memory issue *//* : use StartUpMemReference to interface with MemSys *//*************************************************************************/ int memory_latency(instance * inst, ProcState * proc){ /* just to see if we should execute it at all -- or does it give a seg fault */ if (inst->exception_code == ITLB_MISS || inst->exception_code == DTLB_MISS || inst->exception_code == INSTR_FAULT || inst->exception_code == DATA_FAULT || inst->exception_code == BUSERR || inst->exception_code == PRIVILEGED || (!simulate_ilp && IsStore(inst) && inst->exception_code != OK)) { // the last condition takes care of places that mark_stores_ready would // have handled for an ILP processor proc->FreeingUnits.insert(proc->curr_cycle, uMEM);#ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile, "Freeing memunit for tag %lld\n", inst->tag);#endif#ifndef STORE_ORDERING
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -