From 0ccf9a2c3751f160d7d51153ef468a60b4daf8d0 Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Tue, 5 Feb 2008 23:44:13 -0500 Subject: Add base ARM code to M5 --HG-- extra : convert_revision : d811bf87d1a0bfc712942ecd3db1b48fc75257af --- .hgignore | 1 + src/arch/isa_specific.hh | 3 +++ src/base/loader/elf_object.cc | 3 +++ src/base/loader/object_file.hh | 3 ++- src/cpu/BaseCPU.py | 9 ++++++++- src/cpu/o3/dyn_inst.hh | 4 ++++ src/cpu/simple/timing.cc | 14 ++++++++++---- src/cpu/static_inst.hh | 1 + src/sim/process.cc | 13 +++++++++++++ 9 files changed, 45 insertions(+), 6 deletions(-) diff --git a/.hgignore b/.hgignore index f536836de..f6a91e6e3 100644 --- a/.hgignore +++ b/.hgignore @@ -6,3 +6,4 @@ cscope.files cscope.out *.pyc *~ +.*.swp diff --git a/src/arch/isa_specific.hh b/src/arch/isa_specific.hh index c241e5c62..c10ce7350 100644 --- a/src/arch/isa_specific.hh +++ b/src/arch/isa_specific.hh @@ -49,6 +49,7 @@ #define SPARC_ISA 42 #define MIPS_ISA 34000 #define X86_ISA 8086 +#define ARM_ISA 6 //These tell the preprocessor where to find the files of a particular //ISA, and set the "TheISA" macro for use elsewhere. @@ -60,6 +61,8 @@ #define TheISA MipsISA #elif THE_ISA == X86_ISA #define TheISA X86ISA +#elif THE_ISA == ARM_ISA + #define TheISA ArmISA #else #error "THE_ISA not set" #endif diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index 23df1c5ba..8e41ffd16 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -88,6 +88,8 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) arch = ObjectFile::X86; } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { arch = ObjectFile::Alpha; + } else if (ehdr.e_machine == EM_ARM) { + arch = ObjectFile::Arm; } else { warn("Unknown architecture: %d\n", ehdr.e_machine); arch = ObjectFile::UnknownArch; @@ -98,6 +100,7 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data) { case ELFOSABI_LINUX: + case ELFOSABI_ARM: opSys = ObjectFile::Linux; break; case ELFOSABI_SOLARIS: diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh index 4f0c17cc8..7f2bef0bf 100644 --- a/src/base/loader/object_file.hh +++ b/src/base/loader/object_file.hh @@ -50,7 +50,8 @@ class ObjectFile SPARC64, SPARC32, Mips, - X86 + X86, + Arm }; enum OpSys { diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index ee5ed0774..c2a865113 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -1,4 +1,4 @@ -# Copyright (c) 2005-2007 The Regents of The University of Michigan +# Copyright (c) 2005-2008 The Regents of The University of Michigan # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -45,6 +45,8 @@ elif build_env['TARGET_ISA'] == 'x86': from X86TLB import X86DTB, X86ITB elif build_env['TARGET_ISA'] == 'mips': from MipsTLB import MipsTLB,MipsDTB, MipsITB, MipsUTB +elif build_env['TARGET_ISA'] == 'arm': + from ArmTLB import ArmTLB, ArmDTB, ArmITB, ArmUTB class BaseCPU(SimObject): type = 'BaseCPU' @@ -76,6 +78,11 @@ class BaseCPU(SimObject): dtb = Param.MipsDTB(MipsDTB(), "Data TLB") itb = Param.MipsITB(MipsITB(), "Instruction TLB") tlb = Param.MipsUTB(MipsUTB(), "Unified TLB") + elif build_env['TARGET_ISA'] == 'arm': + UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?") + dtb = Param.ArmDTB(ArmDTB(), "Data TLB") + itb = Param.ArmITB(ArmITB(), "Instruction TLB") + tlb = Param.ArmUTB(ArmUTB(), "Unified TLB") else: print "Don't know what TLB to use for ISA %s" % \ build_env['TARGET_ISA'] diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index c37f8007e..a1f9e0591 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -49,6 +49,10 @@ template class X86DynInst; struct X86SimpleImpl; typedef X86DynInst O3DynInst; +#elif THE_ISA == ARM_ISA + template class ArmDynInst; + struct ArmSimpleImpl; + typedef ArmDynInst O3DynInst; #else #error "O3DynInst not defined for this ISA" #endif diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index fc35f2666..e1fc6882f 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -598,13 +598,19 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt) assert(fault == NoFault); } else { if (fault == NoFault) { + // Note that ARM can have NULL packets if the instruction gets + // squashed due to predication // early fail on store conditional: complete now - assert(dcache_pkt != NULL); + assert(dcache_pkt != NULL || THE_ISA == ARM_ISA); + fault = curStaticInst->completeAcc(dcache_pkt, this, traceData); - delete dcache_pkt->req; - delete dcache_pkt; - dcache_pkt = NULL; + if (dcache_pkt != NULL) + { + delete dcache_pkt->req; + delete dcache_pkt; + dcache_pkt = NULL; + } // keep an instruction count if (fault == NoFault) diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index d2232bab7..ceda78d90 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -259,6 +259,7 @@ class StaticInstBase : public RefCounted bool isMicroBranch() const { return flags[IsMicroBranch]; } //@} + void setLastMicroop() { flags[IsLastMicroop] = true; } /// Operation class. Used to select appropriate function unit in issue. OpClass opClass() const { return _opClass; } }; diff --git a/src/sim/process.cc b/src/sim/process.cc index d83b0247e..16037b2f4 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -61,6 +61,8 @@ #include "arch/sparc/solaris/process.hh" #elif THE_ISA == MIPS_ISA #include "arch/mips/linux/process.hh" +#elif THE_ISA == ARM_ISA +#include "arch/arm/linux/process.hh" #elif THE_ISA == X86_ISA #include "arch/x86/linux/process.hh" #else @@ -697,6 +699,17 @@ LiveProcess::create(LiveProcessParams * params) process = new MipsLinuxProcess(params, objFile); break; + default: + fatal("Unknown/unsupported operating system."); + } +#elif THE_ISA == ARM_ISA + if (objFile->getArch() != ObjectFile::Arm) + fatal("Object file architecture does not match compiled ISA (ARM)."); + switch (objFile->getOpSys()) { + case ObjectFile::Linux: + process = new ArmLinuxProcess(params, objFile); + break; + default: fatal("Unknown/unsupported operating system."); } -- cgit v1.2.3 From 6cc1573923754ecb406d03ab4d807f928737c294 Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Wed, 6 Feb 2008 16:32:40 -0500 Subject: Make the Event::description() a const function --HG-- extra : convert_revision : c7768d54d3f78685e93920069f5485083ca989c0 --- src/arch/mips/regfile/misc_regfile.cc | 2 +- src/arch/mips/regfile/misc_regfile.hh | 2 +- src/cpu/base.cc | 2 +- src/cpu/base.hh | 2 +- src/cpu/memtest/memtest.hh | 2 +- src/cpu/o3/commit.hh | 2 +- src/cpu/o3/commit_impl.hh | 2 +- src/cpu/o3/cpu.cc | 6 +++--- src/cpu/o3/cpu.hh | 6 +++--- src/cpu/o3/inst_queue.hh | 2 +- src/cpu/o3/inst_queue_impl.hh | 2 +- src/cpu/o3/lsq_unit.hh | 2 +- src/cpu/o3/lsq_unit_impl.hh | 2 +- src/cpu/ozone/back_end.hh | 4 ++-- src/cpu/ozone/back_end_impl.hh | 4 ++-- src/cpu/ozone/cpu.hh | 2 +- src/cpu/ozone/cpu_impl.hh | 2 +- src/cpu/ozone/inorder_back_end.hh | 2 +- src/cpu/ozone/inorder_back_end_impl.hh | 2 +- src/cpu/ozone/inst_queue.hh | 2 +- src/cpu/ozone/inst_queue_impl.hh | 2 +- src/cpu/ozone/lsq_unit.hh | 2 +- src/cpu/ozone/lsq_unit_impl.hh | 2 +- src/cpu/ozone/lw_back_end.hh | 2 +- src/cpu/ozone/lw_back_end_impl.hh | 2 +- src/cpu/ozone/lw_lsq.hh | 2 +- src/cpu/ozone/lw_lsq_impl.hh | 2 +- src/cpu/quiesce_event.cc | 2 +- src/cpu/quiesce_event.hh | 2 +- src/cpu/simple/atomic.cc | 2 +- src/cpu/simple/atomic.hh | 2 +- src/cpu/simple/timing.cc | 2 +- src/cpu/simple/timing.hh | 8 ++++---- src/cpu/trace/opt_cpu.cc | 2 +- src/cpu/trace/opt_cpu.hh | 2 +- src/cpu/trace/trace_cpu.cc | 4 ++-- src/cpu/trace/trace_cpu.hh | 4 ++-- src/dev/alpha/tsunami_io.cc | 4 ++-- src/dev/alpha/tsunami_io.hh | 4 ++-- src/dev/etherbus.hh | 3 ++- src/dev/ethertap.hh | 3 ++- src/dev/mips/malta_io.cc | 4 ++-- src/dev/mips/malta_io.hh | 4 ++-- src/dev/uart8250.cc | 2 +- src/dev/uart8250.hh | 2 +- src/mem/bridge.hh | 2 +- src/mem/bus.cc | 2 +- src/mem/bus.hh | 2 +- src/sim/debug.cc | 4 ++-- src/sim/eventq.cc | 2 +- src/sim/eventq.hh | 4 ++-- src/sim/sim_events.cc | 6 +++--- src/sim/sim_events.hh | 6 +++--- 53 files changed, 76 insertions(+), 74 deletions(-) diff --git a/src/arch/mips/regfile/misc_regfile.cc b/src/arch/mips/regfile/misc_regfile.cc index 5e4c803fc..dc6ae0baf 100755 --- a/src/arch/mips/regfile/misc_regfile.cc +++ b/src/arch/mips/regfile/misc_regfile.cc @@ -577,7 +577,7 @@ MiscRegFile::CP0Event::process() } const char * -MiscRegFile::CP0Event::description() +MiscRegFile::CP0Event::description() const { return "Coprocessor-0 event"; } diff --git a/src/arch/mips/regfile/misc_regfile.hh b/src/arch/mips/regfile/misc_regfile.hh index a6f1a15c6..5f19579b3 100644 --- a/src/arch/mips/regfile/misc_regfile.hh +++ b/src/arch/mips/regfile/misc_regfile.hh @@ -139,7 +139,7 @@ namespace MipsISA virtual void process(); /** Returns the description of this event. */ - const char *description(); + const char *description() const; /** Schedule This Event */ void scheduleEvent(int delay); diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 677152ce8..23195f720 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -88,7 +88,7 @@ CPUProgressEvent::process() } const char * -CPUProgressEvent::description() +CPUProgressEvent::description() const { return "CPU Progress"; } diff --git a/src/cpu/base.hh b/src/cpu/base.hh index e0d2340e9..bdc7d7c8b 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -68,7 +68,7 @@ class CPUProgressEvent : public Event void process(); - virtual const char *description(); + virtual const char *description() const; }; class BaseCPU : public MemObject diff --git a/src/cpu/memtest/memtest.hh b/src/cpu/memtest/memtest.hh index 1a330319f..ac2d0a058 100644 --- a/src/cpu/memtest/memtest.hh +++ b/src/cpu/memtest/memtest.hh @@ -77,7 +77,7 @@ class MemTest : public MemObject TickEvent(MemTest *c) : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c) {} void process() {cpu->tick();} - virtual const char *description() { return "MemTest tick"; } + virtual const char *description() const { return "MemTest tick"; } }; TickEvent tickEvent; diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index 27bdd20c5..80e42fa8b 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -97,7 +97,7 @@ class DefaultCommit TrapEvent(DefaultCommit *_commit, unsigned _tid); void process(); - const char *description(); + const char *description() const; }; /** Overall commit status. Used to determine if the CPU can deschedule diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 89df257e9..ee0f2bb59 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -65,7 +65,7 @@ DefaultCommit::TrapEvent::process() template const char * -DefaultCommit::TrapEvent::description() +DefaultCommit::TrapEvent::description() const { return "Trap"; } diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 5908062aa..8eb17d23b 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -80,7 +80,7 @@ FullO3CPU::TickEvent::process() template const char * -FullO3CPU::TickEvent::description() +FullO3CPU::TickEvent::description() const { return "FullO3CPU tick"; } @@ -109,7 +109,7 @@ FullO3CPU::ActivateThreadEvent::process() template const char * -FullO3CPU::ActivateThreadEvent::description() +FullO3CPU::ActivateThreadEvent::description() const { return "FullO3CPU \"Activate Thread\""; } @@ -141,7 +141,7 @@ FullO3CPU::DeallocateContextEvent::process() template const char * -FullO3CPU::DeallocateContextEvent::description() +FullO3CPU::DeallocateContextEvent::description() const { return "FullO3CPU \"Deallocate Context\""; } diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 162e377e1..e902968c1 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -136,7 +136,7 @@ class FullO3CPU : public BaseO3CPU /** Processes a tick event, calling tick() on the CPU. */ void process(); /** Returns the description of the tick event. */ - const char *description(); + const char *description() const; }; /** The tick event used for scheduling CPU ticks. */ @@ -178,7 +178,7 @@ class FullO3CPU : public BaseO3CPU void process(); /** Returns the description of the event. */ - const char *description(); + const char *description() const; }; /** Schedule thread to activate , regardless of its current state. */ @@ -229,7 +229,7 @@ class FullO3CPU : public BaseO3CPU void setRemove(bool _remove) { remove = _remove; } /** Returns the description of the event. */ - const char *description(); + const char *description() const; }; /** Schedule cpu to deallocate thread context.*/ diff --git a/src/cpu/o3/inst_queue.hh b/src/cpu/o3/inst_queue.hh index 9d7c457ca..d0f503977 100644 --- a/src/cpu/o3/inst_queue.hh +++ b/src/cpu/o3/inst_queue.hh @@ -105,7 +105,7 @@ class InstructionQueue InstructionQueue *iq_ptr); virtual void process(); - virtual const char *description(); + virtual const char *description() const; void setFreeFU() { freeFU = true; } }; diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index b14a63a17..fb06f20df 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -58,7 +58,7 @@ InstructionQueue::FUCompletion::process() template const char * -InstructionQueue::FUCompletion::description() +InstructionQueue::FUCompletion::description() const { return "Functional unit completion"; } diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh index be9224099..128a71dbc 100644 --- a/src/cpu/o3/lsq_unit.hh +++ b/src/cpu/o3/lsq_unit.hh @@ -273,7 +273,7 @@ class LSQUnit { void process(); /** Returns the description of this event. */ - const char *description(); + const char *description() const; private: /** Instruction whose results are being written back. */ diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index 71b416c9c..e6ff5e931 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -67,7 +67,7 @@ LSQUnit::WritebackEvent::process() template const char * -LSQUnit::WritebackEvent::description() +LSQUnit::WritebackEvent::description() const { return "Store writeback"; } diff --git a/src/cpu/ozone/back_end.hh b/src/cpu/ozone/back_end.hh index 992f55c6e..4cdc86c3c 100644 --- a/src/cpu/ozone/back_end.hh +++ b/src/cpu/ozone/back_end.hh @@ -186,7 +186,7 @@ class BackEnd /** Processes writeback event. */ virtual void process(); /** Returns the description of the writeback event. */ - virtual const char *description(); + virtual const char *description() const; }; BackEnd(Params *params); @@ -309,7 +309,7 @@ class BackEnd DCacheCompletionEvent(BackEnd *_be); virtual void process(); - virtual const char *description(); + virtual const char *description() const; }; friend class DCacheCompletionEvent; diff --git a/src/cpu/ozone/back_end_impl.hh b/src/cpu/ozone/back_end_impl.hh index 27146ecf0..415407c52 100644 --- a/src/cpu/ozone/back_end_impl.hh +++ b/src/cpu/ozone/back_end_impl.hh @@ -581,7 +581,7 @@ BackEnd::LdWritebackEvent::process() template const char * -BackEnd::LdWritebackEvent::description() +BackEnd::LdWritebackEvent::description() const { return "Load writeback"; } @@ -601,7 +601,7 @@ BackEnd::DCacheCompletionEvent::process() template const char * -BackEnd::DCacheCompletionEvent::description() +BackEnd::DCacheCompletionEvent::description() const { return "Cache completion"; } diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 036db1351..61abae807 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -306,7 +306,7 @@ class OzoneCPU : public BaseCPU TickEvent(OzoneCPU *c, int w); void process(); - const char *description(); + const char *description() const; }; TickEvent tickEvent; diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index 5080c54f6..0c7105382 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -82,7 +82,7 @@ OzoneCPU::TickEvent::process() template const char * -OzoneCPU::TickEvent::description() +OzoneCPU::TickEvent::description() const { return "OzoneCPU tick"; } diff --git a/src/cpu/ozone/inorder_back_end.hh b/src/cpu/ozone/inorder_back_end.hh index 4fd8e02f8..aef29b1e2 100644 --- a/src/cpu/ozone/inorder_back_end.hh +++ b/src/cpu/ozone/inorder_back_end.hh @@ -161,7 +161,7 @@ class InorderBackEnd DCacheCompletionEvent(InorderBackEnd *_be); virtual void process(); - virtual const char *description(); + virtual const char *description() const; DynInstPtr inst; }; diff --git a/src/cpu/ozone/inorder_back_end_impl.hh b/src/cpu/ozone/inorder_back_end_impl.hh index c57fa0200..cf8634a42 100644 --- a/src/cpu/ozone/inorder_back_end_impl.hh +++ b/src/cpu/ozone/inorder_back_end_impl.hh @@ -538,7 +538,7 @@ InorderBackEnd::DCacheCompletionEvent::process() template const char * -InorderBackEnd::DCacheCompletionEvent::description() +InorderBackEnd::DCacheCompletionEvent::description() const { return "DCache completion"; } diff --git a/src/cpu/ozone/inst_queue.hh b/src/cpu/ozone/inst_queue.hh index 0158fd2d2..a11d5204b 100644 --- a/src/cpu/ozone/inst_queue.hh +++ b/src/cpu/ozone/inst_queue.hh @@ -99,7 +99,7 @@ class InstQueue InstQueue *iq_ptr); virtual void process(); - virtual const char *description(); + virtual const char *description() const; }; #endif /** Constructs an IQ. */ diff --git a/src/cpu/ozone/inst_queue_impl.hh b/src/cpu/ozone/inst_queue_impl.hh index 461c7eb0f..3c3084757 100644 --- a/src/cpu/ozone/inst_queue_impl.hh +++ b/src/cpu/ozone/inst_queue_impl.hh @@ -62,7 +62,7 @@ InstQueue::FUCompletion::process() template const char * -InstQueue::FUCompletion::description() +InstQueue::FUCompletion::description() const { return "Functional unit completion"; } diff --git a/src/cpu/ozone/lsq_unit.hh b/src/cpu/ozone/lsq_unit.hh index 056c79521..981682c26 100644 --- a/src/cpu/ozone/lsq_unit.hh +++ b/src/cpu/ozone/lsq_unit.hh @@ -80,7 +80,7 @@ class OzoneLSQ { void process(); /** Returns the description of this event. */ - const char *description(); + const char *description() const; private: /** The store index of the store being written back. */ diff --git a/src/cpu/ozone/lsq_unit_impl.hh b/src/cpu/ozone/lsq_unit_impl.hh index e08e54835..84a90eede 100644 --- a/src/cpu/ozone/lsq_unit_impl.hh +++ b/src/cpu/ozone/lsq_unit_impl.hh @@ -60,7 +60,7 @@ OzoneLSQ::StoreCompletionEvent::process() template const char * -OzoneLSQ::StoreCompletionEvent::description() +OzoneLSQ::StoreCompletionEvent::description() const { return "LSQ store completion"; } diff --git a/src/cpu/ozone/lw_back_end.hh b/src/cpu/ozone/lw_back_end.hh index 08a6863d0..a335ab7dc 100644 --- a/src/cpu/ozone/lw_back_end.hh +++ b/src/cpu/ozone/lw_back_end.hh @@ -94,7 +94,7 @@ class LWBackEnd TrapEvent(LWBackEnd *_be); void process(); - const char *description(); + const char *description() const; }; LWBackEnd(Params *params); diff --git a/src/cpu/ozone/lw_back_end_impl.hh b/src/cpu/ozone/lw_back_end_impl.hh index 42788cee1..a5d79a789 100644 --- a/src/cpu/ozone/lw_back_end_impl.hh +++ b/src/cpu/ozone/lw_back_end_impl.hh @@ -119,7 +119,7 @@ LWBackEnd::TrapEvent::process() template const char * -LWBackEnd::TrapEvent::description() +LWBackEnd::TrapEvent::description() const { return "Trap"; } diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh index ba40e9ce1..7fc8b6307 100644 --- a/src/cpu/ozone/lw_lsq.hh +++ b/src/cpu/ozone/lw_lsq.hh @@ -329,7 +329,7 @@ class OzoneLWLSQ { void process(); /** Returns the description of this event. */ - const char *description(); + const char *description() const; private: /** Instruction whose results are being written back. */ diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh index 82191312a..00e52e039 100644 --- a/src/cpu/ozone/lw_lsq_impl.hh +++ b/src/cpu/ozone/lw_lsq_impl.hh @@ -55,7 +55,7 @@ OzoneLWLSQ::WritebackEvent::process() template const char * -OzoneLWLSQ::WritebackEvent::description() +OzoneLWLSQ::WritebackEvent::description() const { return "Store writeback"; } diff --git a/src/cpu/quiesce_event.cc b/src/cpu/quiesce_event.cc index 3495a0e52..81384d529 100644 --- a/src/cpu/quiesce_event.cc +++ b/src/cpu/quiesce_event.cc @@ -45,7 +45,7 @@ EndQuiesceEvent::process() } const char* -EndQuiesceEvent::description() +EndQuiesceEvent::description() const { return "End Quiesce"; } diff --git a/src/cpu/quiesce_event.hh b/src/cpu/quiesce_event.hh index 3de40f97e..85c88ab32 100644 --- a/src/cpu/quiesce_event.hh +++ b/src/cpu/quiesce_event.hh @@ -47,7 +47,7 @@ struct EndQuiesceEvent : public Event virtual void process(); /** Event description */ - virtual const char *description(); + virtual const char *description() const; }; #endif // __CPU_QUIESCE_EVENT_HH__ diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index aa548b46f..2254d44d5 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -55,7 +55,7 @@ AtomicSimpleCPU::TickEvent::process() } const char * -AtomicSimpleCPU::TickEvent::description() +AtomicSimpleCPU::TickEvent::description() const { return "AtomicSimpleCPU tick"; } diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index f14dd6f99..19bc0e13b 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -68,7 +68,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU TickEvent(AtomicSimpleCPU *c); void process(); - const char *description(); + const char *description() const; }; TickEvent tickEvent; diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index e1fc6882f..9fe3d2fff 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -822,7 +822,7 @@ TimingSimpleCPU::IprEvent::process() } const char * -TimingSimpleCPU::IprEvent::description() +TimingSimpleCPU::IprEvent::description() const { return "Timing Simple CPU Delay IPR event"; } diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index 79fbe0f5f..f8b77604a 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -101,7 +101,7 @@ class TimingSimpleCPU : public BaseSimpleCPU TickEvent(TimingSimpleCPU *_cpu) :Event(&mainEventQueue), cpu(_cpu) {} - const char *description() { return "Timing CPU tick"; } + const char *description() const { return "Timing CPU tick"; } void schedule(PacketPtr _pkt, Tick t); }; @@ -127,7 +127,7 @@ class TimingSimpleCPU : public BaseSimpleCPU ITickEvent(TimingSimpleCPU *_cpu) : TickEvent(_cpu) {} void process(); - const char *description() { return "Timing CPU icache tick"; } + const char *description() const { return "Timing CPU icache tick"; } }; ITickEvent tickEvent; @@ -155,7 +155,7 @@ class TimingSimpleCPU : public BaseSimpleCPU DTickEvent(TimingSimpleCPU *_cpu) : TickEvent(_cpu) {} void process(); - const char *description() { return "Timing CPU dcache tick"; } + const char *description() const { return "Timing CPU dcache tick"; } }; DTickEvent tickEvent; @@ -219,7 +219,7 @@ class TimingSimpleCPU : public BaseSimpleCPU TimingSimpleCPU *cpu; IprEvent(Packet *_pkt, TimingSimpleCPU *_cpu, Tick t); virtual void process(); - virtual const char *description(); + virtual const char *description() const; }; void completeDrain(); diff --git a/src/cpu/trace/opt_cpu.cc b/src/cpu/trace/opt_cpu.cc index 33da3d870..10e71db7b 100644 --- a/src/cpu/trace/opt_cpu.cc +++ b/src/cpu/trace/opt_cpu.cc @@ -204,7 +204,7 @@ OptCPU::TickEvent::process() } const char * -OptCPU::TickEvent::description() +OptCPU::TickEvent::description() const { return "OptCPU tick"; } diff --git a/src/cpu/trace/opt_cpu.hh b/src/cpu/trace/opt_cpu.hh index dfb122319..9d98eebc6 100644 --- a/src/cpu/trace/opt_cpu.hh +++ b/src/cpu/trace/opt_cpu.hh @@ -81,7 +81,7 @@ class OptCPU : public SimObject /** * Return a string description of this event. */ - const char *description(); + const char *description() const; }; TickEvent tickEvent; diff --git a/src/cpu/trace/trace_cpu.cc b/src/cpu/trace/trace_cpu.cc index d3cf34e9d..ab00b3093 100644 --- a/src/cpu/trace/trace_cpu.cc +++ b/src/cpu/trace/trace_cpu.cc @@ -129,7 +129,7 @@ TraceCompleteEvent::process() } const char * -TraceCompleteEvent::description() +TraceCompleteEvent::description() const { return "trace access complete"; } @@ -146,7 +146,7 @@ TraceCPU::TickEvent::process() } const char * -TraceCPU::TickEvent::description() +TraceCPU::TickEvent::description() const { return "TraceCPU tick"; } diff --git a/src/cpu/trace/trace_cpu.hh b/src/cpu/trace/trace_cpu.hh index b88c7072e..a1ae4dc80 100644 --- a/src/cpu/trace/trace_cpu.hh +++ b/src/cpu/trace/trace_cpu.hh @@ -93,7 +93,7 @@ class TraceCPU : public SimObject /** * Return a string description of this event. */ - const char *description(); + const char *description() const; }; TickEvent tickEvent; @@ -135,7 +135,7 @@ class TraceCompleteEvent : public Event void process(); - virtual const char *description(); + virtual const char *description() const; }; #endif // __CPU_TRACE_TRACE_CPU_HH__ diff --git a/src/dev/alpha/tsunami_io.cc b/src/dev/alpha/tsunami_io.cc index e1ca1c84c..710aca48d 100644 --- a/src/dev/alpha/tsunami_io.cc +++ b/src/dev/alpha/tsunami_io.cc @@ -205,7 +205,7 @@ TsunamiIO::RTC::RTCEvent::process() } const char * -TsunamiIO::RTC::RTCEvent::description() +TsunamiIO::RTC::RTCEvent::description() const { return "tsunami RTC interrupt"; } @@ -429,7 +429,7 @@ TsunamiIO::PITimer::Counter::CounterEvent::process() } const char * -TsunamiIO::PITimer::Counter::CounterEvent::description() +TsunamiIO::PITimer::Counter::CounterEvent::description() const { return "tsunami 8254 Interval timer"; } diff --git a/src/dev/alpha/tsunami_io.hh b/src/dev/alpha/tsunami_io.hh index 5083604f8..05c4ee910 100644 --- a/src/dev/alpha/tsunami_io.hh +++ b/src/dev/alpha/tsunami_io.hh @@ -73,7 +73,7 @@ class TsunamiIO : public BasicPioDevice virtual void process(); /** Event description */ - virtual const char *description(); + virtual const char *description() const; }; private: @@ -161,7 +161,7 @@ class TsunamiIO : public BasicPioDevice virtual void process(); /** Event description */ - virtual const char *description(); + virtual const char *description() const; friend class Counter; }; diff --git a/src/dev/etherbus.hh b/src/dev/etherbus.hh index 4deb7fccc..624ceb81a 100644 --- a/src/dev/etherbus.hh +++ b/src/dev/etherbus.hh @@ -62,7 +62,8 @@ class EtherBus : public EtherObject DoneEvent(EventQueue *q, EtherBus *b) : Event(q), bus(b) {} virtual void process() { bus->txDone(); } - virtual const char *description() { return "ethernet bus completion"; } + virtual const char *description() const + { return "ethernet bus completion"; } }; DoneEvent event; diff --git a/src/dev/ethertap.hh b/src/dev/ethertap.hh index 5c24be460..be3d73a24 100644 --- a/src/dev/ethertap.hh +++ b/src/dev/ethertap.hh @@ -93,7 +93,8 @@ class EtherTap : public EtherObject TxEvent(EtherTap *_tap) : Event(&mainEventQueue), tap(_tap) {} void process() { tap->retransmit(); } - virtual const char *description() { return "EtherTap retransmit"; } + virtual const char *description() const + { return "EtherTap retransmit"; } }; friend class TxEvent; diff --git a/src/dev/mips/malta_io.cc b/src/dev/mips/malta_io.cc index bf7afa63b..b56694f1e 100755 --- a/src/dev/mips/malta_io.cc +++ b/src/dev/mips/malta_io.cc @@ -208,7 +208,7 @@ MaltaIO::RTC::RTCEvent::process() } const char * -MaltaIO::RTC::RTCEvent::description() +MaltaIO::RTC::RTCEvent::description() const { return "malta RTC interrupt"; } @@ -461,7 +461,7 @@ MaltaIO::PITimer::Counter::CounterEvent::process() } const char * -MaltaIO::PITimer::Counter::CounterEvent::description() +MaltaIO::PITimer::Counter::CounterEvent::description() const { return "malta 8254 Interval timer"; } diff --git a/src/dev/mips/malta_io.hh b/src/dev/mips/malta_io.hh index 791d49d60..e24a1d8cb 100755 --- a/src/dev/mips/malta_io.hh +++ b/src/dev/mips/malta_io.hh @@ -79,7 +79,7 @@ class MaltaIO : public BasicPioDevice virtual void process(); /** Event description */ - virtual const char *description(); + virtual const char *description() const; }; private: @@ -171,7 +171,7 @@ class MaltaIO : public BasicPioDevice virtual void process(); /** Event description */ - virtual const char *description(); + virtual const char *description() const; friend class Counter; }; diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc index e14b0871e..b4dc93645 100644 --- a/src/dev/uart8250.cc +++ b/src/dev/uart8250.cc @@ -55,7 +55,7 @@ Uart8250::IntrEvent::IntrEvent(Uart8250 *u, int bit) } const char * -Uart8250::IntrEvent::description() +Uart8250::IntrEvent::description() const { return "uart interrupt delay"; } diff --git a/src/dev/uart8250.hh b/src/dev/uart8250.hh index 32b16c17c..2c69667e1 100644 --- a/src/dev/uart8250.hh +++ b/src/dev/uart8250.hh @@ -82,7 +82,7 @@ class Uart8250 : public Uart public: IntrEvent(Uart8250 *u, int bit); virtual void process(); - virtual const char *description(); + virtual const char *description() const; void scheduleIntr(); }; diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index df48eb8c5..1331a45f9 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -150,7 +150,7 @@ class Bridge : public MemObject virtual void process() { port->trySend(); } - virtual const char *description() { return "bridge send"; } + virtual const char *description() const { return "bridge send"; } }; SendEvent sendEvent; diff --git a/src/mem/bus.cc b/src/mem/bus.cc index cfddfff12..66b20703f 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -105,7 +105,7 @@ void Bus::BusFreeEvent::process() bus->recvRetry(-1); } -const char * Bus::BusFreeEvent::description() +const char * Bus::BusFreeEvent::description() const { return "bus became available"; } diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 9ba43c79d..0c23175f1 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -131,7 +131,7 @@ class Bus : public MemObject public: BusFreeEvent(Bus * _bus); void process(); - const char *description(); + const char *description() const; }; /** a globally unique id for this bus. */ diff --git a/src/sim/debug.cc b/src/sim/debug.cc index c189117bd..b4f4cd9dc 100644 --- a/src/sim/debug.cc +++ b/src/sim/debug.cc @@ -63,7 +63,7 @@ class DebugBreakEvent : public Event DebugBreakEvent(EventQueue *q, Tick _when); void process(); // process event - virtual const char *description(); + virtual const char *description() const; }; // @@ -87,7 +87,7 @@ DebugBreakEvent::process() const char * -DebugBreakEvent::description() +DebugBreakEvent::description() const { return "debug break"; } diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index 65e115256..2c679be1e 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -230,7 +230,7 @@ dumpMainQueue() const char * -Event::description() +Event::description() const { return "generic"; } diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index 6fbba46d5..a454e5d64 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -219,7 +219,7 @@ class Event : public Serializable, public FastAlloc /// Return a C string describing the event. This string should /// *not* be dynamically allocated; just a const char array /// describing the event class. - virtual const char *description(); + virtual const char *description() const; /// Dump the current event data void dump(); @@ -280,7 +280,7 @@ DelayFunction(Tick when, T *object) : Event(&mainEventQueue), object(o) { setFlags(this->AutoDestroy); schedule(when); } void process() { (object->*F)(); } - const char *description() { return "delay"; } + const char *description() const { return "delay"; } }; new DelayEvent(when, object); diff --git a/src/sim/sim_events.cc b/src/sim/sim_events.cc index 1949e88dd..09087ef84 100644 --- a/src/sim/sim_events.cc +++ b/src/sim/sim_events.cc @@ -65,7 +65,7 @@ SimLoopExitEvent::process() const char * -SimLoopExitEvent::description() +SimLoopExitEvent::description() const { return "simulation loop exit"; } @@ -123,7 +123,7 @@ CountedExitEvent::process() const char * -CountedExitEvent::description() +CountedExitEvent::description() const { return "counted exit"; } @@ -153,7 +153,7 @@ CheckSwapEvent::process() } const char * -CheckSwapEvent::description() +CheckSwapEvent::description() const { return "check swap"; } diff --git a/src/sim/sim_events.hh b/src/sim/sim_events.hh index 94e2540b1..58ec963c0 100644 --- a/src/sim/sim_events.hh +++ b/src/sim/sim_events.hh @@ -68,7 +68,7 @@ class SimLoopExitEvent : public Event void process(); // process event - virtual const char *description(); + virtual const char *description() const; }; class CountedDrainEvent : public SimLoopExitEvent @@ -104,7 +104,7 @@ class CountedExitEvent : public Event void process(); // process event - virtual const char *description(); + virtual const char *description() const; }; // @@ -122,7 +122,7 @@ class CheckSwapEvent : public Event void process(); // process event - virtual const char *description(); + virtual const char *description() const; }; #endif // __SIM_SIM_EVENTS_HH__ -- cgit v1.2.3 From d56e77c180aeca0ff1ba271378424787345ec0b8 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sun, 10 Feb 2008 14:15:42 -0800 Subject: Rename cache files for brevity and consistency with rest of tree. --HG-- rename : src/mem/cache/base_cache.cc => src/mem/cache/base.cc rename : src/mem/cache/base_cache.hh => src/mem/cache/base.hh rename : src/mem/cache/cache_blk.cc => src/mem/cache/blk.cc rename : src/mem/cache/cache_blk.hh => src/mem/cache/blk.hh rename : src/mem/cache/cache_builder.cc => src/mem/cache/builder.cc rename : src/mem/cache/miss/mshr.cc => src/mem/cache/mshr.cc rename : src/mem/cache/miss/mshr.hh => src/mem/cache/mshr.hh rename : src/mem/cache/miss/mshr_queue.cc => src/mem/cache/mshr_queue.cc rename : src/mem/cache/miss/mshr_queue.hh => src/mem/cache/mshr_queue.hh rename : src/mem/cache/prefetch/base_prefetcher.cc => src/mem/cache/prefetch/base.cc rename : src/mem/cache/prefetch/base_prefetcher.hh => src/mem/cache/prefetch/base.hh rename : src/mem/cache/prefetch/ghb_prefetcher.cc => src/mem/cache/prefetch/ghb.cc rename : src/mem/cache/prefetch/ghb_prefetcher.hh => src/mem/cache/prefetch/ghb.hh rename : src/mem/cache/prefetch/stride_prefetcher.cc => src/mem/cache/prefetch/stride.cc rename : src/mem/cache/prefetch/stride_prefetcher.hh => src/mem/cache/prefetch/stride.hh rename : src/mem/cache/prefetch/tagged_prefetcher.cc => src/mem/cache/prefetch/tagged.cc rename : src/mem/cache/prefetch/tagged_prefetcher.hh => src/mem/cache/prefetch/tagged.hh rename : src/mem/cache/tags/base_tags.cc => src/mem/cache/tags/base.cc rename : src/mem/cache/tags/base_tags.hh => src/mem/cache/tags/base.hh rename : src/mem/cache/tags/Repl.py => src/mem/cache/tags/iic_repl/Repl.py rename : src/mem/cache/tags/repl/gen.cc => src/mem/cache/tags/iic_repl/gen.cc rename : src/mem/cache/tags/repl/gen.hh => src/mem/cache/tags/iic_repl/gen.hh rename : src/mem/cache/tags/repl/repl.hh => src/mem/cache/tags/iic_repl/repl.hh extra : convert_revision : ff7a35cc155a8d80317563c45cebe405984eac62 --- src/mem/cache/SConscript | 8 +- src/mem/cache/base.cc | 638 ++++++++++++++++++++++++++++ src/mem/cache/base.hh | 495 +++++++++++++++++++++ src/mem/cache/base_cache.cc | 638 ---------------------------- src/mem/cache/base_cache.hh | 495 --------------------- src/mem/cache/blk.cc | 41 ++ src/mem/cache/blk.hh | 274 ++++++++++++ src/mem/cache/builder.cc | 246 +++++++++++ src/mem/cache/cache_blk.cc | 41 -- src/mem/cache/cache_blk.hh | 274 ------------ src/mem/cache/cache_builder.cc | 246 ----------- src/mem/cache/miss/SConscript | 34 -- src/mem/cache/miss/mshr.cc | 424 ------------------ src/mem/cache/miss/mshr.hh | 254 ----------- src/mem/cache/miss/mshr_queue.cc | 247 ----------- src/mem/cache/miss/mshr_queue.hh | 214 ---------- src/mem/cache/mshr.cc | 424 ++++++++++++++++++ src/mem/cache/mshr.hh | 254 +++++++++++ src/mem/cache/mshr_queue.cc | 247 +++++++++++ src/mem/cache/mshr_queue.hh | 214 ++++++++++ src/mem/cache/prefetch/SConscript | 8 +- src/mem/cache/prefetch/base.cc | 269 ++++++++++++ src/mem/cache/prefetch/base.hh | 120 ++++++ src/mem/cache/prefetch/base_prefetcher.cc | 269 ------------ src/mem/cache/prefetch/base_prefetcher.hh | 120 ------ src/mem/cache/prefetch/ghb.cc | 74 ++++ src/mem/cache/prefetch/ghb.hh | 66 +++ src/mem/cache/prefetch/ghb_prefetcher.cc | 74 ---- src/mem/cache/prefetch/ghb_prefetcher.hh | 66 --- src/mem/cache/prefetch/stride.cc | 92 ++++ src/mem/cache/prefetch/stride.hh | 83 ++++ src/mem/cache/prefetch/stride_prefetcher.cc | 92 ---- src/mem/cache/prefetch/stride_prefetcher.hh | 83 ---- src/mem/cache/prefetch/tagged.cc | 70 +++ src/mem/cache/prefetch/tagged.hh | 58 +++ src/mem/cache/prefetch/tagged_prefetcher.cc | 70 --- src/mem/cache/prefetch/tagged_prefetcher.hh | 58 --- src/mem/cache/tags/Repl.py | 11 - src/mem/cache/tags/SConscript | 6 +- src/mem/cache/tags/base.cc | 91 ++++ src/mem/cache/tags/base.hh | 143 +++++++ src/mem/cache/tags/base_tags.cc | 91 ---- src/mem/cache/tags/base_tags.hh | 143 ------- src/mem/cache/tags/iic_repl/Repl.py | 39 ++ src/mem/cache/tags/iic_repl/gen.cc | 246 +++++++++++ src/mem/cache/tags/iic_repl/gen.hh | 241 +++++++++++ src/mem/cache/tags/iic_repl/repl.hh | 125 ++++++ src/mem/cache/tags/repl/gen.cc | 246 ----------- src/mem/cache/tags/repl/gen.hh | 241 ----------- src/mem/cache/tags/repl/repl.hh | 125 ------ 50 files changed, 4562 insertions(+), 4566 deletions(-) create mode 100644 src/mem/cache/base.cc create mode 100644 src/mem/cache/base.hh delete mode 100644 src/mem/cache/base_cache.cc delete mode 100644 src/mem/cache/base_cache.hh create mode 100644 src/mem/cache/blk.cc create mode 100644 src/mem/cache/blk.hh create mode 100644 src/mem/cache/builder.cc delete mode 100644 src/mem/cache/cache_blk.cc delete mode 100644 src/mem/cache/cache_blk.hh delete mode 100644 src/mem/cache/cache_builder.cc delete mode 100644 src/mem/cache/miss/SConscript delete mode 100644 src/mem/cache/miss/mshr.cc delete mode 100644 src/mem/cache/miss/mshr.hh delete mode 100644 src/mem/cache/miss/mshr_queue.cc delete mode 100644 src/mem/cache/miss/mshr_queue.hh create mode 100644 src/mem/cache/mshr.cc create mode 100644 src/mem/cache/mshr.hh create mode 100644 src/mem/cache/mshr_queue.cc create mode 100644 src/mem/cache/mshr_queue.hh create mode 100644 src/mem/cache/prefetch/base.cc create mode 100644 src/mem/cache/prefetch/base.hh delete mode 100644 src/mem/cache/prefetch/base_prefetcher.cc delete mode 100644 src/mem/cache/prefetch/base_prefetcher.hh create mode 100644 src/mem/cache/prefetch/ghb.cc create mode 100644 src/mem/cache/prefetch/ghb.hh delete mode 100644 src/mem/cache/prefetch/ghb_prefetcher.cc delete mode 100644 src/mem/cache/prefetch/ghb_prefetcher.hh create mode 100644 src/mem/cache/prefetch/stride.cc create mode 100644 src/mem/cache/prefetch/stride.hh delete mode 100644 src/mem/cache/prefetch/stride_prefetcher.cc delete mode 100644 src/mem/cache/prefetch/stride_prefetcher.hh create mode 100644 src/mem/cache/prefetch/tagged.cc create mode 100644 src/mem/cache/prefetch/tagged.hh delete mode 100644 src/mem/cache/prefetch/tagged_prefetcher.cc delete mode 100644 src/mem/cache/prefetch/tagged_prefetcher.hh delete mode 100644 src/mem/cache/tags/Repl.py create mode 100644 src/mem/cache/tags/base.cc create mode 100644 src/mem/cache/tags/base.hh delete mode 100644 src/mem/cache/tags/base_tags.cc delete mode 100644 src/mem/cache/tags/base_tags.hh create mode 100644 src/mem/cache/tags/iic_repl/Repl.py create mode 100644 src/mem/cache/tags/iic_repl/gen.cc create mode 100644 src/mem/cache/tags/iic_repl/gen.hh create mode 100644 src/mem/cache/tags/iic_repl/repl.hh delete mode 100644 src/mem/cache/tags/repl/gen.cc delete mode 100644 src/mem/cache/tags/repl/gen.hh delete mode 100644 src/mem/cache/tags/repl/repl.hh diff --git a/src/mem/cache/SConscript b/src/mem/cache/SConscript index d5899b623..3b8bdb0c8 100644 --- a/src/mem/cache/SConscript +++ b/src/mem/cache/SConscript @@ -32,10 +32,12 @@ Import('*') SimObject('BaseCache.py') -Source('base_cache.cc') +Source('base.cc') Source('cache.cc') -Source('cache_blk.cc') -Source('cache_builder.cc') +Source('blk.cc') +Source('builder.cc') +Source('mshr.cc') +Source('mshr_queue.cc') TraceFlag('Cache') TraceFlag('CachePort') diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc new file mode 100644 index 000000000..9fa9e2d29 --- /dev/null +++ b/src/mem/cache/base.cc @@ -0,0 +1,638 @@ +/* + * Copyright (c) 2003-2005 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: Erik Hallnor + */ + +/** + * @file + * Definition of BaseCache functions. + */ + +#include "cpu/base.hh" +#include "cpu/smt.hh" +#include "mem/cache/base_cache.hh" +#include "mem/cache/miss/mshr.hh" + +using namespace std; + +BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache, + const std::string &_label, + std::vector > filter_ranges) + : SimpleTimingPort(_name, _cache), cache(_cache), + label(_label), otherPort(NULL), + blocked(false), mustSendRetry(false), filterRanges(filter_ranges) +{ +} + + +BaseCache::BaseCache(const Params *p) + : MemObject(p), + mshrQueue("MSHRs", p->mshrs, 4, MSHRQueue_MSHRs), + writeBuffer("write buffer", p->write_buffers, p->mshrs+1000, + MSHRQueue_WriteBuffer), + blkSize(p->block_size), + hitLatency(p->latency), + numTarget(p->tgts_per_mshr), + blocked(0), + noTargetMSHR(NULL), + missCount(p->max_miss_count), + drainEvent(NULL) +{ +} + +void +BaseCache::CachePort::recvStatusChange(Port::Status status) +{ + if (status == Port::RangeChange) { + otherPort->sendStatusChange(Port::RangeChange); + } +} + + +bool +BaseCache::CachePort::checkFunctional(PacketPtr pkt) +{ + pkt->pushLabel(label); + bool done = SimpleTimingPort::checkFunctional(pkt); + pkt->popLabel(); + return done; +} + + +int +BaseCache::CachePort::deviceBlockSize() +{ + return cache->getBlockSize(); +} + + +bool +BaseCache::CachePort::recvRetryCommon() +{ + assert(waitingOnRetry); + waitingOnRetry = false; + return false; +} + + +void +BaseCache::CachePort::setBlocked() +{ + assert(!blocked); + DPRINTF(Cache, "Cache Blocking\n"); + blocked = true; + //Clear the retry flag + mustSendRetry = false; +} + +void +BaseCache::CachePort::clearBlocked() +{ + assert(blocked); + DPRINTF(Cache, "Cache Unblocking\n"); + blocked = false; + if (mustSendRetry) + { + DPRINTF(Cache, "Cache Sending Retry\n"); + mustSendRetry = false; + SendRetryEvent *ev = new SendRetryEvent(this, true); + // @TODO: need to find a better time (next bus cycle?) + ev->schedule(curTick + 1); + } +} + + +void +BaseCache::init() +{ + if (!cpuSidePort || !memSidePort) + panic("Cache not hooked up on both sides\n"); + cpuSidePort->sendStatusChange(Port::RangeChange); +} + + +void +BaseCache::regStats() +{ + using namespace Stats; + + // Hit statistics + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + hits[access_idx] + .init(maxThreadsPerCPU) + .name(name() + "." + cstr + "_hits") + .desc("number of " + cstr + " hits") + .flags(total | nozero | nonan) + ; + } + +// These macros make it easier to sum the right subset of commands and +// to change the subset of commands that are considered "demand" vs +// "non-demand" +#define SUM_DEMAND(s) \ + (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq]) + +// should writebacks be included here? prior code was inconsistent... +#define SUM_NON_DEMAND(s) \ + (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq]) + + demandHits + .name(name() + ".demand_hits") + .desc("number of demand (read+write) hits") + .flags(total) + ; + demandHits = SUM_DEMAND(hits); + + overallHits + .name(name() + ".overall_hits") + .desc("number of overall hits") + .flags(total) + ; + overallHits = demandHits + SUM_NON_DEMAND(hits); + + // Miss statistics + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + misses[access_idx] + .init(maxThreadsPerCPU) + .name(name() + "." + cstr + "_misses") + .desc("number of " + cstr + " misses") + .flags(total | nozero | nonan) + ; + } + + demandMisses + .name(name() + ".demand_misses") + .desc("number of demand (read+write) misses") + .flags(total) + ; + demandMisses = SUM_DEMAND(misses); + + overallMisses + .name(name() + ".overall_misses") + .desc("number of overall misses") + .flags(total) + ; + overallMisses = demandMisses + SUM_NON_DEMAND(misses); + + // Miss latency statistics + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + missLatency[access_idx] + .init(maxThreadsPerCPU) + .name(name() + "." + cstr + "_miss_latency") + .desc("number of " + cstr + " miss cycles") + .flags(total | nozero | nonan) + ; + } + + demandMissLatency + .name(name() + ".demand_miss_latency") + .desc("number of demand (read+write) miss cycles") + .flags(total) + ; + demandMissLatency = SUM_DEMAND(missLatency); + + overallMissLatency + .name(name() + ".overall_miss_latency") + .desc("number of overall miss cycles") + .flags(total) + ; + overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency); + + // access formulas + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + accesses[access_idx] + .name(name() + "." + cstr + "_accesses") + .desc("number of " + cstr + " accesses(hits+misses)") + .flags(total | nozero | nonan) + ; + + accesses[access_idx] = hits[access_idx] + misses[access_idx]; + } + + demandAccesses + .name(name() + ".demand_accesses") + .desc("number of demand (read+write) accesses") + .flags(total) + ; + demandAccesses = demandHits + demandMisses; + + overallAccesses + .name(name() + ".overall_accesses") + .desc("number of overall (read+write) accesses") + .flags(total) + ; + overallAccesses = overallHits + overallMisses; + + // miss rate formulas + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + missRate[access_idx] + .name(name() + "." + cstr + "_miss_rate") + .desc("miss rate for " + cstr + " accesses") + .flags(total | nozero | nonan) + ; + + missRate[access_idx] = misses[access_idx] / accesses[access_idx]; + } + + demandMissRate + .name(name() + ".demand_miss_rate") + .desc("miss rate for demand accesses") + .flags(total) + ; + demandMissRate = demandMisses / demandAccesses; + + overallMissRate + .name(name() + ".overall_miss_rate") + .desc("miss rate for overall accesses") + .flags(total) + ; + overallMissRate = overallMisses / overallAccesses; + + // miss latency formulas + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + avgMissLatency[access_idx] + .name(name() + "." + cstr + "_avg_miss_latency") + .desc("average " + cstr + " miss latency") + .flags(total | nozero | nonan) + ; + + avgMissLatency[access_idx] = + missLatency[access_idx] / misses[access_idx]; + } + + demandAvgMissLatency + .name(name() + ".demand_avg_miss_latency") + .desc("average overall miss latency") + .flags(total) + ; + demandAvgMissLatency = demandMissLatency / demandMisses; + + overallAvgMissLatency + .name(name() + ".overall_avg_miss_latency") + .desc("average overall miss latency") + .flags(total) + ; + overallAvgMissLatency = overallMissLatency / overallMisses; + + blocked_cycles.init(NUM_BLOCKED_CAUSES); + blocked_cycles + .name(name() + ".blocked_cycles") + .desc("number of cycles access was blocked") + .subname(Blocked_NoMSHRs, "no_mshrs") + .subname(Blocked_NoTargets, "no_targets") + ; + + + blocked_causes.init(NUM_BLOCKED_CAUSES); + blocked_causes + .name(name() + ".blocked") + .desc("number of cycles access was blocked") + .subname(Blocked_NoMSHRs, "no_mshrs") + .subname(Blocked_NoTargets, "no_targets") + ; + + avg_blocked + .name(name() + ".avg_blocked_cycles") + .desc("average number of cycles each access was blocked") + .subname(Blocked_NoMSHRs, "no_mshrs") + .subname(Blocked_NoTargets, "no_targets") + ; + + avg_blocked = blocked_cycles / blocked_causes; + + fastWrites + .name(name() + ".fast_writes") + .desc("number of fast writes performed") + ; + + cacheCopies + .name(name() + ".cache_copies") + .desc("number of cache copies performed") + ; + + writebacks + .init(maxThreadsPerCPU) + .name(name() + ".writebacks") + .desc("number of writebacks") + .flags(total) + ; + + // MSHR statistics + // MSHR hit statistics + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + mshr_hits[access_idx] + .init(maxThreadsPerCPU) + .name(name() + "." + cstr + "_mshr_hits") + .desc("number of " + cstr + " MSHR hits") + .flags(total | nozero | nonan) + ; + } + + demandMshrHits + .name(name() + ".demand_mshr_hits") + .desc("number of demand (read+write) MSHR hits") + .flags(total) + ; + demandMshrHits = SUM_DEMAND(mshr_hits); + + overallMshrHits + .name(name() + ".overall_mshr_hits") + .desc("number of overall MSHR hits") + .flags(total) + ; + overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits); + + // MSHR miss statistics + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + mshr_misses[access_idx] + .init(maxThreadsPerCPU) + .name(name() + "." + cstr + "_mshr_misses") + .desc("number of " + cstr + " MSHR misses") + .flags(total | nozero | nonan) + ; + } + + demandMshrMisses + .name(name() + ".demand_mshr_misses") + .desc("number of demand (read+write) MSHR misses") + .flags(total) + ; + demandMshrMisses = SUM_DEMAND(mshr_misses); + + overallMshrMisses + .name(name() + ".overall_mshr_misses") + .desc("number of overall MSHR misses") + .flags(total) + ; + overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses); + + // MSHR miss latency statistics + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + mshr_miss_latency[access_idx] + .init(maxThreadsPerCPU) + .name(name() + "." + cstr + "_mshr_miss_latency") + .desc("number of " + cstr + " MSHR miss cycles") + .flags(total | nozero | nonan) + ; + } + + demandMshrMissLatency + .name(name() + ".demand_mshr_miss_latency") + .desc("number of demand (read+write) MSHR miss cycles") + .flags(total) + ; + demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency); + + overallMshrMissLatency + .name(name() + ".overall_mshr_miss_latency") + .desc("number of overall MSHR miss cycles") + .flags(total) + ; + overallMshrMissLatency = + demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency); + + // MSHR uncacheable statistics + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + mshr_uncacheable[access_idx] + .init(maxThreadsPerCPU) + .name(name() + "." + cstr + "_mshr_uncacheable") + .desc("number of " + cstr + " MSHR uncacheable") + .flags(total | nozero | nonan) + ; + } + + overallMshrUncacheable + .name(name() + ".overall_mshr_uncacheable_misses") + .desc("number of overall MSHR uncacheable misses") + .flags(total) + ; + overallMshrUncacheable = + SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable); + + // MSHR miss latency statistics + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + mshr_uncacheable_lat[access_idx] + .init(maxThreadsPerCPU) + .name(name() + "." + cstr + "_mshr_uncacheable_latency") + .desc("number of " + cstr + " MSHR uncacheable cycles") + .flags(total | nozero | nonan) + ; + } + + overallMshrUncacheableLatency + .name(name() + ".overall_mshr_uncacheable_latency") + .desc("number of overall MSHR uncacheable cycles") + .flags(total) + ; + overallMshrUncacheableLatency = + SUM_DEMAND(mshr_uncacheable_lat) + + SUM_NON_DEMAND(mshr_uncacheable_lat); + +#if 0 + // MSHR access formulas + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + mshrAccesses[access_idx] + .name(name() + "." + cstr + "_mshr_accesses") + .desc("number of " + cstr + " mshr accesses(hits+misses)") + .flags(total | nozero | nonan) + ; + mshrAccesses[access_idx] = + mshr_hits[access_idx] + mshr_misses[access_idx] + + mshr_uncacheable[access_idx]; + } + + demandMshrAccesses + .name(name() + ".demand_mshr_accesses") + .desc("number of demand (read+write) mshr accesses") + .flags(total | nozero | nonan) + ; + demandMshrAccesses = demandMshrHits + demandMshrMisses; + + overallMshrAccesses + .name(name() + ".overall_mshr_accesses") + .desc("number of overall (read+write) mshr accesses") + .flags(total | nozero | nonan) + ; + overallMshrAccesses = overallMshrHits + overallMshrMisses + + overallMshrUncacheable; +#endif + + // MSHR miss rate formulas + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + mshrMissRate[access_idx] + .name(name() + "." + cstr + "_mshr_miss_rate") + .desc("mshr miss rate for " + cstr + " accesses") + .flags(total | nozero | nonan) + ; + + mshrMissRate[access_idx] = + mshr_misses[access_idx] / accesses[access_idx]; + } + + demandMshrMissRate + .name(name() + ".demand_mshr_miss_rate") + .desc("mshr miss rate for demand accesses") + .flags(total) + ; + demandMshrMissRate = demandMshrMisses / demandAccesses; + + overallMshrMissRate + .name(name() + ".overall_mshr_miss_rate") + .desc("mshr miss rate for overall accesses") + .flags(total) + ; + overallMshrMissRate = overallMshrMisses / overallAccesses; + + // mshrMiss latency formulas + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + avgMshrMissLatency[access_idx] + .name(name() + "." + cstr + "_avg_mshr_miss_latency") + .desc("average " + cstr + " mshr miss latency") + .flags(total | nozero | nonan) + ; + + avgMshrMissLatency[access_idx] = + mshr_miss_latency[access_idx] / mshr_misses[access_idx]; + } + + demandAvgMshrMissLatency + .name(name() + ".demand_avg_mshr_miss_latency") + .desc("average overall mshr miss latency") + .flags(total) + ; + demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses; + + overallAvgMshrMissLatency + .name(name() + ".overall_avg_mshr_miss_latency") + .desc("average overall mshr miss latency") + .flags(total) + ; + overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses; + + // mshrUncacheable latency formulas + for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { + MemCmd cmd(access_idx); + const string &cstr = cmd.toString(); + + avgMshrUncacheableLatency[access_idx] + .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency") + .desc("average " + cstr + " mshr uncacheable latency") + .flags(total | nozero | nonan) + ; + + avgMshrUncacheableLatency[access_idx] = + mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx]; + } + + overallAvgMshrUncacheableLatency + .name(name() + ".overall_avg_mshr_uncacheable_latency") + .desc("average overall mshr uncacheable latency") + .flags(total) + ; + overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable; + + mshr_cap_events + .init(maxThreadsPerCPU) + .name(name() + ".mshr_cap_events") + .desc("number of times MSHR cap was activated") + .flags(total) + ; + + //software prefetching stats + soft_prefetch_mshr_full + .init(maxThreadsPerCPU) + .name(name() + ".soft_prefetch_mshr_full") + .desc("number of mshr full events for SW prefetching instrutions") + .flags(total) + ; + + mshr_no_allocate_misses + .name(name() +".no_allocate_misses") + .desc("Number of misses that were no-allocate") + ; + +} + +unsigned int +BaseCache::drain(Event *de) +{ + int count = memSidePort->drain(de) + cpuSidePort->drain(de); + + // Set status + if (count != 0) { + drainEvent = de; + + changeState(SimObject::Draining); + return count; + } + + changeState(SimObject::Drained); + return 0; +} diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh new file mode 100644 index 000000000..604474524 --- /dev/null +++ b/src/mem/cache/base.hh @@ -0,0 +1,495 @@ +/* + * Copyright (c) 2003-2005 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: Erik Hallnor + * Steve Reinhardt + * Ron Dreslinski + */ + +/** + * @file + * Declares a basic cache interface BaseCache. + */ + +#ifndef __BASE_CACHE_HH__ +#define __BASE_CACHE_HH__ + +#include +#include +#include +#include +#include + +#include "base/misc.hh" +#include "base/statistics.hh" +#include "base/trace.hh" +#include "mem/cache/miss/mshr_queue.hh" +#include "mem/mem_object.hh" +#include "mem/packet.hh" +#include "mem/tport.hh" +#include "mem/request.hh" +#include "params/BaseCache.hh" +#include "sim/eventq.hh" +#include "sim/sim_exit.hh" + +class MSHR; +/** + * A basic cache interface. Implements some common functions for speed. + */ +class BaseCache : public MemObject +{ + /** + * Indexes to enumerate the MSHR queues. + */ + enum MSHRQueueIndex { + MSHRQueue_MSHRs, + MSHRQueue_WriteBuffer + }; + + /** + * Reasons for caches to be blocked. + */ + enum BlockedCause { + Blocked_NoMSHRs = MSHRQueue_MSHRs, + Blocked_NoWBBuffers = MSHRQueue_WriteBuffer, + Blocked_NoTargets, + NUM_BLOCKED_CAUSES + }; + + public: + /** + * Reasons for cache to request a bus. + */ + enum RequestCause { + Request_MSHR = MSHRQueue_MSHRs, + Request_WB = MSHRQueue_WriteBuffer, + Request_PF, + NUM_REQUEST_CAUSES + }; + + private: + + class CachePort : public SimpleTimingPort + { + public: + BaseCache *cache; + + protected: + CachePort(const std::string &_name, BaseCache *_cache, + const std::string &_label, + std::vector > filter_ranges); + + virtual void recvStatusChange(Status status); + + virtual int deviceBlockSize(); + + bool recvRetryCommon(); + + typedef EventWrapper + SendRetryEvent; + + const std::string label; + + public: + void setOtherPort(CachePort *_otherPort) { otherPort = _otherPort; } + + void setBlocked(); + + void clearBlocked(); + + bool checkFunctional(PacketPtr pkt); + + CachePort *otherPort; + + bool blocked; + + bool mustSendRetry; + + /** filter ranges */ + std::vector > filterRanges; + + void requestBus(RequestCause cause, Tick time) + { + DPRINTF(CachePort, "Asserting bus request for cause %d\n", cause); + if (!waitingOnRetry) { + schedSendEvent(time); + } + } + + void respond(PacketPtr pkt, Tick time) { + schedSendTiming(pkt, time); + } + }; + + public: //Made public so coherence can get at it. + CachePort *cpuSidePort; + CachePort *memSidePort; + + protected: + + /** Miss status registers */ + MSHRQueue mshrQueue; + + /** Write/writeback buffer */ + MSHRQueue writeBuffer; + + MSHR *allocateBufferInternal(MSHRQueue *mq, Addr addr, int size, + PacketPtr pkt, Tick time, bool requestBus) + { + MSHR *mshr = mq->allocate(addr, size, pkt, time, order++); + + if (mq->isFull()) { + setBlocked((BlockedCause)mq->index); + } + + if (requestBus) { + requestMemSideBus((RequestCause)mq->index, time); + } + + return mshr; + } + + void markInServiceInternal(MSHR *mshr) + { + MSHRQueue *mq = mshr->queue; + bool wasFull = mq->isFull(); + mq->markInService(mshr); + if (wasFull && !mq->isFull()) { + clearBlocked((BlockedCause)mq->index); + } + } + + /** Block size of this cache */ + const int blkSize; + + /** + * The latency of a hit in this device. + */ + int hitLatency; + + /** The number of targets for each MSHR. */ + const int numTarget; + + /** Increasing order number assigned to each incoming request. */ + uint64_t order; + + /** + * Bit vector of the blocking reasons for the access path. + * @sa #BlockedCause + */ + uint8_t blocked; + + /** Stores time the cache blocked for statistics. */ + Tick blockedCycle; + + /** Pointer to the MSHR that has no targets. */ + MSHR *noTargetMSHR; + + /** The number of misses to trigger an exit event. */ + Counter missCount; + + /** The drain event. */ + Event *drainEvent; + + public: + // Statistics + /** + * @addtogroup CacheStatistics + * @{ + */ + + /** Number of hits per thread for each type of command. @sa Packet::Command */ + Stats::Vector<> hits[MemCmd::NUM_MEM_CMDS]; + /** Number of hits for demand accesses. */ + Stats::Formula demandHits; + /** Number of hit for all accesses. */ + Stats::Formula overallHits; + + /** Number of misses per thread for each type of command. @sa Packet::Command */ + Stats::Vector<> misses[MemCmd::NUM_MEM_CMDS]; + /** Number of misses for demand accesses. */ + Stats::Formula demandMisses; + /** Number of misses for all accesses. */ + Stats::Formula overallMisses; + + /** + * Total number of cycles per thread/command spent waiting for a miss. + * Used to calculate the average miss latency. + */ + Stats::Vector<> missLatency[MemCmd::NUM_MEM_CMDS]; + /** Total number of cycles spent waiting for demand misses. */ + Stats::Formula demandMissLatency; + /** Total number of cycles spent waiting for all misses. */ + Stats::Formula overallMissLatency; + + /** The number of accesses per command and thread. */ + Stats::Formula accesses[MemCmd::NUM_MEM_CMDS]; + /** The number of demand accesses. */ + Stats::Formula demandAccesses; + /** The number of overall accesses. */ + Stats::Formula overallAccesses; + + /** The miss rate per command and thread. */ + Stats::Formula missRate[MemCmd::NUM_MEM_CMDS]; + /** The miss rate of all demand accesses. */ + Stats::Formula demandMissRate; + /** The miss rate for all accesses. */ + Stats::Formula overallMissRate; + + /** The average miss latency per command and thread. */ + Stats::Formula avgMissLatency[MemCmd::NUM_MEM_CMDS]; + /** The average miss latency for demand misses. */ + Stats::Formula demandAvgMissLatency; + /** The average miss latency for all misses. */ + Stats::Formula overallAvgMissLatency; + + /** The total number of cycles blocked for each blocked cause. */ + Stats::Vector<> blocked_cycles; + /** The number of times this cache blocked for each blocked cause. */ + Stats::Vector<> blocked_causes; + + /** The average number of cycles blocked for each blocked cause. */ + Stats::Formula avg_blocked; + + /** The number of fast writes (WH64) performed. */ + Stats::Scalar<> fastWrites; + + /** The number of cache copies performed. */ + Stats::Scalar<> cacheCopies; + + /** Number of blocks written back per thread. */ + Stats::Vector<> writebacks; + + /** Number of misses that hit in the MSHRs per command and thread. */ + Stats::Vector<> mshr_hits[MemCmd::NUM_MEM_CMDS]; + /** Demand misses that hit in the MSHRs. */ + Stats::Formula demandMshrHits; + /** Total number of misses that hit in the MSHRs. */ + Stats::Formula overallMshrHits; + + /** Number of misses that miss in the MSHRs, per command and thread. */ + Stats::Vector<> mshr_misses[MemCmd::NUM_MEM_CMDS]; + /** Demand misses that miss in the MSHRs. */ + Stats::Formula demandMshrMisses; + /** Total number of misses that miss in the MSHRs. */ + Stats::Formula overallMshrMisses; + + /** Number of misses that miss in the MSHRs, per command and thread. */ + Stats::Vector<> mshr_uncacheable[MemCmd::NUM_MEM_CMDS]; + /** Total number of misses that miss in the MSHRs. */ + Stats::Formula overallMshrUncacheable; + + /** Total cycle latency of each MSHR miss, per command and thread. */ + Stats::Vector<> mshr_miss_latency[MemCmd::NUM_MEM_CMDS]; + /** Total cycle latency of demand MSHR misses. */ + Stats::Formula demandMshrMissLatency; + /** Total cycle latency of overall MSHR misses. */ + Stats::Formula overallMshrMissLatency; + + /** Total cycle latency of each MSHR miss, per command and thread. */ + Stats::Vector<> mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS]; + /** Total cycle latency of overall MSHR misses. */ + Stats::Formula overallMshrUncacheableLatency; + + /** The total number of MSHR accesses per command and thread. */ + Stats::Formula mshrAccesses[MemCmd::NUM_MEM_CMDS]; + /** The total number of demand MSHR accesses. */ + Stats::Formula demandMshrAccesses; + /** The total number of MSHR accesses. */ + Stats::Formula overallMshrAccesses; + + /** The miss rate in the MSHRs pre command and thread. */ + Stats::Formula mshrMissRate[MemCmd::NUM_MEM_CMDS]; + /** The demand miss rate in the MSHRs. */ + Stats::Formula demandMshrMissRate; + /** The overall miss rate in the MSHRs. */ + Stats::Formula overallMshrMissRate; + + /** The average latency of an MSHR miss, per command and thread. */ + Stats::Formula avgMshrMissLatency[MemCmd::NUM_MEM_CMDS]; + /** The average latency of a demand MSHR miss. */ + Stats::Formula demandAvgMshrMissLatency; + /** The average overall latency of an MSHR miss. */ + Stats::Formula overallAvgMshrMissLatency; + + /** The average latency of an MSHR miss, per command and thread. */ + Stats::Formula avgMshrUncacheableLatency[MemCmd::NUM_MEM_CMDS]; + /** The average overall latency of an MSHR miss. */ + Stats::Formula overallAvgMshrUncacheableLatency; + + /** The number of times a thread hit its MSHR cap. */ + Stats::Vector<> mshr_cap_events; + /** The number of times software prefetches caused the MSHR to block. */ + Stats::Vector<> soft_prefetch_mshr_full; + + Stats::Scalar<> mshr_no_allocate_misses; + + /** + * @} + */ + + /** + * Register stats for this object. + */ + virtual void regStats(); + + public: + typedef BaseCacheParams Params; + BaseCache(const Params *p); + ~BaseCache() {} + + virtual void init(); + + /** + * Query block size of a cache. + * @return The block size + */ + int getBlockSize() const + { + return blkSize; + } + + + Addr blockAlign(Addr addr) const { return (addr & ~(blkSize - 1)); } + + + MSHR *allocateMissBuffer(PacketPtr pkt, Tick time, bool requestBus) + { + assert(!pkt->req->isUncacheable()); + return allocateBufferInternal(&mshrQueue, + blockAlign(pkt->getAddr()), blkSize, + pkt, time, requestBus); + } + + MSHR *allocateWriteBuffer(PacketPtr pkt, Tick time, bool requestBus) + { + assert(pkt->isWrite() && !pkt->isRead()); + return allocateBufferInternal(&writeBuffer, + pkt->getAddr(), pkt->getSize(), + pkt, time, requestBus); + } + + MSHR *allocateUncachedReadBuffer(PacketPtr pkt, Tick time, bool requestBus) + { + assert(pkt->req->isUncacheable()); + assert(pkt->isRead()); + return allocateBufferInternal(&mshrQueue, + pkt->getAddr(), pkt->getSize(), + pkt, time, requestBus); + } + + /** + * Returns true if the cache is blocked for accesses. + */ + bool isBlocked() + { + return blocked != 0; + } + + /** + * Marks the access path of the cache as blocked for the given cause. This + * also sets the blocked flag in the slave interface. + * @param cause The reason for the cache blocking. + */ + void setBlocked(BlockedCause cause) + { + uint8_t flag = 1 << cause; + if (blocked == 0) { + blocked_causes[cause]++; + blockedCycle = curTick; + cpuSidePort->setBlocked(); + } + blocked |= flag; + DPRINTF(Cache,"Blocking for cause %d, mask=%d\n", cause, blocked); + } + + /** + * Marks the cache as unblocked for the given cause. This also clears the + * blocked flags in the appropriate interfaces. + * @param cause The newly unblocked cause. + * @warning Calling this function can cause a blocked request on the bus to + * access the cache. The cache must be in a state to handle that request. + */ + void clearBlocked(BlockedCause cause) + { + uint8_t flag = 1 << cause; + blocked &= ~flag; + DPRINTF(Cache,"Unblocking for cause %d, mask=%d\n", cause, blocked); + if (blocked == 0) { + blocked_cycles[cause] += curTick - blockedCycle; + cpuSidePort->clearBlocked(); + } + } + + Tick nextMSHRReadyTime() + { + return std::min(mshrQueue.nextMSHRReadyTime(), + writeBuffer.nextMSHRReadyTime()); + } + + /** + * Request the master bus for the given cause and time. + * @param cause The reason for the request. + * @param time The time to make the request. + */ + void requestMemSideBus(RequestCause cause, Tick time) + { + memSidePort->requestBus(cause, time); + } + + /** + * Clear the master bus request for the given cause. + * @param cause The request reason to clear. + */ + void deassertMemSideBusRequest(RequestCause cause) + { + // obsolete!! + assert(false); + // memSidePort->deassertBusRequest(cause); + // checkDrain(); + } + + virtual unsigned int drain(Event *de); + + virtual bool inCache(Addr addr) = 0; + + virtual bool inMissQueue(Addr addr) = 0; + + void incMissCount(PacketPtr pkt) + { + misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; + + if (missCount) { + --missCount; + if (missCount == 0) + exitSimLoop("A cache reached the maximum miss count"); + } + } + +}; + +#endif //__BASE_CACHE_HH__ diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc deleted file mode 100644 index 9fa9e2d29..000000000 --- a/src/mem/cache/base_cache.cc +++ /dev/null @@ -1,638 +0,0 @@ -/* - * Copyright (c) 2003-2005 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: Erik Hallnor - */ - -/** - * @file - * Definition of BaseCache functions. - */ - -#include "cpu/base.hh" -#include "cpu/smt.hh" -#include "mem/cache/base_cache.hh" -#include "mem/cache/miss/mshr.hh" - -using namespace std; - -BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache, - const std::string &_label, - std::vector > filter_ranges) - : SimpleTimingPort(_name, _cache), cache(_cache), - label(_label), otherPort(NULL), - blocked(false), mustSendRetry(false), filterRanges(filter_ranges) -{ -} - - -BaseCache::BaseCache(const Params *p) - : MemObject(p), - mshrQueue("MSHRs", p->mshrs, 4, MSHRQueue_MSHRs), - writeBuffer("write buffer", p->write_buffers, p->mshrs+1000, - MSHRQueue_WriteBuffer), - blkSize(p->block_size), - hitLatency(p->latency), - numTarget(p->tgts_per_mshr), - blocked(0), - noTargetMSHR(NULL), - missCount(p->max_miss_count), - drainEvent(NULL) -{ -} - -void -BaseCache::CachePort::recvStatusChange(Port::Status status) -{ - if (status == Port::RangeChange) { - otherPort->sendStatusChange(Port::RangeChange); - } -} - - -bool -BaseCache::CachePort::checkFunctional(PacketPtr pkt) -{ - pkt->pushLabel(label); - bool done = SimpleTimingPort::checkFunctional(pkt); - pkt->popLabel(); - return done; -} - - -int -BaseCache::CachePort::deviceBlockSize() -{ - return cache->getBlockSize(); -} - - -bool -BaseCache::CachePort::recvRetryCommon() -{ - assert(waitingOnRetry); - waitingOnRetry = false; - return false; -} - - -void -BaseCache::CachePort::setBlocked() -{ - assert(!blocked); - DPRINTF(Cache, "Cache Blocking\n"); - blocked = true; - //Clear the retry flag - mustSendRetry = false; -} - -void -BaseCache::CachePort::clearBlocked() -{ - assert(blocked); - DPRINTF(Cache, "Cache Unblocking\n"); - blocked = false; - if (mustSendRetry) - { - DPRINTF(Cache, "Cache Sending Retry\n"); - mustSendRetry = false; - SendRetryEvent *ev = new SendRetryEvent(this, true); - // @TODO: need to find a better time (next bus cycle?) - ev->schedule(curTick + 1); - } -} - - -void -BaseCache::init() -{ - if (!cpuSidePort || !memSidePort) - panic("Cache not hooked up on both sides\n"); - cpuSidePort->sendStatusChange(Port::RangeChange); -} - - -void -BaseCache::regStats() -{ - using namespace Stats; - - // Hit statistics - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - hits[access_idx] - .init(maxThreadsPerCPU) - .name(name() + "." + cstr + "_hits") - .desc("number of " + cstr + " hits") - .flags(total | nozero | nonan) - ; - } - -// These macros make it easier to sum the right subset of commands and -// to change the subset of commands that are considered "demand" vs -// "non-demand" -#define SUM_DEMAND(s) \ - (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq]) - -// should writebacks be included here? prior code was inconsistent... -#define SUM_NON_DEMAND(s) \ - (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq]) - - demandHits - .name(name() + ".demand_hits") - .desc("number of demand (read+write) hits") - .flags(total) - ; - demandHits = SUM_DEMAND(hits); - - overallHits - .name(name() + ".overall_hits") - .desc("number of overall hits") - .flags(total) - ; - overallHits = demandHits + SUM_NON_DEMAND(hits); - - // Miss statistics - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - misses[access_idx] - .init(maxThreadsPerCPU) - .name(name() + "." + cstr + "_misses") - .desc("number of " + cstr + " misses") - .flags(total | nozero | nonan) - ; - } - - demandMisses - .name(name() + ".demand_misses") - .desc("number of demand (read+write) misses") - .flags(total) - ; - demandMisses = SUM_DEMAND(misses); - - overallMisses - .name(name() + ".overall_misses") - .desc("number of overall misses") - .flags(total) - ; - overallMisses = demandMisses + SUM_NON_DEMAND(misses); - - // Miss latency statistics - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - missLatency[access_idx] - .init(maxThreadsPerCPU) - .name(name() + "." + cstr + "_miss_latency") - .desc("number of " + cstr + " miss cycles") - .flags(total | nozero | nonan) - ; - } - - demandMissLatency - .name(name() + ".demand_miss_latency") - .desc("number of demand (read+write) miss cycles") - .flags(total) - ; - demandMissLatency = SUM_DEMAND(missLatency); - - overallMissLatency - .name(name() + ".overall_miss_latency") - .desc("number of overall miss cycles") - .flags(total) - ; - overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency); - - // access formulas - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - accesses[access_idx] - .name(name() + "." + cstr + "_accesses") - .desc("number of " + cstr + " accesses(hits+misses)") - .flags(total | nozero | nonan) - ; - - accesses[access_idx] = hits[access_idx] + misses[access_idx]; - } - - demandAccesses - .name(name() + ".demand_accesses") - .desc("number of demand (read+write) accesses") - .flags(total) - ; - demandAccesses = demandHits + demandMisses; - - overallAccesses - .name(name() + ".overall_accesses") - .desc("number of overall (read+write) accesses") - .flags(total) - ; - overallAccesses = overallHits + overallMisses; - - // miss rate formulas - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - missRate[access_idx] - .name(name() + "." + cstr + "_miss_rate") - .desc("miss rate for " + cstr + " accesses") - .flags(total | nozero | nonan) - ; - - missRate[access_idx] = misses[access_idx] / accesses[access_idx]; - } - - demandMissRate - .name(name() + ".demand_miss_rate") - .desc("miss rate for demand accesses") - .flags(total) - ; - demandMissRate = demandMisses / demandAccesses; - - overallMissRate - .name(name() + ".overall_miss_rate") - .desc("miss rate for overall accesses") - .flags(total) - ; - overallMissRate = overallMisses / overallAccesses; - - // miss latency formulas - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - avgMissLatency[access_idx] - .name(name() + "." + cstr + "_avg_miss_latency") - .desc("average " + cstr + " miss latency") - .flags(total | nozero | nonan) - ; - - avgMissLatency[access_idx] = - missLatency[access_idx] / misses[access_idx]; - } - - demandAvgMissLatency - .name(name() + ".demand_avg_miss_latency") - .desc("average overall miss latency") - .flags(total) - ; - demandAvgMissLatency = demandMissLatency / demandMisses; - - overallAvgMissLatency - .name(name() + ".overall_avg_miss_latency") - .desc("average overall miss latency") - .flags(total) - ; - overallAvgMissLatency = overallMissLatency / overallMisses; - - blocked_cycles.init(NUM_BLOCKED_CAUSES); - blocked_cycles - .name(name() + ".blocked_cycles") - .desc("number of cycles access was blocked") - .subname(Blocked_NoMSHRs, "no_mshrs") - .subname(Blocked_NoTargets, "no_targets") - ; - - - blocked_causes.init(NUM_BLOCKED_CAUSES); - blocked_causes - .name(name() + ".blocked") - .desc("number of cycles access was blocked") - .subname(Blocked_NoMSHRs, "no_mshrs") - .subname(Blocked_NoTargets, "no_targets") - ; - - avg_blocked - .name(name() + ".avg_blocked_cycles") - .desc("average number of cycles each access was blocked") - .subname(Blocked_NoMSHRs, "no_mshrs") - .subname(Blocked_NoTargets, "no_targets") - ; - - avg_blocked = blocked_cycles / blocked_causes; - - fastWrites - .name(name() + ".fast_writes") - .desc("number of fast writes performed") - ; - - cacheCopies - .name(name() + ".cache_copies") - .desc("number of cache copies performed") - ; - - writebacks - .init(maxThreadsPerCPU) - .name(name() + ".writebacks") - .desc("number of writebacks") - .flags(total) - ; - - // MSHR statistics - // MSHR hit statistics - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - mshr_hits[access_idx] - .init(maxThreadsPerCPU) - .name(name() + "." + cstr + "_mshr_hits") - .desc("number of " + cstr + " MSHR hits") - .flags(total | nozero | nonan) - ; - } - - demandMshrHits - .name(name() + ".demand_mshr_hits") - .desc("number of demand (read+write) MSHR hits") - .flags(total) - ; - demandMshrHits = SUM_DEMAND(mshr_hits); - - overallMshrHits - .name(name() + ".overall_mshr_hits") - .desc("number of overall MSHR hits") - .flags(total) - ; - overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits); - - // MSHR miss statistics - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - mshr_misses[access_idx] - .init(maxThreadsPerCPU) - .name(name() + "." + cstr + "_mshr_misses") - .desc("number of " + cstr + " MSHR misses") - .flags(total | nozero | nonan) - ; - } - - demandMshrMisses - .name(name() + ".demand_mshr_misses") - .desc("number of demand (read+write) MSHR misses") - .flags(total) - ; - demandMshrMisses = SUM_DEMAND(mshr_misses); - - overallMshrMisses - .name(name() + ".overall_mshr_misses") - .desc("number of overall MSHR misses") - .flags(total) - ; - overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses); - - // MSHR miss latency statistics - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - mshr_miss_latency[access_idx] - .init(maxThreadsPerCPU) - .name(name() + "." + cstr + "_mshr_miss_latency") - .desc("number of " + cstr + " MSHR miss cycles") - .flags(total | nozero | nonan) - ; - } - - demandMshrMissLatency - .name(name() + ".demand_mshr_miss_latency") - .desc("number of demand (read+write) MSHR miss cycles") - .flags(total) - ; - demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency); - - overallMshrMissLatency - .name(name() + ".overall_mshr_miss_latency") - .desc("number of overall MSHR miss cycles") - .flags(total) - ; - overallMshrMissLatency = - demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency); - - // MSHR uncacheable statistics - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - mshr_uncacheable[access_idx] - .init(maxThreadsPerCPU) - .name(name() + "." + cstr + "_mshr_uncacheable") - .desc("number of " + cstr + " MSHR uncacheable") - .flags(total | nozero | nonan) - ; - } - - overallMshrUncacheable - .name(name() + ".overall_mshr_uncacheable_misses") - .desc("number of overall MSHR uncacheable misses") - .flags(total) - ; - overallMshrUncacheable = - SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable); - - // MSHR miss latency statistics - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - mshr_uncacheable_lat[access_idx] - .init(maxThreadsPerCPU) - .name(name() + "." + cstr + "_mshr_uncacheable_latency") - .desc("number of " + cstr + " MSHR uncacheable cycles") - .flags(total | nozero | nonan) - ; - } - - overallMshrUncacheableLatency - .name(name() + ".overall_mshr_uncacheable_latency") - .desc("number of overall MSHR uncacheable cycles") - .flags(total) - ; - overallMshrUncacheableLatency = - SUM_DEMAND(mshr_uncacheable_lat) + - SUM_NON_DEMAND(mshr_uncacheable_lat); - -#if 0 - // MSHR access formulas - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - mshrAccesses[access_idx] - .name(name() + "." + cstr + "_mshr_accesses") - .desc("number of " + cstr + " mshr accesses(hits+misses)") - .flags(total | nozero | nonan) - ; - mshrAccesses[access_idx] = - mshr_hits[access_idx] + mshr_misses[access_idx] - + mshr_uncacheable[access_idx]; - } - - demandMshrAccesses - .name(name() + ".demand_mshr_accesses") - .desc("number of demand (read+write) mshr accesses") - .flags(total | nozero | nonan) - ; - demandMshrAccesses = demandMshrHits + demandMshrMisses; - - overallMshrAccesses - .name(name() + ".overall_mshr_accesses") - .desc("number of overall (read+write) mshr accesses") - .flags(total | nozero | nonan) - ; - overallMshrAccesses = overallMshrHits + overallMshrMisses - + overallMshrUncacheable; -#endif - - // MSHR miss rate formulas - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - mshrMissRate[access_idx] - .name(name() + "." + cstr + "_mshr_miss_rate") - .desc("mshr miss rate for " + cstr + " accesses") - .flags(total | nozero | nonan) - ; - - mshrMissRate[access_idx] = - mshr_misses[access_idx] / accesses[access_idx]; - } - - demandMshrMissRate - .name(name() + ".demand_mshr_miss_rate") - .desc("mshr miss rate for demand accesses") - .flags(total) - ; - demandMshrMissRate = demandMshrMisses / demandAccesses; - - overallMshrMissRate - .name(name() + ".overall_mshr_miss_rate") - .desc("mshr miss rate for overall accesses") - .flags(total) - ; - overallMshrMissRate = overallMshrMisses / overallAccesses; - - // mshrMiss latency formulas - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - avgMshrMissLatency[access_idx] - .name(name() + "." + cstr + "_avg_mshr_miss_latency") - .desc("average " + cstr + " mshr miss latency") - .flags(total | nozero | nonan) - ; - - avgMshrMissLatency[access_idx] = - mshr_miss_latency[access_idx] / mshr_misses[access_idx]; - } - - demandAvgMshrMissLatency - .name(name() + ".demand_avg_mshr_miss_latency") - .desc("average overall mshr miss latency") - .flags(total) - ; - demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses; - - overallAvgMshrMissLatency - .name(name() + ".overall_avg_mshr_miss_latency") - .desc("average overall mshr miss latency") - .flags(total) - ; - overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses; - - // mshrUncacheable latency formulas - for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) { - MemCmd cmd(access_idx); - const string &cstr = cmd.toString(); - - avgMshrUncacheableLatency[access_idx] - .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency") - .desc("average " + cstr + " mshr uncacheable latency") - .flags(total | nozero | nonan) - ; - - avgMshrUncacheableLatency[access_idx] = - mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx]; - } - - overallAvgMshrUncacheableLatency - .name(name() + ".overall_avg_mshr_uncacheable_latency") - .desc("average overall mshr uncacheable latency") - .flags(total) - ; - overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable; - - mshr_cap_events - .init(maxThreadsPerCPU) - .name(name() + ".mshr_cap_events") - .desc("number of times MSHR cap was activated") - .flags(total) - ; - - //software prefetching stats - soft_prefetch_mshr_full - .init(maxThreadsPerCPU) - .name(name() + ".soft_prefetch_mshr_full") - .desc("number of mshr full events for SW prefetching instrutions") - .flags(total) - ; - - mshr_no_allocate_misses - .name(name() +".no_allocate_misses") - .desc("Number of misses that were no-allocate") - ; - -} - -unsigned int -BaseCache::drain(Event *de) -{ - int count = memSidePort->drain(de) + cpuSidePort->drain(de); - - // Set status - if (count != 0) { - drainEvent = de; - - changeState(SimObject::Draining); - return count; - } - - changeState(SimObject::Drained); - return 0; -} diff --git a/src/mem/cache/base_cache.hh b/src/mem/cache/base_cache.hh deleted file mode 100644 index 604474524..000000000 --- a/src/mem/cache/base_cache.hh +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright (c) 2003-2005 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: Erik Hallnor - * Steve Reinhardt - * Ron Dreslinski - */ - -/** - * @file - * Declares a basic cache interface BaseCache. - */ - -#ifndef __BASE_CACHE_HH__ -#define __BASE_CACHE_HH__ - -#include -#include -#include -#include -#include - -#include "base/misc.hh" -#include "base/statistics.hh" -#include "base/trace.hh" -#include "mem/cache/miss/mshr_queue.hh" -#include "mem/mem_object.hh" -#include "mem/packet.hh" -#include "mem/tport.hh" -#include "mem/request.hh" -#include "params/BaseCache.hh" -#include "sim/eventq.hh" -#include "sim/sim_exit.hh" - -class MSHR; -/** - * A basic cache interface. Implements some common functions for speed. - */ -class BaseCache : public MemObject -{ - /** - * Indexes to enumerate the MSHR queues. - */ - enum MSHRQueueIndex { - MSHRQueue_MSHRs, - MSHRQueue_WriteBuffer - }; - - /** - * Reasons for caches to be blocked. - */ - enum BlockedCause { - Blocked_NoMSHRs = MSHRQueue_MSHRs, - Blocked_NoWBBuffers = MSHRQueue_WriteBuffer, - Blocked_NoTargets, - NUM_BLOCKED_CAUSES - }; - - public: - /** - * Reasons for cache to request a bus. - */ - enum RequestCause { - Request_MSHR = MSHRQueue_MSHRs, - Request_WB = MSHRQueue_WriteBuffer, - Request_PF, - NUM_REQUEST_CAUSES - }; - - private: - - class CachePort : public SimpleTimingPort - { - public: - BaseCache *cache; - - protected: - CachePort(const std::string &_name, BaseCache *_cache, - const std::string &_label, - std::vector > filter_ranges); - - virtual void recvStatusChange(Status status); - - virtual int deviceBlockSize(); - - bool recvRetryCommon(); - - typedef EventWrapper - SendRetryEvent; - - const std::string label; - - public: - void setOtherPort(CachePort *_otherPort) { otherPort = _otherPort; } - - void setBlocked(); - - void clearBlocked(); - - bool checkFunctional(PacketPtr pkt); - - CachePort *otherPort; - - bool blocked; - - bool mustSendRetry; - - /** filter ranges */ - std::vector > filterRanges; - - void requestBus(RequestCause cause, Tick time) - { - DPRINTF(CachePort, "Asserting bus request for cause %d\n", cause); - if (!waitingOnRetry) { - schedSendEvent(time); - } - } - - void respond(PacketPtr pkt, Tick time) { - schedSendTiming(pkt, time); - } - }; - - public: //Made public so coherence can get at it. - CachePort *cpuSidePort; - CachePort *memSidePort; - - protected: - - /** Miss status registers */ - MSHRQueue mshrQueue; - - /** Write/writeback buffer */ - MSHRQueue writeBuffer; - - MSHR *allocateBufferInternal(MSHRQueue *mq, Addr addr, int size, - PacketPtr pkt, Tick time, bool requestBus) - { - MSHR *mshr = mq->allocate(addr, size, pkt, time, order++); - - if (mq->isFull()) { - setBlocked((BlockedCause)mq->index); - } - - if (requestBus) { - requestMemSideBus((RequestCause)mq->index, time); - } - - return mshr; - } - - void markInServiceInternal(MSHR *mshr) - { - MSHRQueue *mq = mshr->queue; - bool wasFull = mq->isFull(); - mq->markInService(mshr); - if (wasFull && !mq->isFull()) { - clearBlocked((BlockedCause)mq->index); - } - } - - /** Block size of this cache */ - const int blkSize; - - /** - * The latency of a hit in this device. - */ - int hitLatency; - - /** The number of targets for each MSHR. */ - const int numTarget; - - /** Increasing order number assigned to each incoming request. */ - uint64_t order; - - /** - * Bit vector of the blocking reasons for the access path. - * @sa #BlockedCause - */ - uint8_t blocked; - - /** Stores time the cache blocked for statistics. */ - Tick blockedCycle; - - /** Pointer to the MSHR that has no targets. */ - MSHR *noTargetMSHR; - - /** The number of misses to trigger an exit event. */ - Counter missCount; - - /** The drain event. */ - Event *drainEvent; - - public: - // Statistics - /** - * @addtogroup CacheStatistics - * @{ - */ - - /** Number of hits per thread for each type of command. @sa Packet::Command */ - Stats::Vector<> hits[MemCmd::NUM_MEM_CMDS]; - /** Number of hits for demand accesses. */ - Stats::Formula demandHits; - /** Number of hit for all accesses. */ - Stats::Formula overallHits; - - /** Number of misses per thread for each type of command. @sa Packet::Command */ - Stats::Vector<> misses[MemCmd::NUM_MEM_CMDS]; - /** Number of misses for demand accesses. */ - Stats::Formula demandMisses; - /** Number of misses for all accesses. */ - Stats::Formula overallMisses; - - /** - * Total number of cycles per thread/command spent waiting for a miss. - * Used to calculate the average miss latency. - */ - Stats::Vector<> missLatency[MemCmd::NUM_MEM_CMDS]; - /** Total number of cycles spent waiting for demand misses. */ - Stats::Formula demandMissLatency; - /** Total number of cycles spent waiting for all misses. */ - Stats::Formula overallMissLatency; - - /** The number of accesses per command and thread. */ - Stats::Formula accesses[MemCmd::NUM_MEM_CMDS]; - /** The number of demand accesses. */ - Stats::Formula demandAccesses; - /** The number of overall accesses. */ - Stats::Formula overallAccesses; - - /** The miss rate per command and thread. */ - Stats::Formula missRate[MemCmd::NUM_MEM_CMDS]; - /** The miss rate of all demand accesses. */ - Stats::Formula demandMissRate; - /** The miss rate for all accesses. */ - Stats::Formula overallMissRate; - - /** The average miss latency per command and thread. */ - Stats::Formula avgMissLatency[MemCmd::NUM_MEM_CMDS]; - /** The average miss latency for demand misses. */ - Stats::Formula demandAvgMissLatency; - /** The average miss latency for all misses. */ - Stats::Formula overallAvgMissLatency; - - /** The total number of cycles blocked for each blocked cause. */ - Stats::Vector<> blocked_cycles; - /** The number of times this cache blocked for each blocked cause. */ - Stats::Vector<> blocked_causes; - - /** The average number of cycles blocked for each blocked cause. */ - Stats::Formula avg_blocked; - - /** The number of fast writes (WH64) performed. */ - Stats::Scalar<> fastWrites; - - /** The number of cache copies performed. */ - Stats::Scalar<> cacheCopies; - - /** Number of blocks written back per thread. */ - Stats::Vector<> writebacks; - - /** Number of misses that hit in the MSHRs per command and thread. */ - Stats::Vector<> mshr_hits[MemCmd::NUM_MEM_CMDS]; - /** Demand misses that hit in the MSHRs. */ - Stats::Formula demandMshrHits; - /** Total number of misses that hit in the MSHRs. */ - Stats::Formula overallMshrHits; - - /** Number of misses that miss in the MSHRs, per command and thread. */ - Stats::Vector<> mshr_misses[MemCmd::NUM_MEM_CMDS]; - /** Demand misses that miss in the MSHRs. */ - Stats::Formula demandMshrMisses; - /** Total number of misses that miss in the MSHRs. */ - Stats::Formula overallMshrMisses; - - /** Number of misses that miss in the MSHRs, per command and thread. */ - Stats::Vector<> mshr_uncacheable[MemCmd::NUM_MEM_CMDS]; - /** Total number of misses that miss in the MSHRs. */ - Stats::Formula overallMshrUncacheable; - - /** Total cycle latency of each MSHR miss, per command and thread. */ - Stats::Vector<> mshr_miss_latency[MemCmd::NUM_MEM_CMDS]; - /** Total cycle latency of demand MSHR misses. */ - Stats::Formula demandMshrMissLatency; - /** Total cycle latency of overall MSHR misses. */ - Stats::Formula overallMshrMissLatency; - - /** Total cycle latency of each MSHR miss, per command and thread. */ - Stats::Vector<> mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS]; - /** Total cycle latency of overall MSHR misses. */ - Stats::Formula overallMshrUncacheableLatency; - - /** The total number of MSHR accesses per command and thread. */ - Stats::Formula mshrAccesses[MemCmd::NUM_MEM_CMDS]; - /** The total number of demand MSHR accesses. */ - Stats::Formula demandMshrAccesses; - /** The total number of MSHR accesses. */ - Stats::Formula overallMshrAccesses; - - /** The miss rate in the MSHRs pre command and thread. */ - Stats::Formula mshrMissRate[MemCmd::NUM_MEM_CMDS]; - /** The demand miss rate in the MSHRs. */ - Stats::Formula demandMshrMissRate; - /** The overall miss rate in the MSHRs. */ - Stats::Formula overallMshrMissRate; - - /** The average latency of an MSHR miss, per command and thread. */ - Stats::Formula avgMshrMissLatency[MemCmd::NUM_MEM_CMDS]; - /** The average latency of a demand MSHR miss. */ - Stats::Formula demandAvgMshrMissLatency; - /** The average overall latency of an MSHR miss. */ - Stats::Formula overallAvgMshrMissLatency; - - /** The average latency of an MSHR miss, per command and thread. */ - Stats::Formula avgMshrUncacheableLatency[MemCmd::NUM_MEM_CMDS]; - /** The average overall latency of an MSHR miss. */ - Stats::Formula overallAvgMshrUncacheableLatency; - - /** The number of times a thread hit its MSHR cap. */ - Stats::Vector<> mshr_cap_events; - /** The number of times software prefetches caused the MSHR to block. */ - Stats::Vector<> soft_prefetch_mshr_full; - - Stats::Scalar<> mshr_no_allocate_misses; - - /** - * @} - */ - - /** - * Register stats for this object. - */ - virtual void regStats(); - - public: - typedef BaseCacheParams Params; - BaseCache(const Params *p); - ~BaseCache() {} - - virtual void init(); - - /** - * Query block size of a cache. - * @return The block size - */ - int getBlockSize() const - { - return blkSize; - } - - - Addr blockAlign(Addr addr) const { return (addr & ~(blkSize - 1)); } - - - MSHR *allocateMissBuffer(PacketPtr pkt, Tick time, bool requestBus) - { - assert(!pkt->req->isUncacheable()); - return allocateBufferInternal(&mshrQueue, - blockAlign(pkt->getAddr()), blkSize, - pkt, time, requestBus); - } - - MSHR *allocateWriteBuffer(PacketPtr pkt, Tick time, bool requestBus) - { - assert(pkt->isWrite() && !pkt->isRead()); - return allocateBufferInternal(&writeBuffer, - pkt->getAddr(), pkt->getSize(), - pkt, time, requestBus); - } - - MSHR *allocateUncachedReadBuffer(PacketPtr pkt, Tick time, bool requestBus) - { - assert(pkt->req->isUncacheable()); - assert(pkt->isRead()); - return allocateBufferInternal(&mshrQueue, - pkt->getAddr(), pkt->getSize(), - pkt, time, requestBus); - } - - /** - * Returns true if the cache is blocked for accesses. - */ - bool isBlocked() - { - return blocked != 0; - } - - /** - * Marks the access path of the cache as blocked for the given cause. This - * also sets the blocked flag in the slave interface. - * @param cause The reason for the cache blocking. - */ - void setBlocked(BlockedCause cause) - { - uint8_t flag = 1 << cause; - if (blocked == 0) { - blocked_causes[cause]++; - blockedCycle = curTick; - cpuSidePort->setBlocked(); - } - blocked |= flag; - DPRINTF(Cache,"Blocking for cause %d, mask=%d\n", cause, blocked); - } - - /** - * Marks the cache as unblocked for the given cause. This also clears the - * blocked flags in the appropriate interfaces. - * @param cause The newly unblocked cause. - * @warning Calling this function can cause a blocked request on the bus to - * access the cache. The cache must be in a state to handle that request. - */ - void clearBlocked(BlockedCause cause) - { - uint8_t flag = 1 << cause; - blocked &= ~flag; - DPRINTF(Cache,"Unblocking for cause %d, mask=%d\n", cause, blocked); - if (blocked == 0) { - blocked_cycles[cause] += curTick - blockedCycle; - cpuSidePort->clearBlocked(); - } - } - - Tick nextMSHRReadyTime() - { - return std::min(mshrQueue.nextMSHRReadyTime(), - writeBuffer.nextMSHRReadyTime()); - } - - /** - * Request the master bus for the given cause and time. - * @param cause The reason for the request. - * @param time The time to make the request. - */ - void requestMemSideBus(RequestCause cause, Tick time) - { - memSidePort->requestBus(cause, time); - } - - /** - * Clear the master bus request for the given cause. - * @param cause The request reason to clear. - */ - void deassertMemSideBusRequest(RequestCause cause) - { - // obsolete!! - assert(false); - // memSidePort->deassertBusRequest(cause); - // checkDrain(); - } - - virtual unsigned int drain(Event *de); - - virtual bool inCache(Addr addr) = 0; - - virtual bool inMissQueue(Addr addr) = 0; - - void incMissCount(PacketPtr pkt) - { - misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++; - - if (missCount) { - --missCount; - if (missCount == 0) - exitSimLoop("A cache reached the maximum miss count"); - } - } - -}; - -#endif //__BASE_CACHE_HH__ diff --git a/src/mem/cache/blk.cc b/src/mem/cache/blk.cc new file mode 100644 index 000000000..d4a2eaee8 --- /dev/null +++ b/src/mem/cache/blk.cc @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2007 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 "base/cprintf.hh" +#include "mem/cache/cache_blk.hh" + +void +CacheBlkPrintWrapper::print(std::ostream &os, int verbosity, + const std::string &prefix) const +{ + ccprintf(os, "%sblk %c%c%c\n", prefix, + blk->isValid() ? 'V' : '-', + blk->isWritable() ? 'E' : '-', + blk->isDirty() ? 'M' : '-'); +} + diff --git a/src/mem/cache/blk.hh b/src/mem/cache/blk.hh new file mode 100644 index 000000000..bafb46a89 --- /dev/null +++ b/src/mem/cache/blk.hh @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2003-2005 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: Erik Hallnor + */ + +/** @file + * Definitions of a simple cache block class. + */ + +#ifndef __CACHE_BLK_HH__ +#define __CACHE_BLK_HH__ + +#include + +#include "base/printable.hh" +#include "sim/core.hh" // for Tick +#include "arch/isa_traits.hh" // for Addr +#include "mem/packet.hh" +#include "mem/request.hh" + +/** + * Cache block status bit assignments + */ +enum CacheBlkStatusBits { + /** valid, readable */ + BlkValid = 0x01, + /** write permission */ + BlkWritable = 0x02, + /** dirty (modified) */ + BlkDirty = 0x04, + /** block was referenced */ + BlkReferenced = 0x10, + /** block was a hardware prefetch yet unaccessed*/ + BlkHWPrefetched = 0x20 +}; + +/** + * A Basic Cache block. + * Contains the tag, status, and a pointer to data. + */ +class CacheBlk +{ + public: + /** The address space ID of this block. */ + int asid; + /** Data block tag value. */ + Addr tag; + /** + * Contains a copy of the data in this block for easy access. This is used + * for efficient execution when the data could be actually stored in + * another format (COW, compressed, sub-blocked, etc). In all cases the + * data stored here should be kept consistant with the actual data + * referenced by this block. + */ + uint8_t *data; + /** the number of bytes stored in this block. */ + int size; + + /** block state: OR of CacheBlkStatusBit */ + typedef unsigned State; + + /** The current status of this block. @sa CacheBlockStatusBits */ + State status; + + /** Which curTick will this block be accessable */ + Tick whenReady; + + /** + * The set this block belongs to. + * @todo Move this into subclasses when we fix CacheTags to use them. + */ + int set; + + /** Number of references to this block since it was brought in. */ + int refCount; + + protected: + /** + * Represents that the indicated thread context has a "lock" on + * the block, in the LL/SC sense. + */ + class Lock { + public: + int cpuNum; // locking CPU + int threadNum; // locking thread ID within CPU + + // check for matching execution context + bool matchesContext(Request *req) + { + return (cpuNum == req->getCpuNum() && + threadNum == req->getThreadNum()); + } + + Lock(Request *req) + : cpuNum(req->getCpuNum()), threadNum(req->getThreadNum()) + { + } + }; + + /** List of thread contexts that have performed a load-locked (LL) + * on the block since the last store. */ + std::list lockList; + + public: + + CacheBlk() + : asid(-1), tag(0), data(0) ,size(0), status(0), whenReady(0), + set(-1), refCount(0) + {} + + /** + * Copy the state of the given block into this one. + * @param rhs The block to copy. + * @return a const reference to this block. + */ + const CacheBlk& operator=(const CacheBlk& rhs) + { + asid = rhs.asid; + tag = rhs.tag; + data = rhs.data; + size = rhs.size; + status = rhs.status; + whenReady = rhs.whenReady; + set = rhs.set; + refCount = rhs.refCount; + return *this; + } + + /** + * Checks the write permissions of this block. + * @return True if the block is writable. + */ + bool isWritable() const + { + const int needed_bits = BlkWritable | BlkValid; + return (status & needed_bits) == needed_bits; + } + + /** + * Checks that a block is valid (readable). + * @return True if the block is valid. + */ + bool isValid() const + { + return (status & BlkValid) != 0; + } + + /** + * Check to see if a block has been written. + * @return True if the block is dirty. + */ + bool isDirty() const + { + return (status & BlkDirty) != 0; + } + + /** + * Check if this block has been referenced. + * @return True if the block has been referenced. + */ + bool isReferenced() const + { + return (status & BlkReferenced) != 0; + } + + /** + * Check if this block was the result of a hardware prefetch, yet to + * be touched. + * @return True if the block was a hardware prefetch, unaccesed. + */ + bool isPrefetch() const + { + return (status & BlkHWPrefetched) != 0; + } + + /** + * Track the fact that a local locked was issued to the block. If + * multiple LLs get issued from the same context we could have + * redundant records on the list, but that's OK, as they'll all + * get blown away at the next store. + */ + void trackLoadLocked(PacketPtr pkt) + { + assert(pkt->isLocked()); + lockList.push_front(Lock(pkt->req)); + } + + /** + * Clear the list of valid load locks. Should be called whenever + * block is written to or invalidated. + */ + void clearLoadLocks() { lockList.clear(); } + + /** + * Handle interaction of load-locked operations and stores. + * @return True if write should proceed, false otherwise. Returns + * false only in the case of a failed store conditional. + */ + bool checkWrite(PacketPtr pkt) + { + Request *req = pkt->req; + if (pkt->isLocked()) { + // it's a store conditional... have to check for matching + // load locked. + bool success = false; + + for (std::list::iterator i = lockList.begin(); + i != lockList.end(); ++i) + { + if (i->matchesContext(req)) { + // it's a store conditional, and as far as the memory + // system can tell, the requesting context's lock is + // still valid. + success = true; + break; + } + } + + req->setExtraData(success ? 1 : 0); + clearLoadLocks(); + return success; + } else { + // for *all* stores (conditional or otherwise) we have to + // clear the list of load-locks as they're all invalid now. + clearLoadLocks(); + return true; + } + } +}; + +/** + * Simple class to provide virtual print() method on cache blocks + * without allocating a vtable pointer for every single cache block. + * Just wrap the CacheBlk object in an instance of this before passing + * to a function that requires a Printable object. + */ +class CacheBlkPrintWrapper : public Printable +{ + CacheBlk *blk; + public: + CacheBlkPrintWrapper(CacheBlk *_blk) : blk(_blk) {} + virtual ~CacheBlkPrintWrapper() {} + void print(std::ostream &o, int verbosity = 0, + const std::string &prefix = "") const; +}; + + + +#endif //__CACHE_BLK_HH__ diff --git a/src/mem/cache/builder.cc b/src/mem/cache/builder.cc new file mode 100644 index 000000000..d67a9c9a4 --- /dev/null +++ b/src/mem/cache/builder.cc @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2003-2005 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: Erik Hallnor + * Nathan Binkert + */ + +/** + * @file + * Simobject instatiation of caches. + */ +#include + +// Must be included first to determine which caches we want +#include "enums/Prefetch.hh" +#include "mem/config/cache.hh" +#include "mem/config/prefetch.hh" +#include "mem/cache/base_cache.hh" +#include "mem/cache/cache.hh" +#include "mem/bus.hh" +#include "params/BaseCache.hh" + +// Tag Templates +#if defined(USE_CACHE_LRU) +#include "mem/cache/tags/lru.hh" +#endif + +#if defined(USE_CACHE_FALRU) +#include "mem/cache/tags/fa_lru.hh" +#endif + +#if defined(USE_CACHE_IIC) +#include "mem/cache/tags/iic.hh" +#endif + +#if defined(USE_CACHE_SPLIT) +#include "mem/cache/tags/split.hh" +#endif + +#if defined(USE_CACHE_SPLIT_LIFO) +#include "mem/cache/tags/split_lifo.hh" +#endif + +//Prefetcher Headers +#if defined(USE_GHB) +#include "mem/cache/prefetch/ghb_prefetcher.hh" +#endif +#if defined(USE_TAGGED) +#include "mem/cache/prefetch/tagged_prefetcher.hh" +#endif +#if defined(USE_STRIDED) +#include "mem/cache/prefetch/stride_prefetcher.hh" +#endif + + +using namespace std; +using namespace TheISA; + +#define BUILD_CACHE(TAGS, tags) \ + do { \ + BasePrefetcher *pf; \ + if (prefetch_policy == Enums::tagged) { \ + BUILD_TAGGED_PREFETCHER(TAGS); \ + } \ + else if (prefetch_policy == Enums::stride) { \ + BUILD_STRIDED_PREFETCHER(TAGS); \ + } \ + else if (prefetch_policy == Enums::ghb) { \ + BUILD_GHB_PREFETCHER(TAGS); \ + } \ + else { \ + BUILD_NULL_PREFETCHER(TAGS); \ + } \ + Cache *retval = \ + new Cache(this, tags, pf); \ + return retval; \ + } while (0) + +#define BUILD_CACHE_PANIC(x) do { \ + panic("%s not compiled into M5", x); \ + } while (0) + +#if defined(USE_CACHE_FALRU) +#define BUILD_FALRU_CACHE do { \ + FALRU *tags = new FALRU(block_size, size, latency); \ + BUILD_CACHE(FALRU, tags); \ + } while (0) +#else +#define BUILD_FALRU_CACHE BUILD_CACHE_PANIC("falru cache") +#endif + +#if defined(USE_CACHE_LRU) +#define BUILD_LRU_CACHE do { \ + LRU *tags = new LRU(numSets, block_size, assoc, latency); \ + BUILD_CACHE(LRU, tags); \ + } while (0) +#else +#define BUILD_LRU_CACHE BUILD_CACHE_PANIC("lru cache") +#endif + +#if defined(USE_CACHE_SPLIT) +#define BUILD_SPLIT_CACHE do { \ + Split *tags = new Split(numSets, block_size, assoc, split_size, lifo, \ + two_queue, latency); \ + BUILD_CACHE(Split, tags); \ + } while (0) +#else +#define BUILD_SPLIT_CACHE BUILD_CACHE_PANIC("split cache") +#endif + +#if defined(USE_CACHE_SPLIT_LIFO) +#define BUILD_SPLIT_LIFO_CACHE do { \ + SplitLIFO *tags = new SplitLIFO(block_size, size, assoc, \ + latency, two_queue, -1); \ + BUILD_CACHE(SplitLIFO, tags); \ + } while (0) +#else +#define BUILD_SPLIT_LIFO_CACHE BUILD_CACHE_PANIC("lifo cache") +#endif + +#if defined(USE_CACHE_IIC) +#define BUILD_IIC_CACHE do { \ + IIC *tags = new IIC(iic_params); \ + BUILD_CACHE(IIC, tags); \ + } while (0) +#else +#define BUILD_IIC_CACHE BUILD_CACHE_PANIC("iic") +#endif + +#define BUILD_CACHES do { \ + if (repl == NULL) { \ + if (numSets == 1) { \ + BUILD_FALRU_CACHE; \ + } else { \ + if (split == true) { \ + BUILD_SPLIT_CACHE; \ + } else if (lifo == true) { \ + BUILD_SPLIT_LIFO_CACHE; \ + } else { \ + BUILD_LRU_CACHE; \ + } \ + } \ + } else { \ + BUILD_IIC_CACHE; \ + } \ + } while (0) + +#define BUILD_COHERENCE(b) do { \ + } while (0) + +#if defined(USE_TAGGED) +#define BUILD_TAGGED_PREFETCHER(t) \ + pf = new TaggedPrefetcher(this) +#else +#define BUILD_TAGGED_PREFETCHER(t) BUILD_CACHE_PANIC("Tagged Prefetcher") +#endif + +#if defined(USE_STRIDED) +#define BUILD_STRIDED_PREFETCHER(t) \ + pf = new StridePrefetcher(this) +#else +#define BUILD_STRIDED_PREFETCHER(t) BUILD_CACHE_PANIC("Stride Prefetcher") +#endif + +#if defined(USE_GHB) +#define BUILD_GHB_PREFETCHER(t) \ + pf = new GHBPrefetcher(this) +#else +#define BUILD_GHB_PREFETCHER(t) BUILD_CACHE_PANIC("GHB Prefetcher") +#endif + +#if defined(USE_TAGGED) +#define BUILD_NULL_PREFETCHER(t) \ + pf = new TaggedPrefetcher(this) +#else +#define BUILD_NULL_PREFETCHER(t) BUILD_CACHE_PANIC("NULL Prefetcher (uses Tagged)") +#endif + +BaseCache * +BaseCacheParams::create() +{ + int numSets = size / (assoc * block_size); + if (subblock_size == 0) { + subblock_size = block_size; + } + + //Warnings about prefetcher policy + if (prefetch_policy == Enums::none) { + if (prefetch_miss || prefetch_access) + panic("With no prefetcher, you shouldn't prefetch from" + " either miss or access stream\n"); + } + + if (prefetch_policy == Enums::tagged || prefetch_policy == Enums::stride || + prefetch_policy == Enums::ghb) { + + if (!prefetch_miss && !prefetch_access) + warn("With this prefetcher you should chose a prefetch" + " stream (miss or access)\nNo Prefetching will occur\n"); + + if (prefetch_miss && prefetch_access) + panic("Can't do prefetches from both miss and access stream"); + } + +#if defined(USE_CACHE_IIC) + // Build IIC params + IIC::Params iic_params; + iic_params.size = size; + iic_params.numSets = numSets; + iic_params.blkSize = block_size; + iic_params.assoc = assoc; + iic_params.hashDelay = hash_delay; + iic_params.hitLatency = latency; + iic_params.rp = repl; + iic_params.subblockSize = subblock_size; +#else + const void *repl = NULL; +#endif + + BUILD_CACHES; + return NULL; +} diff --git a/src/mem/cache/cache_blk.cc b/src/mem/cache/cache_blk.cc deleted file mode 100644 index d4a2eaee8..000000000 --- a/src/mem/cache/cache_blk.cc +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2007 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 "base/cprintf.hh" -#include "mem/cache/cache_blk.hh" - -void -CacheBlkPrintWrapper::print(std::ostream &os, int verbosity, - const std::string &prefix) const -{ - ccprintf(os, "%sblk %c%c%c\n", prefix, - blk->isValid() ? 'V' : '-', - blk->isWritable() ? 'E' : '-', - blk->isDirty() ? 'M' : '-'); -} - diff --git a/src/mem/cache/cache_blk.hh b/src/mem/cache/cache_blk.hh deleted file mode 100644 index bafb46a89..000000000 --- a/src/mem/cache/cache_blk.hh +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) 2003-2005 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: Erik Hallnor - */ - -/** @file - * Definitions of a simple cache block class. - */ - -#ifndef __CACHE_BLK_HH__ -#define __CACHE_BLK_HH__ - -#include - -#include "base/printable.hh" -#include "sim/core.hh" // for Tick -#include "arch/isa_traits.hh" // for Addr -#include "mem/packet.hh" -#include "mem/request.hh" - -/** - * Cache block status bit assignments - */ -enum CacheBlkStatusBits { - /** valid, readable */ - BlkValid = 0x01, - /** write permission */ - BlkWritable = 0x02, - /** dirty (modified) */ - BlkDirty = 0x04, - /** block was referenced */ - BlkReferenced = 0x10, - /** block was a hardware prefetch yet unaccessed*/ - BlkHWPrefetched = 0x20 -}; - -/** - * A Basic Cache block. - * Contains the tag, status, and a pointer to data. - */ -class CacheBlk -{ - public: - /** The address space ID of this block. */ - int asid; - /** Data block tag value. */ - Addr tag; - /** - * Contains a copy of the data in this block for easy access. This is used - * for efficient execution when the data could be actually stored in - * another format (COW, compressed, sub-blocked, etc). In all cases the - * data stored here should be kept consistant with the actual data - * referenced by this block. - */ - uint8_t *data; - /** the number of bytes stored in this block. */ - int size; - - /** block state: OR of CacheBlkStatusBit */ - typedef unsigned State; - - /** The current status of this block. @sa CacheBlockStatusBits */ - State status; - - /** Which curTick will this block be accessable */ - Tick whenReady; - - /** - * The set this block belongs to. - * @todo Move this into subclasses when we fix CacheTags to use them. - */ - int set; - - /** Number of references to this block since it was brought in. */ - int refCount; - - protected: - /** - * Represents that the indicated thread context has a "lock" on - * the block, in the LL/SC sense. - */ - class Lock { - public: - int cpuNum; // locking CPU - int threadNum; // locking thread ID within CPU - - // check for matching execution context - bool matchesContext(Request *req) - { - return (cpuNum == req->getCpuNum() && - threadNum == req->getThreadNum()); - } - - Lock(Request *req) - : cpuNum(req->getCpuNum()), threadNum(req->getThreadNum()) - { - } - }; - - /** List of thread contexts that have performed a load-locked (LL) - * on the block since the last store. */ - std::list lockList; - - public: - - CacheBlk() - : asid(-1), tag(0), data(0) ,size(0), status(0), whenReady(0), - set(-1), refCount(0) - {} - - /** - * Copy the state of the given block into this one. - * @param rhs The block to copy. - * @return a const reference to this block. - */ - const CacheBlk& operator=(const CacheBlk& rhs) - { - asid = rhs.asid; - tag = rhs.tag; - data = rhs.data; - size = rhs.size; - status = rhs.status; - whenReady = rhs.whenReady; - set = rhs.set; - refCount = rhs.refCount; - return *this; - } - - /** - * Checks the write permissions of this block. - * @return True if the block is writable. - */ - bool isWritable() const - { - const int needed_bits = BlkWritable | BlkValid; - return (status & needed_bits) == needed_bits; - } - - /** - * Checks that a block is valid (readable). - * @return True if the block is valid. - */ - bool isValid() const - { - return (status & BlkValid) != 0; - } - - /** - * Check to see if a block has been written. - * @return True if the block is dirty. - */ - bool isDirty() const - { - return (status & BlkDirty) != 0; - } - - /** - * Check if this block has been referenced. - * @return True if the block has been referenced. - */ - bool isReferenced() const - { - return (status & BlkReferenced) != 0; - } - - /** - * Check if this block was the result of a hardware prefetch, yet to - * be touched. - * @return True if the block was a hardware prefetch, unaccesed. - */ - bool isPrefetch() const - { - return (status & BlkHWPrefetched) != 0; - } - - /** - * Track the fact that a local locked was issued to the block. If - * multiple LLs get issued from the same context we could have - * redundant records on the list, but that's OK, as they'll all - * get blown away at the next store. - */ - void trackLoadLocked(PacketPtr pkt) - { - assert(pkt->isLocked()); - lockList.push_front(Lock(pkt->req)); - } - - /** - * Clear the list of valid load locks. Should be called whenever - * block is written to or invalidated. - */ - void clearLoadLocks() { lockList.clear(); } - - /** - * Handle interaction of load-locked operations and stores. - * @return True if write should proceed, false otherwise. Returns - * false only in the case of a failed store conditional. - */ - bool checkWrite(PacketPtr pkt) - { - Request *req = pkt->req; - if (pkt->isLocked()) { - // it's a store conditional... have to check for matching - // load locked. - bool success = false; - - for (std::list::iterator i = lockList.begin(); - i != lockList.end(); ++i) - { - if (i->matchesContext(req)) { - // it's a store conditional, and as far as the memory - // system can tell, the requesting context's lock is - // still valid. - success = true; - break; - } - } - - req->setExtraData(success ? 1 : 0); - clearLoadLocks(); - return success; - } else { - // for *all* stores (conditional or otherwise) we have to - // clear the list of load-locks as they're all invalid now. - clearLoadLocks(); - return true; - } - } -}; - -/** - * Simple class to provide virtual print() method on cache blocks - * without allocating a vtable pointer for every single cache block. - * Just wrap the CacheBlk object in an instance of this before passing - * to a function that requires a Printable object. - */ -class CacheBlkPrintWrapper : public Printable -{ - CacheBlk *blk; - public: - CacheBlkPrintWrapper(CacheBlk *_blk) : blk(_blk) {} - virtual ~CacheBlkPrintWrapper() {} - void print(std::ostream &o, int verbosity = 0, - const std::string &prefix = "") const; -}; - - - -#endif //__CACHE_BLK_HH__ diff --git a/src/mem/cache/cache_builder.cc b/src/mem/cache/cache_builder.cc deleted file mode 100644 index d67a9c9a4..000000000 --- a/src/mem/cache/cache_builder.cc +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2003-2005 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: Erik Hallnor - * Nathan Binkert - */ - -/** - * @file - * Simobject instatiation of caches. - */ -#include - -// Must be included first to determine which caches we want -#include "enums/Prefetch.hh" -#include "mem/config/cache.hh" -#include "mem/config/prefetch.hh" -#include "mem/cache/base_cache.hh" -#include "mem/cache/cache.hh" -#include "mem/bus.hh" -#include "params/BaseCache.hh" - -// Tag Templates -#if defined(USE_CACHE_LRU) -#include "mem/cache/tags/lru.hh" -#endif - -#if defined(USE_CACHE_FALRU) -#include "mem/cache/tags/fa_lru.hh" -#endif - -#if defined(USE_CACHE_IIC) -#include "mem/cache/tags/iic.hh" -#endif - -#if defined(USE_CACHE_SPLIT) -#include "mem/cache/tags/split.hh" -#endif - -#if defined(USE_CACHE_SPLIT_LIFO) -#include "mem/cache/tags/split_lifo.hh" -#endif - -//Prefetcher Headers -#if defined(USE_GHB) -#include "mem/cache/prefetch/ghb_prefetcher.hh" -#endif -#if defined(USE_TAGGED) -#include "mem/cache/prefetch/tagged_prefetcher.hh" -#endif -#if defined(USE_STRIDED) -#include "mem/cache/prefetch/stride_prefetcher.hh" -#endif - - -using namespace std; -using namespace TheISA; - -#define BUILD_CACHE(TAGS, tags) \ - do { \ - BasePrefetcher *pf; \ - if (prefetch_policy == Enums::tagged) { \ - BUILD_TAGGED_PREFETCHER(TAGS); \ - } \ - else if (prefetch_policy == Enums::stride) { \ - BUILD_STRIDED_PREFETCHER(TAGS); \ - } \ - else if (prefetch_policy == Enums::ghb) { \ - BUILD_GHB_PREFETCHER(TAGS); \ - } \ - else { \ - BUILD_NULL_PREFETCHER(TAGS); \ - } \ - Cache *retval = \ - new Cache(this, tags, pf); \ - return retval; \ - } while (0) - -#define BUILD_CACHE_PANIC(x) do { \ - panic("%s not compiled into M5", x); \ - } while (0) - -#if defined(USE_CACHE_FALRU) -#define BUILD_FALRU_CACHE do { \ - FALRU *tags = new FALRU(block_size, size, latency); \ - BUILD_CACHE(FALRU, tags); \ - } while (0) -#else -#define BUILD_FALRU_CACHE BUILD_CACHE_PANIC("falru cache") -#endif - -#if defined(USE_CACHE_LRU) -#define BUILD_LRU_CACHE do { \ - LRU *tags = new LRU(numSets, block_size, assoc, latency); \ - BUILD_CACHE(LRU, tags); \ - } while (0) -#else -#define BUILD_LRU_CACHE BUILD_CACHE_PANIC("lru cache") -#endif - -#if defined(USE_CACHE_SPLIT) -#define BUILD_SPLIT_CACHE do { \ - Split *tags = new Split(numSets, block_size, assoc, split_size, lifo, \ - two_queue, latency); \ - BUILD_CACHE(Split, tags); \ - } while (0) -#else -#define BUILD_SPLIT_CACHE BUILD_CACHE_PANIC("split cache") -#endif - -#if defined(USE_CACHE_SPLIT_LIFO) -#define BUILD_SPLIT_LIFO_CACHE do { \ - SplitLIFO *tags = new SplitLIFO(block_size, size, assoc, \ - latency, two_queue, -1); \ - BUILD_CACHE(SplitLIFO, tags); \ - } while (0) -#else -#define BUILD_SPLIT_LIFO_CACHE BUILD_CACHE_PANIC("lifo cache") -#endif - -#if defined(USE_CACHE_IIC) -#define BUILD_IIC_CACHE do { \ - IIC *tags = new IIC(iic_params); \ - BUILD_CACHE(IIC, tags); \ - } while (0) -#else -#define BUILD_IIC_CACHE BUILD_CACHE_PANIC("iic") -#endif - -#define BUILD_CACHES do { \ - if (repl == NULL) { \ - if (numSets == 1) { \ - BUILD_FALRU_CACHE; \ - } else { \ - if (split == true) { \ - BUILD_SPLIT_CACHE; \ - } else if (lifo == true) { \ - BUILD_SPLIT_LIFO_CACHE; \ - } else { \ - BUILD_LRU_CACHE; \ - } \ - } \ - } else { \ - BUILD_IIC_CACHE; \ - } \ - } while (0) - -#define BUILD_COHERENCE(b) do { \ - } while (0) - -#if defined(USE_TAGGED) -#define BUILD_TAGGED_PREFETCHER(t) \ - pf = new TaggedPrefetcher(this) -#else -#define BUILD_TAGGED_PREFETCHER(t) BUILD_CACHE_PANIC("Tagged Prefetcher") -#endif - -#if defined(USE_STRIDED) -#define BUILD_STRIDED_PREFETCHER(t) \ - pf = new StridePrefetcher(this) -#else -#define BUILD_STRIDED_PREFETCHER(t) BUILD_CACHE_PANIC("Stride Prefetcher") -#endif - -#if defined(USE_GHB) -#define BUILD_GHB_PREFETCHER(t) \ - pf = new GHBPrefetcher(this) -#else -#define BUILD_GHB_PREFETCHER(t) BUILD_CACHE_PANIC("GHB Prefetcher") -#endif - -#if defined(USE_TAGGED) -#define BUILD_NULL_PREFETCHER(t) \ - pf = new TaggedPrefetcher(this) -#else -#define BUILD_NULL_PREFETCHER(t) BUILD_CACHE_PANIC("NULL Prefetcher (uses Tagged)") -#endif - -BaseCache * -BaseCacheParams::create() -{ - int numSets = size / (assoc * block_size); - if (subblock_size == 0) { - subblock_size = block_size; - } - - //Warnings about prefetcher policy - if (prefetch_policy == Enums::none) { - if (prefetch_miss || prefetch_access) - panic("With no prefetcher, you shouldn't prefetch from" - " either miss or access stream\n"); - } - - if (prefetch_policy == Enums::tagged || prefetch_policy == Enums::stride || - prefetch_policy == Enums::ghb) { - - if (!prefetch_miss && !prefetch_access) - warn("With this prefetcher you should chose a prefetch" - " stream (miss or access)\nNo Prefetching will occur\n"); - - if (prefetch_miss && prefetch_access) - panic("Can't do prefetches from both miss and access stream"); - } - -#if defined(USE_CACHE_IIC) - // Build IIC params - IIC::Params iic_params; - iic_params.size = size; - iic_params.numSets = numSets; - iic_params.blkSize = block_size; - iic_params.assoc = assoc; - iic_params.hashDelay = hash_delay; - iic_params.hitLatency = latency; - iic_params.rp = repl; - iic_params.subblockSize = subblock_size; -#else - const void *repl = NULL; -#endif - - BUILD_CACHES; - return NULL; -} diff --git a/src/mem/cache/miss/SConscript b/src/mem/cache/miss/SConscript deleted file mode 100644 index 376d670cd..000000000 --- a/src/mem/cache/miss/SConscript +++ /dev/null @@ -1,34 +0,0 @@ -# -*- mode:python -*- - -# 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. -# -# Authors: Nathan Binkert - -Import('*') - -Source('mshr.cc') -Source('mshr_queue.cc') diff --git a/src/mem/cache/miss/mshr.cc b/src/mem/cache/miss/mshr.cc deleted file mode 100644 index d711ca537..000000000 --- a/src/mem/cache/miss/mshr.cc +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (c) 2002-2005 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: Erik Hallnor - * Dave Greene - */ - -/** - * @file - * Miss Status and Handling Register (MSHR) definitions. - */ - -#include -#include -#include -#include - -#include "mem/cache/miss/mshr.hh" -#include "sim/core.hh" // for curTick -#include "sim/host.hh" -#include "base/misc.hh" -#include "mem/cache/cache.hh" - -using namespace std; - -MSHR::MSHR() -{ - inService = false; - ntargets = 0; - threadNum = -1; - targets = new TargetList(); - deferredTargets = new TargetList(); -} - - -MSHR::TargetList::TargetList() - : needsExclusive(false), hasUpgrade(false) -{} - - -inline void -MSHR::TargetList::add(PacketPtr pkt, Tick readyTime, - Counter order, bool cpuSide, bool markPending) -{ - if (cpuSide) { - if (pkt->needsExclusive()) { - needsExclusive = true; - } - - if (pkt->cmd == MemCmd::UpgradeReq) { - hasUpgrade = true; - } - } - - if (markPending) { - MSHR *mshr = dynamic_cast(pkt->senderState); - if (mshr != NULL) { - assert(!mshr->downstreamPending); - mshr->downstreamPending = true; - } - } - - push_back(Target(pkt, readyTime, order, cpuSide, markPending)); -} - - -void -MSHR::TargetList::replaceUpgrades() -{ - if (!hasUpgrade) - return; - - Iterator end_i = end(); - for (Iterator i = begin(); i != end_i; ++i) { - if (i->pkt->cmd == MemCmd::UpgradeReq) { - i->pkt->cmd = MemCmd::ReadExReq; - DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); - } - } - - hasUpgrade = false; -} - - -void -MSHR::TargetList::clearDownstreamPending() -{ - Iterator end_i = end(); - for (Iterator i = begin(); i != end_i; ++i) { - if (i->markedPending) { - MSHR *mshr = dynamic_cast(i->pkt->senderState); - if (mshr != NULL) { - mshr->clearDownstreamPending(); - } - } - } -} - - -bool -MSHR::TargetList::checkFunctional(PacketPtr pkt) -{ - Iterator end_i = end(); - for (Iterator i = begin(); i != end_i; ++i) { - if (pkt->checkFunctional(i->pkt)) { - return true; - } - } - - return false; -} - - -void -MSHR::TargetList:: -print(std::ostream &os, int verbosity, const std::string &prefix) const -{ - ConstIterator end_i = end(); - for (ConstIterator i = begin(); i != end_i; ++i) { - ccprintf(os, "%s%s: ", prefix, i->isCpuSide() ? "cpu" : "mem"); - i->pkt->print(os, verbosity, ""); - } -} - - -void -MSHR::allocate(Addr _addr, int _size, PacketPtr target, - Tick whenReady, Counter _order) -{ - addr = _addr; - size = _size; - readyTime = whenReady; - order = _order; - assert(target); - isCacheFill = false; - _isUncacheable = target->req->isUncacheable(); - inService = false; - downstreamPending = false; - threadNum = 0; - ntargets = 1; - // Don't know of a case where we would allocate a new MSHR for a - // snoop (mem-side request), so set cpuSide to true here. - assert(targets->isReset()); - targets->add(target, whenReady, _order, true, true); - assert(deferredTargets->isReset()); - pendingInvalidate = false; - pendingShared = false; - data = NULL; -} - - -void -MSHR::clearDownstreamPending() -{ - assert(downstreamPending); - downstreamPending = false; - // recursively clear flag on any MSHRs we will be forwarding - // responses to - targets->clearDownstreamPending(); -} - -bool -MSHR::markInService() -{ - assert(!inService); - if (isSimpleForward()) { - // we just forwarded the request packet & don't expect a - // response, so get rid of it - assert(getNumTargets() == 1); - popTarget(); - return true; - } - inService = true; - if (!downstreamPending) { - // let upstream caches know that the request has made it to a - // level where it's going to get a response - targets->clearDownstreamPending(); - } - return false; -} - - -void -MSHR::deallocate() -{ - assert(targets->empty()); - targets->resetFlags(); - assert(deferredTargets->isReset()); - assert(ntargets == 0); - inService = false; - //allocIter = NULL; - //readyIter = NULL; -} - -/* - * Adds a target to an MSHR - */ -void -MSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) -{ - // if there's a request already in service for this MSHR, we will - // have to defer the new target until after the response if any of - // the following are true: - // - there are other targets already deferred - // - there's a pending invalidate to be applied after the response - // comes back (but before this target is processed) - // - the outstanding request is for a non-exclusive block and this - // target requires an exclusive block - if (inService && - (!deferredTargets->empty() || pendingInvalidate || - (!targets->needsExclusive && pkt->needsExclusive()))) { - // need to put on deferred list - deferredTargets->add(pkt, whenReady, _order, true, true); - } else { - // No request outstanding, or still OK to append to - // outstanding request: append to regular target list. Only - // mark pending if current request hasn't been issued yet - // (isn't in service). - targets->add(pkt, whenReady, _order, true, !inService); - } - - ++ntargets; -} - -bool -MSHR::handleSnoop(PacketPtr pkt, Counter _order) -{ - if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { - // Request has not been issued yet, or it's been issued - // locally but is buffered unissued at some downstream cache - // which is forwarding us this snoop. Either way, the packet - // we're snooping logically precedes this MSHR's request, so - // the snoop has no impact on the MSHR, but must be processed - // in the standard way by the cache. The only exception is - // that if we're an L2+ cache buffering an UpgradeReq from a - // higher-level cache, and the snoop is invalidating, then our - // buffered upgrades must be converted to read exclusives, - // since the upper-level cache no longer has a valid copy. - // That is, even though the upper-level cache got out on its - // local bus first, some other invalidating transaction - // reached the global bus before the upgrade did. - if (pkt->needsExclusive()) { - targets->replaceUpgrades(); - deferredTargets->replaceUpgrades(); - } - - return false; - } - - // From here on down, the request issued by this MSHR logically - // precedes the request we're snooping. - - if (pkt->needsExclusive()) { - // snooped request still precedes the re-request we'll have to - // issue for deferred targets, if any... - deferredTargets->replaceUpgrades(); - } - - if (pendingInvalidate) { - // a prior snoop has already appended an invalidation, so - // logically we don't have the block anymore; no need for - // further snooping. - return true; - } - - if (targets->needsExclusive || pkt->needsExclusive()) { - // actual target device (typ. PhysicalMemory) will delete the - // packet on reception, so we need to save a copy here - PacketPtr cp_pkt = new Packet(pkt, true); - targets->add(cp_pkt, curTick, _order, false, - downstreamPending && targets->needsExclusive); - ++ntargets; - - if (targets->needsExclusive) { - // We're awaiting an exclusive copy, so ownership is pending. - // It's up to us to respond once the data arrives. - pkt->assertMemInhibit(); - pkt->setSupplyExclusive(); - } else { - // Someone else may respond before we get around to - // processing this snoop, which means the copied request - // pointer will no longer be valid - cp_pkt->req = NULL; - } - - if (pkt->needsExclusive()) { - // This transaction will take away our pending copy - pendingInvalidate = true; - } - } else { - // Read to a read: no conflict, so no need to record as - // target, but make sure neither reader thinks he's getting an - // exclusive copy - pendingShared = true; - pkt->assertShared(); - } - - return true; -} - - -bool -MSHR::promoteDeferredTargets() -{ - assert(targets->empty()); - if (deferredTargets->empty()) { - return false; - } - - // swap targets & deferredTargets lists - TargetList *tmp = targets; - targets = deferredTargets; - deferredTargets = tmp; - - assert(targets->size() == ntargets); - - // clear deferredTargets flags - deferredTargets->resetFlags(); - - pendingInvalidate = false; - pendingShared = false; - order = targets->front().order; - readyTime = std::max(curTick, targets->front().readyTime); - - return true; -} - - -void -MSHR::handleFill(Packet *pkt, CacheBlk *blk) -{ - if (pendingShared) { - // we snooped another read while this read was in - // service... assert shared line on its behalf - pkt->assertShared(); - } - - if (!pkt->sharedAsserted() && !pendingInvalidate - && deferredTargets->needsExclusive) { - // We got an exclusive response, but we have deferred targets - // which are waiting to request an exclusive copy (not because - // of a pending invalidate). This can happen if the original - // request was for a read-only (non-exclusive) block, but we - // got an exclusive copy anyway because of the E part of the - // MOESI/MESI protocol. Since we got the exclusive copy - // there's no need to defer the targets, so move them up to - // the regular target list. - assert(!targets->needsExclusive); - targets->needsExclusive = true; - // if any of the deferred targets were upper-level cache - // requests marked downstreamPending, need to clear that - assert(!downstreamPending); // not pending here anymore - deferredTargets->clearDownstreamPending(); - // this clears out deferredTargets too - targets->splice(targets->end(), *deferredTargets); - deferredTargets->resetFlags(); - } -} - - -bool -MSHR::checkFunctional(PacketPtr pkt) -{ - // For printing, we treat the MSHR as a whole as single entity. - // For other requests, we iterate over the individual targets - // since that's where the actual data lies. - if (pkt->isPrint()) { - pkt->checkFunctional(this, addr, size, NULL); - return false; - } else { - return (targets->checkFunctional(pkt) || - deferredTargets->checkFunctional(pkt)); - } -} - - -void -MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const -{ - ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n", - prefix, addr, addr+size-1, - isCacheFill ? "Fill" : "", - needsExclusive() ? "Excl" : "", - _isUncacheable ? "Unc" : "", - inService ? "InSvc" : "", - downstreamPending ? "DwnPend" : "", - pendingInvalidate ? "PendInv" : "", - pendingShared ? "PendShared" : ""); - - ccprintf(os, "%s Targets:\n", prefix); - targets->print(os, verbosity, prefix + " "); - if (!deferredTargets->empty()) { - ccprintf(os, "%s Deferred Targets:\n", prefix); - deferredTargets->print(os, verbosity, prefix + " "); - } -} - -MSHR::~MSHR() -{ -} diff --git a/src/mem/cache/miss/mshr.hh b/src/mem/cache/miss/mshr.hh deleted file mode 100644 index fdb0485cb..000000000 --- a/src/mem/cache/miss/mshr.hh +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2002-2005 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: Erik Hallnor - */ - -/** - * @file - * Miss Status and Handling Register (MSHR) declaration. - */ - -#ifndef __MSHR_HH__ -#define __MSHR_HH__ - -#include - -#include "base/printable.hh" -#include "mem/packet.hh" - -class CacheBlk; -class MSHRQueue; - -/** - * Miss Status and handling Register. This class keeps all the information - * needed to handle a cache miss including a list of target requests. - */ -class MSHR : public Packet::SenderState, public Printable -{ - - public: - - class Target { - public: - Tick recvTime; //!< Time when request was received (for stats) - Tick readyTime; //!< Time when request is ready to be serviced - Counter order; //!< Global order (for memory consistency mgmt) - PacketPtr pkt; //!< Pending request packet. - bool cpuSide; //!< Did request come from cpu side or mem side? - bool markedPending; //!< Did we mark upstream MSHR - //!< as downstreamPending? - - bool isCpuSide() const { return cpuSide; } - - Target(PacketPtr _pkt, Tick _readyTime, Counter _order, - bool _cpuSide, bool _markedPending) - : recvTime(curTick), readyTime(_readyTime), order(_order), - pkt(_pkt), cpuSide(_cpuSide), markedPending(_markedPending) - {} - }; - - class TargetList : public std::list { - /** Target list iterator. */ - typedef std::list::iterator Iterator; - typedef std::list::const_iterator ConstIterator; - - public: - bool needsExclusive; - bool hasUpgrade; - - TargetList(); - void resetFlags() { needsExclusive = hasUpgrade = false; } - bool isReset() { return !needsExclusive && !hasUpgrade; } - void add(PacketPtr pkt, Tick readyTime, Counter order, - bool cpuSide, bool markPending); - void replaceUpgrades(); - void clearDownstreamPending(); - bool checkFunctional(PacketPtr pkt); - void print(std::ostream &os, int verbosity, - const std::string &prefix) const; - }; - - /** A list of MSHRs. */ - typedef std::list List; - /** MSHR list iterator. */ - typedef List::iterator Iterator; - /** MSHR list const_iterator. */ - typedef List::const_iterator ConstIterator; - - /** Pointer to queue containing this MSHR. */ - MSHRQueue *queue; - - /** Cycle when ready to issue */ - Tick readyTime; - - /** Order number assigned by the miss queue. */ - Counter order; - - /** Address of the request. */ - Addr addr; - - /** Size of the request. */ - int size; - - /** True if the request has been sent to the bus. */ - bool inService; - - /** True if we will be putting the returned block in the cache */ - bool isCacheFill; - - /** True if we need to get an exclusive copy of the block. */ - bool needsExclusive() const { return targets->needsExclusive; } - - /** True if the request is uncacheable */ - bool _isUncacheable; - - bool downstreamPending; - - bool pendingInvalidate; - bool pendingShared; - - /** Thread number of the miss. */ - short threadNum; - /** The number of currently allocated targets. */ - short ntargets; - - - /** Data buffer (if needed). Currently used only for pending - * upgrade handling. */ - uint8_t *data; - - /** - * Pointer to this MSHR on the ready list. - * @sa MissQueue, MSHRQueue::readyList - */ - Iterator readyIter; - - /** - * Pointer to this MSHR on the allocated list. - * @sa MissQueue, MSHRQueue::allocatedList - */ - Iterator allocIter; - -private: - /** List of all requests that match the address */ - TargetList *targets; - - TargetList *deferredTargets; - -public: - - bool isUncacheable() { return _isUncacheable; } - - /** - * Allocate a miss to this MSHR. - * @param cmd The requesting command. - * @param addr The address of the miss. - * @param asid The address space id of the miss. - * @param size The number of bytes to request. - * @param pkt The original miss. - */ - void allocate(Addr addr, int size, PacketPtr pkt, - Tick when, Counter _order); - - bool markInService(); - - void clearDownstreamPending(); - - /** - * Mark this MSHR as free. - */ - void deallocate(); - - /** - * Add a request to the list of targets. - * @param target The target. - */ - void allocateTarget(PacketPtr target, Tick when, Counter order); - bool handleSnoop(PacketPtr target, Counter order); - - /** A simple constructor. */ - MSHR(); - /** A simple destructor. */ - ~MSHR(); - - /** - * Returns the current number of allocated targets. - * @return The current number of allocated targets. - */ - int getNumTargets() { return ntargets; } - - /** - * Returns a pointer to the target list. - * @return a pointer to the target list. - */ - TargetList *getTargetList() { return targets; } - - /** - * Returns true if there are targets left. - * @return true if there are targets - */ - bool hasTargets() { return !targets->empty(); } - - /** - * Returns a reference to the first target. - * @return A pointer to the first target. - */ - Target *getTarget() { assert(hasTargets()); return &targets->front(); } - - /** - * Pop first target. - */ - void popTarget() - { - --ntargets; - targets->pop_front(); - } - - bool isSimpleForward() - { - if (getNumTargets() != 1) - return false; - Target *tgt = getTarget(); - return tgt->isCpuSide() && !tgt->pkt->needsResponse(); - } - - bool promoteDeferredTargets(); - - void handleFill(Packet *pkt, CacheBlk *blk); - - bool checkFunctional(PacketPtr pkt); - - /** - * Prints the contents of this MSHR for debugging. - */ - void print(std::ostream &os, - int verbosity = 0, - const std::string &prefix = "") const; -}; - -#endif //__MSHR_HH__ diff --git a/src/mem/cache/miss/mshr_queue.cc b/src/mem/cache/miss/mshr_queue.cc deleted file mode 100644 index 71da7e4c1..000000000 --- a/src/mem/cache/miss/mshr_queue.cc +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2003-2005 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: Erik Hallnor - */ - -/** @file - * Definition of MSHRQueue class functions. - */ - -#include "mem/cache/miss/mshr_queue.hh" - -using namespace std; - -MSHRQueue::MSHRQueue(const std::string &_label, - int num_entries, int reserve, int _index) - : label(_label), - numEntries(num_entries + reserve - 1), numReserve(reserve), - index(_index) -{ - allocated = 0; - inServiceEntries = 0; - registers = new MSHR[numEntries]; - for (int i = 0; i < numEntries; ++i) { - registers[i].queue = this; - freeList.push_back(®isters[i]); - } -} - -MSHRQueue::~MSHRQueue() -{ - delete [] registers; -} - -MSHR * -MSHRQueue::findMatch(Addr addr) const -{ - MSHR::ConstIterator i = allocatedList.begin(); - MSHR::ConstIterator end = allocatedList.end(); - for (; i != end; ++i) { - MSHR *mshr = *i; - if (mshr->addr == addr) { - return mshr; - } - } - return NULL; -} - -bool -MSHRQueue::findMatches(Addr addr, vector& matches) const -{ - // Need an empty vector - assert(matches.empty()); - bool retval = false; - MSHR::ConstIterator i = allocatedList.begin(); - MSHR::ConstIterator end = allocatedList.end(); - for (; i != end; ++i) { - MSHR *mshr = *i; - if (mshr->addr == addr) { - retval = true; - matches.push_back(mshr); - } - } - return retval; -} - - -bool -MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr) -{ - pkt->pushLabel(label); - MSHR::ConstIterator i = allocatedList.begin(); - MSHR::ConstIterator end = allocatedList.end(); - for (; i != end; ++i) { - MSHR *mshr = *i; - if (mshr->addr == blk_addr && mshr->checkFunctional(pkt)) { - pkt->popLabel(); - return true; - } - } - pkt->popLabel(); - return false; -} - - -MSHR * -MSHRQueue::findPending(Addr addr, int size) const -{ - MSHR::ConstIterator i = readyList.begin(); - MSHR::ConstIterator end = readyList.end(); - for (; i != end; ++i) { - MSHR *mshr = *i; - if (mshr->addr < addr) { - if (mshr->addr + mshr->size > addr) { - return mshr; - } - } else { - if (addr + size > mshr->addr) { - return mshr; - } - } - } - return NULL; -} - - -MSHR::Iterator -MSHRQueue::addToReadyList(MSHR *mshr) -{ - if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) { - return readyList.insert(readyList.end(), mshr); - } - - MSHR::Iterator i = readyList.begin(); - MSHR::Iterator end = readyList.end(); - for (; i != end; ++i) { - if ((*i)->readyTime > mshr->readyTime) { - return readyList.insert(i, mshr); - } - } - assert(false); - return end; // keep stupid compilers happy -} - - -MSHR * -MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt, - Tick when, Counter order) -{ - assert(!freeList.empty()); - MSHR *mshr = freeList.front(); - assert(mshr->getNumTargets() == 0); - freeList.pop_front(); - - mshr->allocate(addr, size, pkt, when, order); - mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr); - mshr->readyIter = addToReadyList(mshr); - - allocated += 1; - return mshr; -} - - -void -MSHRQueue::deallocate(MSHR *mshr) -{ - deallocateOne(mshr); -} - -MSHR::Iterator -MSHRQueue::deallocateOne(MSHR *mshr) -{ - MSHR::Iterator retval = allocatedList.erase(mshr->allocIter); - freeList.push_front(mshr); - allocated--; - if (mshr->inService) { - inServiceEntries--; - } else { - readyList.erase(mshr->readyIter); - } - mshr->deallocate(); - return retval; -} - -void -MSHRQueue::moveToFront(MSHR *mshr) -{ - if (!mshr->inService) { - assert(mshr == *(mshr->readyIter)); - readyList.erase(mshr->readyIter); - mshr->readyIter = readyList.insert(readyList.begin(), mshr); - } -} - -void -MSHRQueue::markInService(MSHR *mshr) -{ - if (mshr->markInService()) { - deallocate(mshr); - } else { - readyList.erase(mshr->readyIter); - inServiceEntries += 1; - } -} - -void -MSHRQueue::markPending(MSHR *mshr) -{ - assert(mshr->inService); - mshr->inService = false; - --inServiceEntries; - /** - * @ todo might want to add rerequests to front of pending list for - * performance. - */ - mshr->readyIter = addToReadyList(mshr); -} - -void -MSHRQueue::squash(int threadNum) -{ - MSHR::Iterator i = allocatedList.begin(); - MSHR::Iterator end = allocatedList.end(); - for (; i != end;) { - MSHR *mshr = *i; - if (mshr->threadNum == threadNum) { - while (mshr->hasTargets()) { - mshr->popTarget(); - assert(0/*target->req->getThreadNum()*/ == threadNum); - } - assert(!mshr->hasTargets()); - assert(mshr->ntargets==0); - if (!mshr->inService) { - i = deallocateOne(mshr); - } else { - //mshr->pkt->flags &= ~CACHE_LINE_FILL; - ++i; - } - } else { - ++i; - } - } -} diff --git a/src/mem/cache/miss/mshr_queue.hh b/src/mem/cache/miss/mshr_queue.hh deleted file mode 100644 index e04745087..000000000 --- a/src/mem/cache/miss/mshr_queue.hh +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2003-2005 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: Erik Hallnor - */ - -/** @file - * Declaration of a structure to manage MSHRs. - */ - -#ifndef __MEM__CACHE__MISS__MSHR_QUEUE_HH__ -#define __MEM__CACHE__MISS__MSHR_QUEUE_HH__ - -#include - -#include "mem/packet.hh" -#include "mem/cache/miss/mshr.hh" - -/** - * A Class for maintaining a list of pending and allocated memory requests. - */ -class MSHRQueue -{ - private: - /** Local label (for functional print requests) */ - const std::string label; - - /** MSHR storage. */ - MSHR *registers; - /** Holds pointers to all allocated entries. */ - MSHR::List allocatedList; - /** Holds pointers to entries that haven't been sent to the bus. */ - MSHR::List readyList; - /** Holds non allocated entries. */ - MSHR::List freeList; - - // Parameters - /** - * The total number of entries in this queue. This number is set as the - * number of entries requested plus (numReserve - 1). This allows for - * the same number of effective entries while still maintaining the reserve. - */ - const int numEntries; - - /** - * The number of entries to hold in reserve. This is needed because copy - * operations can allocate upto 4 entries at one time. - */ - const int numReserve; - - MSHR::Iterator addToReadyList(MSHR *mshr); - - - public: - /** The number of allocated entries. */ - int allocated; - /** The number of entries that have been forwarded to the bus. */ - int inServiceEntries; - /** The index of this queue within the cache (MSHR queue vs. write - * buffer). */ - const int index; - - /** - * Create a queue with a given number of entries. - * @param num_entrys The number of entries in this queue. - * @param reserve The minimum number of entries needed to satisfy - * any access. - */ - MSHRQueue(const std::string &_label, int num_entries, int reserve, - int index); - - /** Destructor */ - ~MSHRQueue(); - - /** - * Find the first MSHR that matches the provided address. - * @param addr The address to find. - * @return Pointer to the matching MSHR, null if not found. - */ - MSHR *findMatch(Addr addr) const; - - /** - * Find and return all the matching entries in the provided vector. - * @param addr The address to find. - * @param matches The vector to return pointers to the matching entries. - * @return True if any matches are found, false otherwise. - * @todo Typedef the vector?? - */ - bool findMatches(Addr addr, std::vector& matches) const; - - /** - * Find any pending requests that overlap the given request. - * @param pkt The request to find. - * @return A pointer to the earliest matching MSHR. - */ - MSHR *findPending(Addr addr, int size) const; - - bool checkFunctional(PacketPtr pkt, Addr blk_addr); - - /** - * Allocates a new MSHR for the request and size. This places the request - * as the first target in the MSHR. - * @param pkt The request to handle. - * @param size The number in bytes to fetch from memory. - * @return The a pointer to the MSHR allocated. - * - * @pre There are free entries. - */ - MSHR *allocate(Addr addr, int size, PacketPtr &pkt, - Tick when, Counter order); - - /** - * Removes the given MSHR from the queue. This places the MSHR on the - * free list. - * @param mshr - */ - void deallocate(MSHR *mshr); - - /** - * Remove a MSHR from the queue. Returns an iterator into the - * allocatedList for faster squash implementation. - * @param mshr The MSHR to remove. - * @return An iterator to the next entry in the allocatedList. - */ - MSHR::Iterator deallocateOne(MSHR *mshr); - - /** - * Moves the MSHR to the front of the pending list if it is not - * in service. - * @param mshr The entry to move. - */ - void moveToFront(MSHR *mshr); - - /** - * Mark the given MSHR as in service. This removes the MSHR from the - * readyList. Deallocates the MSHR if it does not expect a response. - * @param mshr The MSHR to mark in service. - */ - void markInService(MSHR *mshr); - - /** - * Mark an in service entry as pending, used to resend a request. - * @param mshr The MSHR to resend. - */ - void markPending(MSHR *mshr); - - /** - * Squash outstanding requests with the given thread number. If a request - * is in service, just squashes the targets. - * @param threadNum The thread to squash. - */ - void squash(int threadNum); - - /** - * Returns true if the pending list is not empty. - * @return True if there are outstanding requests. - */ - bool havePending() const - { - return !readyList.empty(); - } - - /** - * Returns true if there are no free entries. - * @return True if this queue is full. - */ - bool isFull() const - { - return (allocated > numEntries - numReserve); - } - - /** - * Returns the MSHR at the head of the readyList. - * @return The next request to service. - */ - MSHR *getNextMSHR() const - { - if (readyList.empty() || readyList.front()->readyTime > curTick) { - return NULL; - } - return readyList.front(); - } - - Tick nextMSHRReadyTime() const - { - return readyList.empty() ? MaxTick : readyList.front()->readyTime; - } -}; - -#endif //__MEM__CACHE__MISS__MSHR_QUEUE_HH__ diff --git a/src/mem/cache/mshr.cc b/src/mem/cache/mshr.cc new file mode 100644 index 000000000..d711ca537 --- /dev/null +++ b/src/mem/cache/mshr.cc @@ -0,0 +1,424 @@ +/* + * Copyright (c) 2002-2005 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: Erik Hallnor + * Dave Greene + */ + +/** + * @file + * Miss Status and Handling Register (MSHR) definitions. + */ + +#include +#include +#include +#include + +#include "mem/cache/miss/mshr.hh" +#include "sim/core.hh" // for curTick +#include "sim/host.hh" +#include "base/misc.hh" +#include "mem/cache/cache.hh" + +using namespace std; + +MSHR::MSHR() +{ + inService = false; + ntargets = 0; + threadNum = -1; + targets = new TargetList(); + deferredTargets = new TargetList(); +} + + +MSHR::TargetList::TargetList() + : needsExclusive(false), hasUpgrade(false) +{} + + +inline void +MSHR::TargetList::add(PacketPtr pkt, Tick readyTime, + Counter order, bool cpuSide, bool markPending) +{ + if (cpuSide) { + if (pkt->needsExclusive()) { + needsExclusive = true; + } + + if (pkt->cmd == MemCmd::UpgradeReq) { + hasUpgrade = true; + } + } + + if (markPending) { + MSHR *mshr = dynamic_cast(pkt->senderState); + if (mshr != NULL) { + assert(!mshr->downstreamPending); + mshr->downstreamPending = true; + } + } + + push_back(Target(pkt, readyTime, order, cpuSide, markPending)); +} + + +void +MSHR::TargetList::replaceUpgrades() +{ + if (!hasUpgrade) + return; + + Iterator end_i = end(); + for (Iterator i = begin(); i != end_i; ++i) { + if (i->pkt->cmd == MemCmd::UpgradeReq) { + i->pkt->cmd = MemCmd::ReadExReq; + DPRINTF(Cache, "Replacing UpgradeReq with ReadExReq\n"); + } + } + + hasUpgrade = false; +} + + +void +MSHR::TargetList::clearDownstreamPending() +{ + Iterator end_i = end(); + for (Iterator i = begin(); i != end_i; ++i) { + if (i->markedPending) { + MSHR *mshr = dynamic_cast(i->pkt->senderState); + if (mshr != NULL) { + mshr->clearDownstreamPending(); + } + } + } +} + + +bool +MSHR::TargetList::checkFunctional(PacketPtr pkt) +{ + Iterator end_i = end(); + for (Iterator i = begin(); i != end_i; ++i) { + if (pkt->checkFunctional(i->pkt)) { + return true; + } + } + + return false; +} + + +void +MSHR::TargetList:: +print(std::ostream &os, int verbosity, const std::string &prefix) const +{ + ConstIterator end_i = end(); + for (ConstIterator i = begin(); i != end_i; ++i) { + ccprintf(os, "%s%s: ", prefix, i->isCpuSide() ? "cpu" : "mem"); + i->pkt->print(os, verbosity, ""); + } +} + + +void +MSHR::allocate(Addr _addr, int _size, PacketPtr target, + Tick whenReady, Counter _order) +{ + addr = _addr; + size = _size; + readyTime = whenReady; + order = _order; + assert(target); + isCacheFill = false; + _isUncacheable = target->req->isUncacheable(); + inService = false; + downstreamPending = false; + threadNum = 0; + ntargets = 1; + // Don't know of a case where we would allocate a new MSHR for a + // snoop (mem-side request), so set cpuSide to true here. + assert(targets->isReset()); + targets->add(target, whenReady, _order, true, true); + assert(deferredTargets->isReset()); + pendingInvalidate = false; + pendingShared = false; + data = NULL; +} + + +void +MSHR::clearDownstreamPending() +{ + assert(downstreamPending); + downstreamPending = false; + // recursively clear flag on any MSHRs we will be forwarding + // responses to + targets->clearDownstreamPending(); +} + +bool +MSHR::markInService() +{ + assert(!inService); + if (isSimpleForward()) { + // we just forwarded the request packet & don't expect a + // response, so get rid of it + assert(getNumTargets() == 1); + popTarget(); + return true; + } + inService = true; + if (!downstreamPending) { + // let upstream caches know that the request has made it to a + // level where it's going to get a response + targets->clearDownstreamPending(); + } + return false; +} + + +void +MSHR::deallocate() +{ + assert(targets->empty()); + targets->resetFlags(); + assert(deferredTargets->isReset()); + assert(ntargets == 0); + inService = false; + //allocIter = NULL; + //readyIter = NULL; +} + +/* + * Adds a target to an MSHR + */ +void +MSHR::allocateTarget(PacketPtr pkt, Tick whenReady, Counter _order) +{ + // if there's a request already in service for this MSHR, we will + // have to defer the new target until after the response if any of + // the following are true: + // - there are other targets already deferred + // - there's a pending invalidate to be applied after the response + // comes back (but before this target is processed) + // - the outstanding request is for a non-exclusive block and this + // target requires an exclusive block + if (inService && + (!deferredTargets->empty() || pendingInvalidate || + (!targets->needsExclusive && pkt->needsExclusive()))) { + // need to put on deferred list + deferredTargets->add(pkt, whenReady, _order, true, true); + } else { + // No request outstanding, or still OK to append to + // outstanding request: append to regular target list. Only + // mark pending if current request hasn't been issued yet + // (isn't in service). + targets->add(pkt, whenReady, _order, true, !inService); + } + + ++ntargets; +} + +bool +MSHR::handleSnoop(PacketPtr pkt, Counter _order) +{ + if (!inService || (pkt->isExpressSnoop() && downstreamPending)) { + // Request has not been issued yet, or it's been issued + // locally but is buffered unissued at some downstream cache + // which is forwarding us this snoop. Either way, the packet + // we're snooping logically precedes this MSHR's request, so + // the snoop has no impact on the MSHR, but must be processed + // in the standard way by the cache. The only exception is + // that if we're an L2+ cache buffering an UpgradeReq from a + // higher-level cache, and the snoop is invalidating, then our + // buffered upgrades must be converted to read exclusives, + // since the upper-level cache no longer has a valid copy. + // That is, even though the upper-level cache got out on its + // local bus first, some other invalidating transaction + // reached the global bus before the upgrade did. + if (pkt->needsExclusive()) { + targets->replaceUpgrades(); + deferredTargets->replaceUpgrades(); + } + + return false; + } + + // From here on down, the request issued by this MSHR logically + // precedes the request we're snooping. + + if (pkt->needsExclusive()) { + // snooped request still precedes the re-request we'll have to + // issue for deferred targets, if any... + deferredTargets->replaceUpgrades(); + } + + if (pendingInvalidate) { + // a prior snoop has already appended an invalidation, so + // logically we don't have the block anymore; no need for + // further snooping. + return true; + } + + if (targets->needsExclusive || pkt->needsExclusive()) { + // actual target device (typ. PhysicalMemory) will delete the + // packet on reception, so we need to save a copy here + PacketPtr cp_pkt = new Packet(pkt, true); + targets->add(cp_pkt, curTick, _order, false, + downstreamPending && targets->needsExclusive); + ++ntargets; + + if (targets->needsExclusive) { + // We're awaiting an exclusive copy, so ownership is pending. + // It's up to us to respond once the data arrives. + pkt->assertMemInhibit(); + pkt->setSupplyExclusive(); + } else { + // Someone else may respond before we get around to + // processing this snoop, which means the copied request + // pointer will no longer be valid + cp_pkt->req = NULL; + } + + if (pkt->needsExclusive()) { + // This transaction will take away our pending copy + pendingInvalidate = true; + } + } else { + // Read to a read: no conflict, so no need to record as + // target, but make sure neither reader thinks he's getting an + // exclusive copy + pendingShared = true; + pkt->assertShared(); + } + + return true; +} + + +bool +MSHR::promoteDeferredTargets() +{ + assert(targets->empty()); + if (deferredTargets->empty()) { + return false; + } + + // swap targets & deferredTargets lists + TargetList *tmp = targets; + targets = deferredTargets; + deferredTargets = tmp; + + assert(targets->size() == ntargets); + + // clear deferredTargets flags + deferredTargets->resetFlags(); + + pendingInvalidate = false; + pendingShared = false; + order = targets->front().order; + readyTime = std::max(curTick, targets->front().readyTime); + + return true; +} + + +void +MSHR::handleFill(Packet *pkt, CacheBlk *blk) +{ + if (pendingShared) { + // we snooped another read while this read was in + // service... assert shared line on its behalf + pkt->assertShared(); + } + + if (!pkt->sharedAsserted() && !pendingInvalidate + && deferredTargets->needsExclusive) { + // We got an exclusive response, but we have deferred targets + // which are waiting to request an exclusive copy (not because + // of a pending invalidate). This can happen if the original + // request was for a read-only (non-exclusive) block, but we + // got an exclusive copy anyway because of the E part of the + // MOESI/MESI protocol. Since we got the exclusive copy + // there's no need to defer the targets, so move them up to + // the regular target list. + assert(!targets->needsExclusive); + targets->needsExclusive = true; + // if any of the deferred targets were upper-level cache + // requests marked downstreamPending, need to clear that + assert(!downstreamPending); // not pending here anymore + deferredTargets->clearDownstreamPending(); + // this clears out deferredTargets too + targets->splice(targets->end(), *deferredTargets); + deferredTargets->resetFlags(); + } +} + + +bool +MSHR::checkFunctional(PacketPtr pkt) +{ + // For printing, we treat the MSHR as a whole as single entity. + // For other requests, we iterate over the individual targets + // since that's where the actual data lies. + if (pkt->isPrint()) { + pkt->checkFunctional(this, addr, size, NULL); + return false; + } else { + return (targets->checkFunctional(pkt) || + deferredTargets->checkFunctional(pkt)); + } +} + + +void +MSHR::print(std::ostream &os, int verbosity, const std::string &prefix) const +{ + ccprintf(os, "%s[%x:%x] %s %s %s state: %s %s %s %s\n", + prefix, addr, addr+size-1, + isCacheFill ? "Fill" : "", + needsExclusive() ? "Excl" : "", + _isUncacheable ? "Unc" : "", + inService ? "InSvc" : "", + downstreamPending ? "DwnPend" : "", + pendingInvalidate ? "PendInv" : "", + pendingShared ? "PendShared" : ""); + + ccprintf(os, "%s Targets:\n", prefix); + targets->print(os, verbosity, prefix + " "); + if (!deferredTargets->empty()) { + ccprintf(os, "%s Deferred Targets:\n", prefix); + deferredTargets->print(os, verbosity, prefix + " "); + } +} + +MSHR::~MSHR() +{ +} diff --git a/src/mem/cache/mshr.hh b/src/mem/cache/mshr.hh new file mode 100644 index 000000000..fdb0485cb --- /dev/null +++ b/src/mem/cache/mshr.hh @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2002-2005 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: Erik Hallnor + */ + +/** + * @file + * Miss Status and Handling Register (MSHR) declaration. + */ + +#ifndef __MSHR_HH__ +#define __MSHR_HH__ + +#include + +#include "base/printable.hh" +#include "mem/packet.hh" + +class CacheBlk; +class MSHRQueue; + +/** + * Miss Status and handling Register. This class keeps all the information + * needed to handle a cache miss including a list of target requests. + */ +class MSHR : public Packet::SenderState, public Printable +{ + + public: + + class Target { + public: + Tick recvTime; //!< Time when request was received (for stats) + Tick readyTime; //!< Time when request is ready to be serviced + Counter order; //!< Global order (for memory consistency mgmt) + PacketPtr pkt; //!< Pending request packet. + bool cpuSide; //!< Did request come from cpu side or mem side? + bool markedPending; //!< Did we mark upstream MSHR + //!< as downstreamPending? + + bool isCpuSide() const { return cpuSide; } + + Target(PacketPtr _pkt, Tick _readyTime, Counter _order, + bool _cpuSide, bool _markedPending) + : recvTime(curTick), readyTime(_readyTime), order(_order), + pkt(_pkt), cpuSide(_cpuSide), markedPending(_markedPending) + {} + }; + + class TargetList : public std::list { + /** Target list iterator. */ + typedef std::list::iterator Iterator; + typedef std::list::const_iterator ConstIterator; + + public: + bool needsExclusive; + bool hasUpgrade; + + TargetList(); + void resetFlags() { needsExclusive = hasUpgrade = false; } + bool isReset() { return !needsExclusive && !hasUpgrade; } + void add(PacketPtr pkt, Tick readyTime, Counter order, + bool cpuSide, bool markPending); + void replaceUpgrades(); + void clearDownstreamPending(); + bool checkFunctional(PacketPtr pkt); + void print(std::ostream &os, int verbosity, + const std::string &prefix) const; + }; + + /** A list of MSHRs. */ + typedef std::list List; + /** MSHR list iterator. */ + typedef List::iterator Iterator; + /** MSHR list const_iterator. */ + typedef List::const_iterator ConstIterator; + + /** Pointer to queue containing this MSHR. */ + MSHRQueue *queue; + + /** Cycle when ready to issue */ + Tick readyTime; + + /** Order number assigned by the miss queue. */ + Counter order; + + /** Address of the request. */ + Addr addr; + + /** Size of the request. */ + int size; + + /** True if the request has been sent to the bus. */ + bool inService; + + /** True if we will be putting the returned block in the cache */ + bool isCacheFill; + + /** True if we need to get an exclusive copy of the block. */ + bool needsExclusive() const { return targets->needsExclusive; } + + /** True if the request is uncacheable */ + bool _isUncacheable; + + bool downstreamPending; + + bool pendingInvalidate; + bool pendingShared; + + /** Thread number of the miss. */ + short threadNum; + /** The number of currently allocated targets. */ + short ntargets; + + + /** Data buffer (if needed). Currently used only for pending + * upgrade handling. */ + uint8_t *data; + + /** + * Pointer to this MSHR on the ready list. + * @sa MissQueue, MSHRQueue::readyList + */ + Iterator readyIter; + + /** + * Pointer to this MSHR on the allocated list. + * @sa MissQueue, MSHRQueue::allocatedList + */ + Iterator allocIter; + +private: + /** List of all requests that match the address */ + TargetList *targets; + + TargetList *deferredTargets; + +public: + + bool isUncacheable() { return _isUncacheable; } + + /** + * Allocate a miss to this MSHR. + * @param cmd The requesting command. + * @param addr The address of the miss. + * @param asid The address space id of the miss. + * @param size The number of bytes to request. + * @param pkt The original miss. + */ + void allocate(Addr addr, int size, PacketPtr pkt, + Tick when, Counter _order); + + bool markInService(); + + void clearDownstreamPending(); + + /** + * Mark this MSHR as free. + */ + void deallocate(); + + /** + * Add a request to the list of targets. + * @param target The target. + */ + void allocateTarget(PacketPtr target, Tick when, Counter order); + bool handleSnoop(PacketPtr target, Counter order); + + /** A simple constructor. */ + MSHR(); + /** A simple destructor. */ + ~MSHR(); + + /** + * Returns the current number of allocated targets. + * @return The current number of allocated targets. + */ + int getNumTargets() { return ntargets; } + + /** + * Returns a pointer to the target list. + * @return a pointer to the target list. + */ + TargetList *getTargetList() { return targets; } + + /** + * Returns true if there are targets left. + * @return true if there are targets + */ + bool hasTargets() { return !targets->empty(); } + + /** + * Returns a reference to the first target. + * @return A pointer to the first target. + */ + Target *getTarget() { assert(hasTargets()); return &targets->front(); } + + /** + * Pop first target. + */ + void popTarget() + { + --ntargets; + targets->pop_front(); + } + + bool isSimpleForward() + { + if (getNumTargets() != 1) + return false; + Target *tgt = getTarget(); + return tgt->isCpuSide() && !tgt->pkt->needsResponse(); + } + + bool promoteDeferredTargets(); + + void handleFill(Packet *pkt, CacheBlk *blk); + + bool checkFunctional(PacketPtr pkt); + + /** + * Prints the contents of this MSHR for debugging. + */ + void print(std::ostream &os, + int verbosity = 0, + const std::string &prefix = "") const; +}; + +#endif //__MSHR_HH__ diff --git a/src/mem/cache/mshr_queue.cc b/src/mem/cache/mshr_queue.cc new file mode 100644 index 000000000..71da7e4c1 --- /dev/null +++ b/src/mem/cache/mshr_queue.cc @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2003-2005 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: Erik Hallnor + */ + +/** @file + * Definition of MSHRQueue class functions. + */ + +#include "mem/cache/miss/mshr_queue.hh" + +using namespace std; + +MSHRQueue::MSHRQueue(const std::string &_label, + int num_entries, int reserve, int _index) + : label(_label), + numEntries(num_entries + reserve - 1), numReserve(reserve), + index(_index) +{ + allocated = 0; + inServiceEntries = 0; + registers = new MSHR[numEntries]; + for (int i = 0; i < numEntries; ++i) { + registers[i].queue = this; + freeList.push_back(®isters[i]); + } +} + +MSHRQueue::~MSHRQueue() +{ + delete [] registers; +} + +MSHR * +MSHRQueue::findMatch(Addr addr) const +{ + MSHR::ConstIterator i = allocatedList.begin(); + MSHR::ConstIterator end = allocatedList.end(); + for (; i != end; ++i) { + MSHR *mshr = *i; + if (mshr->addr == addr) { + return mshr; + } + } + return NULL; +} + +bool +MSHRQueue::findMatches(Addr addr, vector& matches) const +{ + // Need an empty vector + assert(matches.empty()); + bool retval = false; + MSHR::ConstIterator i = allocatedList.begin(); + MSHR::ConstIterator end = allocatedList.end(); + for (; i != end; ++i) { + MSHR *mshr = *i; + if (mshr->addr == addr) { + retval = true; + matches.push_back(mshr); + } + } + return retval; +} + + +bool +MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr) +{ + pkt->pushLabel(label); + MSHR::ConstIterator i = allocatedList.begin(); + MSHR::ConstIterator end = allocatedList.end(); + for (; i != end; ++i) { + MSHR *mshr = *i; + if (mshr->addr == blk_addr && mshr->checkFunctional(pkt)) { + pkt->popLabel(); + return true; + } + } + pkt->popLabel(); + return false; +} + + +MSHR * +MSHRQueue::findPending(Addr addr, int size) const +{ + MSHR::ConstIterator i = readyList.begin(); + MSHR::ConstIterator end = readyList.end(); + for (; i != end; ++i) { + MSHR *mshr = *i; + if (mshr->addr < addr) { + if (mshr->addr + mshr->size > addr) { + return mshr; + } + } else { + if (addr + size > mshr->addr) { + return mshr; + } + } + } + return NULL; +} + + +MSHR::Iterator +MSHRQueue::addToReadyList(MSHR *mshr) +{ + if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) { + return readyList.insert(readyList.end(), mshr); + } + + MSHR::Iterator i = readyList.begin(); + MSHR::Iterator end = readyList.end(); + for (; i != end; ++i) { + if ((*i)->readyTime > mshr->readyTime) { + return readyList.insert(i, mshr); + } + } + assert(false); + return end; // keep stupid compilers happy +} + + +MSHR * +MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt, + Tick when, Counter order) +{ + assert(!freeList.empty()); + MSHR *mshr = freeList.front(); + assert(mshr->getNumTargets() == 0); + freeList.pop_front(); + + mshr->allocate(addr, size, pkt, when, order); + mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr); + mshr->readyIter = addToReadyList(mshr); + + allocated += 1; + return mshr; +} + + +void +MSHRQueue::deallocate(MSHR *mshr) +{ + deallocateOne(mshr); +} + +MSHR::Iterator +MSHRQueue::deallocateOne(MSHR *mshr) +{ + MSHR::Iterator retval = allocatedList.erase(mshr->allocIter); + freeList.push_front(mshr); + allocated--; + if (mshr->inService) { + inServiceEntries--; + } else { + readyList.erase(mshr->readyIter); + } + mshr->deallocate(); + return retval; +} + +void +MSHRQueue::moveToFront(MSHR *mshr) +{ + if (!mshr->inService) { + assert(mshr == *(mshr->readyIter)); + readyList.erase(mshr->readyIter); + mshr->readyIter = readyList.insert(readyList.begin(), mshr); + } +} + +void +MSHRQueue::markInService(MSHR *mshr) +{ + if (mshr->markInService()) { + deallocate(mshr); + } else { + readyList.erase(mshr->readyIter); + inServiceEntries += 1; + } +} + +void +MSHRQueue::markPending(MSHR *mshr) +{ + assert(mshr->inService); + mshr->inService = false; + --inServiceEntries; + /** + * @ todo might want to add rerequests to front of pending list for + * performance. + */ + mshr->readyIter = addToReadyList(mshr); +} + +void +MSHRQueue::squash(int threadNum) +{ + MSHR::Iterator i = allocatedList.begin(); + MSHR::Iterator end = allocatedList.end(); + for (; i != end;) { + MSHR *mshr = *i; + if (mshr->threadNum == threadNum) { + while (mshr->hasTargets()) { + mshr->popTarget(); + assert(0/*target->req->getThreadNum()*/ == threadNum); + } + assert(!mshr->hasTargets()); + assert(mshr->ntargets==0); + if (!mshr->inService) { + i = deallocateOne(mshr); + } else { + //mshr->pkt->flags &= ~CACHE_LINE_FILL; + ++i; + } + } else { + ++i; + } + } +} diff --git a/src/mem/cache/mshr_queue.hh b/src/mem/cache/mshr_queue.hh new file mode 100644 index 000000000..e04745087 --- /dev/null +++ b/src/mem/cache/mshr_queue.hh @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2003-2005 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: Erik Hallnor + */ + +/** @file + * Declaration of a structure to manage MSHRs. + */ + +#ifndef __MEM__CACHE__MISS__MSHR_QUEUE_HH__ +#define __MEM__CACHE__MISS__MSHR_QUEUE_HH__ + +#include + +#include "mem/packet.hh" +#include "mem/cache/miss/mshr.hh" + +/** + * A Class for maintaining a list of pending and allocated memory requests. + */ +class MSHRQueue +{ + private: + /** Local label (for functional print requests) */ + const std::string label; + + /** MSHR storage. */ + MSHR *registers; + /** Holds pointers to all allocated entries. */ + MSHR::List allocatedList; + /** Holds pointers to entries that haven't been sent to the bus. */ + MSHR::List readyList; + /** Holds non allocated entries. */ + MSHR::List freeList; + + // Parameters + /** + * The total number of entries in this queue. This number is set as the + * number of entries requested plus (numReserve - 1). This allows for + * the same number of effective entries while still maintaining the reserve. + */ + const int numEntries; + + /** + * The number of entries to hold in reserve. This is needed because copy + * operations can allocate upto 4 entries at one time. + */ + const int numReserve; + + MSHR::Iterator addToReadyList(MSHR *mshr); + + + public: + /** The number of allocated entries. */ + int allocated; + /** The number of entries that have been forwarded to the bus. */ + int inServiceEntries; + /** The index of this queue within the cache (MSHR queue vs. write + * buffer). */ + const int index; + + /** + * Create a queue with a given number of entries. + * @param num_entrys The number of entries in this queue. + * @param reserve The minimum number of entries needed to satisfy + * any access. + */ + MSHRQueue(const std::string &_label, int num_entries, int reserve, + int index); + + /** Destructor */ + ~MSHRQueue(); + + /** + * Find the first MSHR that matches the provided address. + * @param addr The address to find. + * @return Pointer to the matching MSHR, null if not found. + */ + MSHR *findMatch(Addr addr) const; + + /** + * Find and return all the matching entries in the provided vector. + * @param addr The address to find. + * @param matches The vector to return pointers to the matching entries. + * @return True if any matches are found, false otherwise. + * @todo Typedef the vector?? + */ + bool findMatches(Addr addr, std::vector& matches) const; + + /** + * Find any pending requests that overlap the given request. + * @param pkt The request to find. + * @return A pointer to the earliest matching MSHR. + */ + MSHR *findPending(Addr addr, int size) const; + + bool checkFunctional(PacketPtr pkt, Addr blk_addr); + + /** + * Allocates a new MSHR for the request and size. This places the request + * as the first target in the MSHR. + * @param pkt The request to handle. + * @param size The number in bytes to fetch from memory. + * @return The a pointer to the MSHR allocated. + * + * @pre There are free entries. + */ + MSHR *allocate(Addr addr, int size, PacketPtr &pkt, + Tick when, Counter order); + + /** + * Removes the given MSHR from the queue. This places the MSHR on the + * free list. + * @param mshr + */ + void deallocate(MSHR *mshr); + + /** + * Remove a MSHR from the queue. Returns an iterator into the + * allocatedList for faster squash implementation. + * @param mshr The MSHR to remove. + * @return An iterator to the next entry in the allocatedList. + */ + MSHR::Iterator deallocateOne(MSHR *mshr); + + /** + * Moves the MSHR to the front of the pending list if it is not + * in service. + * @param mshr The entry to move. + */ + void moveToFront(MSHR *mshr); + + /** + * Mark the given MSHR as in service. This removes the MSHR from the + * readyList. Deallocates the MSHR if it does not expect a response. + * @param mshr The MSHR to mark in service. + */ + void markInService(MSHR *mshr); + + /** + * Mark an in service entry as pending, used to resend a request. + * @param mshr The MSHR to resend. + */ + void markPending(MSHR *mshr); + + /** + * Squash outstanding requests with the given thread number. If a request + * is in service, just squashes the targets. + * @param threadNum The thread to squash. + */ + void squash(int threadNum); + + /** + * Returns true if the pending list is not empty. + * @return True if there are outstanding requests. + */ + bool havePending() const + { + return !readyList.empty(); + } + + /** + * Returns true if there are no free entries. + * @return True if this queue is full. + */ + bool isFull() const + { + return (allocated > numEntries - numReserve); + } + + /** + * Returns the MSHR at the head of the readyList. + * @return The next request to service. + */ + MSHR *getNextMSHR() const + { + if (readyList.empty() || readyList.front()->readyTime > curTick) { + return NULL; + } + return readyList.front(); + } + + Tick nextMSHRReadyTime() const + { + return readyList.empty() ? MaxTick : readyList.front()->readyTime; + } +}; + +#endif //__MEM__CACHE__MISS__MSHR_QUEUE_HH__ diff --git a/src/mem/cache/prefetch/SConscript b/src/mem/cache/prefetch/SConscript index 8a7f1232c..7314b5ccf 100644 --- a/src/mem/cache/prefetch/SConscript +++ b/src/mem/cache/prefetch/SConscript @@ -30,8 +30,8 @@ Import('*') -Source('base_prefetcher.cc') -Source('ghb_prefetcher.cc') -Source('stride_prefetcher.cc') -Source('tagged_prefetcher.cc') +Source('base.cc') +Source('ghb.cc') +Source('stride.cc') +Source('tagged.cc') diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc new file mode 100644 index 000000000..1af900849 --- /dev/null +++ b/src/mem/cache/prefetch/base.cc @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2005 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: Ron Dreslinski + */ + +/** + * @file + * Hardware Prefetcher Definition. + */ + +#include "base/trace.hh" +#include "mem/cache/base_cache.hh" +#include "mem/cache/prefetch/base_prefetcher.hh" +#include "mem/request.hh" +#include + +BasePrefetcher::BasePrefetcher(const BaseCacheParams *p) + : size(p->prefetcher_size), pageStop(!p->prefetch_past_page), + serialSquash(p->prefetch_serial_squash), + cacheCheckPush(p->prefetch_cache_check_push), + only_data(p->prefetch_data_accesses_only) +{ +} + +void +BasePrefetcher::setCache(BaseCache *_cache) +{ + cache = _cache; + blkSize = cache->getBlockSize(); +} + +void +BasePrefetcher::regStats(const std::string &name) +{ + pfIdentified + .name(name + ".prefetcher.num_hwpf_identified") + .desc("number of hwpf identified") + ; + + pfMSHRHit + .name(name + ".prefetcher.num_hwpf_already_in_mshr") + .desc("number of hwpf that were already in mshr") + ; + + pfCacheHit + .name(name + ".prefetcher.num_hwpf_already_in_cache") + .desc("number of hwpf that were already in the cache") + ; + + pfBufferHit + .name(name + ".prefetcher.num_hwpf_already_in_prefetcher") + .desc("number of hwpf that were already in the prefetch queue") + ; + + pfRemovedFull + .name(name + ".prefetcher.num_hwpf_evicted") + .desc("number of hwpf removed due to no buffer left") + ; + + pfRemovedMSHR + .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit") + .desc("number of hwpf removed because MSHR allocated") + ; + + pfIssued + .name(name + ".prefetcher.num_hwpf_issued") + .desc("number of hwpf issued") + ; + + pfSpanPage + .name(name + ".prefetcher.num_hwpf_span_page") + .desc("number of hwpf spanning a virtual page") + ; + + pfSquashed + .name(name + ".prefetcher.num_hwpf_squashed_from_miss") + .desc("number of hwpf that got squashed due to a miss aborting calculation time") + ; +} + +inline bool +BasePrefetcher::inCache(Addr addr) +{ + if (cache->inCache(addr)) { + pfCacheHit++; + return true; + } + return false; +} + +inline bool +BasePrefetcher::inMissQueue(Addr addr) +{ + if (cache->inMissQueue(addr)) { + pfMSHRHit++; + return true; + } + return false; +} + +PacketPtr +BasePrefetcher::getPacket() +{ + DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name()); + + if (pf.empty()) { + DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name()); + return NULL; + } + + PacketPtr pkt; + bool keepTrying = false; + do { + pkt = *pf.begin(); + pf.pop_front(); + if (!cacheCheckPush) { + keepTrying = cache->inCache(pkt->getAddr()); + } + if (pf.empty()) { + cache->deassertMemSideBusRequest(BaseCache::Request_PF); + if (keepTrying) return NULL; //None left, all were in cache + } + } while (keepTrying); + + pfIssued++; + return pkt; +} + +void +BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) +{ + if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && only_data)) + { + //Calculate the blk address + Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1); + + //Check if miss is in pfq, if so remove it + std::list::iterator iter = inPrefetch(blkAddr); + if (iter != pf.end()) { + DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name()); + pfRemovedMSHR++; + pf.erase(iter); + if (pf.empty()) + cache->deassertMemSideBusRequest(BaseCache::Request_PF); + } + + //Remove anything in queue with delay older than time + //since everything is inserted in time order, start from end + //and work until pf.empty() or time is earlier + //This is done to emulate Aborting the previous work on a new miss + //Needed for serial calculators like GHB + if (serialSquash) { + iter = pf.end(); + iter--; + while (!pf.empty() && ((*iter)->time >= time)) { + pfSquashed++; + pf.pop_back(); + iter--; + } + if (pf.empty()) + cache->deassertMemSideBusRequest(BaseCache::Request_PF); + } + + + std::list addresses; + std::list delays; + calculatePrefetch(pkt, addresses, delays); + + std::list::iterator addr = addresses.begin(); + std::list::iterator delay = delays.begin(); + while (addr != addresses.end()) + { + DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name()); + //temp calc this here... + pfIdentified++; + //create a prefetch memreq + Request * prefetchReq = new Request(*addr, blkSize, 0); + PacketPtr prefetch; + prefetch = new Packet(prefetchReq, MemCmd::HardPFReq, -1); + prefetch->allocate(); + prefetch->req->setThreadContext(pkt->req->getCpuNum(), + pkt->req->getThreadNum()); + + prefetch->time = time + (*delay); //@todo ADD LATENCY HERE + //... initialize + + //Check if it is already in the cache + if (cacheCheckPush) { + if (cache->inCache(prefetch->getAddr())) { + addr++; + delay++; + continue; + } + } + + //Check if it is already in the miss_queue + if (cache->inMissQueue(prefetch->getAddr())) { + addr++; + delay++; + continue; + } + + //Check if it is already in the pf buffer + if (inPrefetch(prefetch->getAddr()) != pf.end()) { + pfBufferHit++; + addr++; + delay++; + continue; + } + + //We just remove the head if we are full + if (pf.size() == size) + { + DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name()); + pfRemovedFull++; + pf.pop_front(); + } + + pf.push_back(prefetch); + + //Make sure to request the bus, with proper delay + cache->requestMemSideBus(BaseCache::Request_PF, prefetch->time); + + //Increment through the list + addr++; + delay++; + } + } +} + +std::list::iterator +BasePrefetcher::inPrefetch(Addr address) +{ + //Guaranteed to only be one match, we always check before inserting + std::list::iterator iter; + for (iter=pf.begin(); iter != pf.end(); iter++) { + if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { + return iter; + } + } + return pf.end(); +} + + diff --git a/src/mem/cache/prefetch/base.hh b/src/mem/cache/prefetch/base.hh new file mode 100644 index 000000000..1515d8a93 --- /dev/null +++ b/src/mem/cache/prefetch/base.hh @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2005 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: Ron Dreslinski + */ + +/** + * @file + * Miss and writeback queue declarations. + */ + +#ifndef __MEM_CACHE_PREFETCH_BASE_PREFETCHER_HH__ +#define __MEM_CACHE_PREFETCH_BASE_PREFETCHER_HH__ + +#include + +#include "base/statistics.hh" +#include "mem/packet.hh" +#include "params/BaseCache.hh" + +class BaseCache; + +class BasePrefetcher +{ + protected: + + /** The Prefetch Queue. */ + std::list pf; + + // PARAMETERS + + /** The number of MSHRs in the Prefetch Queue. */ + const int size; + + /** Pointr to the parent cache. */ + BaseCache* cache; + + /** The block size of the parent cache. */ + int blkSize; + + /** Do we prefetch across page boundaries. */ + bool pageStop; + + /** Do we remove prefetches with later times than a new miss.*/ + bool serialSquash; + + /** Do we check if it is in the cache when inserting into buffer, + or removing.*/ + bool cacheCheckPush; + + /** Do we prefetch on only data reads, or on inst reads as well. */ + bool only_data; + + public: + + Stats::Scalar<> pfIdentified; + Stats::Scalar<> pfMSHRHit; + Stats::Scalar<> pfCacheHit; + Stats::Scalar<> pfBufferHit; + Stats::Scalar<> pfRemovedFull; + Stats::Scalar<> pfRemovedMSHR; + Stats::Scalar<> pfIssued; + Stats::Scalar<> pfSpanPage; + Stats::Scalar<> pfSquashed; + + void regStats(const std::string &name); + + public: + BasePrefetcher(const BaseCacheParams *p); + + virtual ~BasePrefetcher() {} + + void setCache(BaseCache *_cache); + + void handleMiss(PacketPtr &pkt, Tick time); + + bool inCache(Addr addr); + + bool inMissQueue(Addr addr); + + PacketPtr getPacket(); + + bool havePending() + { + return !pf.empty(); + } + + virtual void calculatePrefetch(PacketPtr &pkt, + std::list &addresses, + std::list &delays) = 0; + + std::list::iterator inPrefetch(Addr address); +}; + + +#endif //__MEM_CACHE_PREFETCH_BASE_PREFETCHER_HH__ diff --git a/src/mem/cache/prefetch/base_prefetcher.cc b/src/mem/cache/prefetch/base_prefetcher.cc deleted file mode 100644 index 1af900849..000000000 --- a/src/mem/cache/prefetch/base_prefetcher.cc +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (c) 2005 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: Ron Dreslinski - */ - -/** - * @file - * Hardware Prefetcher Definition. - */ - -#include "base/trace.hh" -#include "mem/cache/base_cache.hh" -#include "mem/cache/prefetch/base_prefetcher.hh" -#include "mem/request.hh" -#include - -BasePrefetcher::BasePrefetcher(const BaseCacheParams *p) - : size(p->prefetcher_size), pageStop(!p->prefetch_past_page), - serialSquash(p->prefetch_serial_squash), - cacheCheckPush(p->prefetch_cache_check_push), - only_data(p->prefetch_data_accesses_only) -{ -} - -void -BasePrefetcher::setCache(BaseCache *_cache) -{ - cache = _cache; - blkSize = cache->getBlockSize(); -} - -void -BasePrefetcher::regStats(const std::string &name) -{ - pfIdentified - .name(name + ".prefetcher.num_hwpf_identified") - .desc("number of hwpf identified") - ; - - pfMSHRHit - .name(name + ".prefetcher.num_hwpf_already_in_mshr") - .desc("number of hwpf that were already in mshr") - ; - - pfCacheHit - .name(name + ".prefetcher.num_hwpf_already_in_cache") - .desc("number of hwpf that were already in the cache") - ; - - pfBufferHit - .name(name + ".prefetcher.num_hwpf_already_in_prefetcher") - .desc("number of hwpf that were already in the prefetch queue") - ; - - pfRemovedFull - .name(name + ".prefetcher.num_hwpf_evicted") - .desc("number of hwpf removed due to no buffer left") - ; - - pfRemovedMSHR - .name(name + ".prefetcher.num_hwpf_removed_MSHR_hit") - .desc("number of hwpf removed because MSHR allocated") - ; - - pfIssued - .name(name + ".prefetcher.num_hwpf_issued") - .desc("number of hwpf issued") - ; - - pfSpanPage - .name(name + ".prefetcher.num_hwpf_span_page") - .desc("number of hwpf spanning a virtual page") - ; - - pfSquashed - .name(name + ".prefetcher.num_hwpf_squashed_from_miss") - .desc("number of hwpf that got squashed due to a miss aborting calculation time") - ; -} - -inline bool -BasePrefetcher::inCache(Addr addr) -{ - if (cache->inCache(addr)) { - pfCacheHit++; - return true; - } - return false; -} - -inline bool -BasePrefetcher::inMissQueue(Addr addr) -{ - if (cache->inMissQueue(addr)) { - pfMSHRHit++; - return true; - } - return false; -} - -PacketPtr -BasePrefetcher::getPacket() -{ - DPRINTF(HWPrefetch, "%s:Requesting a hw_pf to issue\n", cache->name()); - - if (pf.empty()) { - DPRINTF(HWPrefetch, "%s:No HW_PF found\n", cache->name()); - return NULL; - } - - PacketPtr pkt; - bool keepTrying = false; - do { - pkt = *pf.begin(); - pf.pop_front(); - if (!cacheCheckPush) { - keepTrying = cache->inCache(pkt->getAddr()); - } - if (pf.empty()) { - cache->deassertMemSideBusRequest(BaseCache::Request_PF); - if (keepTrying) return NULL; //None left, all were in cache - } - } while (keepTrying); - - pfIssued++; - return pkt; -} - -void -BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time) -{ - if (!pkt->req->isUncacheable() && !(pkt->req->isInstRead() && only_data)) - { - //Calculate the blk address - Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1); - - //Check if miss is in pfq, if so remove it - std::list::iterator iter = inPrefetch(blkAddr); - if (iter != pf.end()) { - DPRINTF(HWPrefetch, "%s:Saw a miss to a queued prefetch, removing it\n", cache->name()); - pfRemovedMSHR++; - pf.erase(iter); - if (pf.empty()) - cache->deassertMemSideBusRequest(BaseCache::Request_PF); - } - - //Remove anything in queue with delay older than time - //since everything is inserted in time order, start from end - //and work until pf.empty() or time is earlier - //This is done to emulate Aborting the previous work on a new miss - //Needed for serial calculators like GHB - if (serialSquash) { - iter = pf.end(); - iter--; - while (!pf.empty() && ((*iter)->time >= time)) { - pfSquashed++; - pf.pop_back(); - iter--; - } - if (pf.empty()) - cache->deassertMemSideBusRequest(BaseCache::Request_PF); - } - - - std::list addresses; - std::list delays; - calculatePrefetch(pkt, addresses, delays); - - std::list::iterator addr = addresses.begin(); - std::list::iterator delay = delays.begin(); - while (addr != addresses.end()) - { - DPRINTF(HWPrefetch, "%s:Found a pf canidate, inserting into prefetch queue\n", cache->name()); - //temp calc this here... - pfIdentified++; - //create a prefetch memreq - Request * prefetchReq = new Request(*addr, blkSize, 0); - PacketPtr prefetch; - prefetch = new Packet(prefetchReq, MemCmd::HardPFReq, -1); - prefetch->allocate(); - prefetch->req->setThreadContext(pkt->req->getCpuNum(), - pkt->req->getThreadNum()); - - prefetch->time = time + (*delay); //@todo ADD LATENCY HERE - //... initialize - - //Check if it is already in the cache - if (cacheCheckPush) { - if (cache->inCache(prefetch->getAddr())) { - addr++; - delay++; - continue; - } - } - - //Check if it is already in the miss_queue - if (cache->inMissQueue(prefetch->getAddr())) { - addr++; - delay++; - continue; - } - - //Check if it is already in the pf buffer - if (inPrefetch(prefetch->getAddr()) != pf.end()) { - pfBufferHit++; - addr++; - delay++; - continue; - } - - //We just remove the head if we are full - if (pf.size() == size) - { - DPRINTF(HWPrefetch, "%s:Inserting into prefetch queue, it was full removing oldest\n", cache->name()); - pfRemovedFull++; - pf.pop_front(); - } - - pf.push_back(prefetch); - - //Make sure to request the bus, with proper delay - cache->requestMemSideBus(BaseCache::Request_PF, prefetch->time); - - //Increment through the list - addr++; - delay++; - } - } -} - -std::list::iterator -BasePrefetcher::inPrefetch(Addr address) -{ - //Guaranteed to only be one match, we always check before inserting - std::list::iterator iter; - for (iter=pf.begin(); iter != pf.end(); iter++) { - if (((*iter)->getAddr() & ~(Addr)(blkSize-1)) == address) { - return iter; - } - } - return pf.end(); -} - - diff --git a/src/mem/cache/prefetch/base_prefetcher.hh b/src/mem/cache/prefetch/base_prefetcher.hh deleted file mode 100644 index 1515d8a93..000000000 --- a/src/mem/cache/prefetch/base_prefetcher.hh +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2005 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: Ron Dreslinski - */ - -/** - * @file - * Miss and writeback queue declarations. - */ - -#ifndef __MEM_CACHE_PREFETCH_BASE_PREFETCHER_HH__ -#define __MEM_CACHE_PREFETCH_BASE_PREFETCHER_HH__ - -#include - -#include "base/statistics.hh" -#include "mem/packet.hh" -#include "params/BaseCache.hh" - -class BaseCache; - -class BasePrefetcher -{ - protected: - - /** The Prefetch Queue. */ - std::list pf; - - // PARAMETERS - - /** The number of MSHRs in the Prefetch Queue. */ - const int size; - - /** Pointr to the parent cache. */ - BaseCache* cache; - - /** The block size of the parent cache. */ - int blkSize; - - /** Do we prefetch across page boundaries. */ - bool pageStop; - - /** Do we remove prefetches with later times than a new miss.*/ - bool serialSquash; - - /** Do we check if it is in the cache when inserting into buffer, - or removing.*/ - bool cacheCheckPush; - - /** Do we prefetch on only data reads, or on inst reads as well. */ - bool only_data; - - public: - - Stats::Scalar<> pfIdentified; - Stats::Scalar<> pfMSHRHit; - Stats::Scalar<> pfCacheHit; - Stats::Scalar<> pfBufferHit; - Stats::Scalar<> pfRemovedFull; - Stats::Scalar<> pfRemovedMSHR; - Stats::Scalar<> pfIssued; - Stats::Scalar<> pfSpanPage; - Stats::Scalar<> pfSquashed; - - void regStats(const std::string &name); - - public: - BasePrefetcher(const BaseCacheParams *p); - - virtual ~BasePrefetcher() {} - - void setCache(BaseCache *_cache); - - void handleMiss(PacketPtr &pkt, Tick time); - - bool inCache(Addr addr); - - bool inMissQueue(Addr addr); - - PacketPtr getPacket(); - - bool havePending() - { - return !pf.empty(); - } - - virtual void calculatePrefetch(PacketPtr &pkt, - std::list &addresses, - std::list &delays) = 0; - - std::list::iterator inPrefetch(Addr address); -}; - - -#endif //__MEM_CACHE_PREFETCH_BASE_PREFETCHER_HH__ diff --git a/src/mem/cache/prefetch/ghb.cc b/src/mem/cache/prefetch/ghb.cc new file mode 100644 index 000000000..d7d819a2d --- /dev/null +++ b/src/mem/cache/prefetch/ghb.cc @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2005 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: Ron Dreslinski + * Steve Reinhardt + */ + +/** + * @file + * GHB Prefetcher implementation. + */ + +#include "mem/cache/prefetch/ghb_prefetcher.hh" +#include "arch/isa_traits.hh" + +void +GHBPrefetcher::calculatePrefetch(PacketPtr &pkt, std::list &addresses, + std::list &delays) +{ + Addr blkAddr = pkt->getAddr() & ~(Addr)(this->blkSize-1); + int cpuID = pkt->req->getCpuNum(); + if (!useCPUId) cpuID = 0; + + + int new_stride = blkAddr - last_miss_addr[cpuID]; + int old_stride = last_miss_addr[cpuID] - + second_last_miss_addr[cpuID]; + + second_last_miss_addr[cpuID] = last_miss_addr[cpuID]; + last_miss_addr[cpuID] = blkAddr; + + if (new_stride == old_stride) { + for (int d=1; d <= degree; d++) { + Addr newAddr = blkAddr + d * new_stride; + if (this->pageStop && + (blkAddr & ~(TheISA::VMPageSize - 1)) != + (newAddr & ~(TheISA::VMPageSize - 1))) + { + //Spanned the page, so now stop + this->pfSpanPage += degree - d + 1; + return; + } + else + { + addresses.push_back(newAddr); + delays.push_back(latency); + } + } + } +} diff --git a/src/mem/cache/prefetch/ghb.hh b/src/mem/cache/prefetch/ghb.hh new file mode 100644 index 000000000..c44e9c456 --- /dev/null +++ b/src/mem/cache/prefetch/ghb.hh @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2005 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: Ron Dreslinski + */ + +/** + * @file + * Describes a ghb prefetcher. + */ + +#ifndef __MEM_CACHE_PREFETCH_GHB_PREFETCHER_HH__ +#define __MEM_CACHE_PREFETCH_GHB_PREFETCHER_HH__ + +#include "mem/cache/prefetch/base_prefetcher.hh" + +class GHBPrefetcher : public BasePrefetcher +{ + protected: + + Addr second_last_miss_addr[64/*MAX_CPUS*/]; + Addr last_miss_addr[64/*MAX_CPUS*/]; + + Tick latency; + int degree; + bool useCPUId; + + public: + + GHBPrefetcher(const BaseCacheParams *p) + : BasePrefetcher(p), latency(p->prefetch_latency), + degree(p->prefetch_degree), useCPUId(p->prefetch_use_cpu_id) + { + } + + ~GHBPrefetcher() {} + + void calculatePrefetch(PacketPtr &pkt, std::list &addresses, + std::list &delays); +}; + +#endif // __MEM_CACHE_PREFETCH_GHB_PREFETCHER_HH__ diff --git a/src/mem/cache/prefetch/ghb_prefetcher.cc b/src/mem/cache/prefetch/ghb_prefetcher.cc deleted file mode 100644 index d7d819a2d..000000000 --- a/src/mem/cache/prefetch/ghb_prefetcher.cc +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2005 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: Ron Dreslinski - * Steve Reinhardt - */ - -/** - * @file - * GHB Prefetcher implementation. - */ - -#include "mem/cache/prefetch/ghb_prefetcher.hh" -#include "arch/isa_traits.hh" - -void -GHBPrefetcher::calculatePrefetch(PacketPtr &pkt, std::list &addresses, - std::list &delays) -{ - Addr blkAddr = pkt->getAddr() & ~(Addr)(this->blkSize-1); - int cpuID = pkt->req->getCpuNum(); - if (!useCPUId) cpuID = 0; - - - int new_stride = blkAddr - last_miss_addr[cpuID]; - int old_stride = last_miss_addr[cpuID] - - second_last_miss_addr[cpuID]; - - second_last_miss_addr[cpuID] = last_miss_addr[cpuID]; - last_miss_addr[cpuID] = blkAddr; - - if (new_stride == old_stride) { - for (int d=1; d <= degree; d++) { - Addr newAddr = blkAddr + d * new_stride; - if (this->pageStop && - (blkAddr & ~(TheISA::VMPageSize - 1)) != - (newAddr & ~(TheISA::VMPageSize - 1))) - { - //Spanned the page, so now stop - this->pfSpanPage += degree - d + 1; - return; - } - else - { - addresses.push_back(newAddr); - delays.push_back(latency); - } - } - } -} diff --git a/src/mem/cache/prefetch/ghb_prefetcher.hh b/src/mem/cache/prefetch/ghb_prefetcher.hh deleted file mode 100644 index c44e9c456..000000000 --- a/src/mem/cache/prefetch/ghb_prefetcher.hh +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2005 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: Ron Dreslinski - */ - -/** - * @file - * Describes a ghb prefetcher. - */ - -#ifndef __MEM_CACHE_PREFETCH_GHB_PREFETCHER_HH__ -#define __MEM_CACHE_PREFETCH_GHB_PREFETCHER_HH__ - -#include "mem/cache/prefetch/base_prefetcher.hh" - -class GHBPrefetcher : public BasePrefetcher -{ - protected: - - Addr second_last_miss_addr[64/*MAX_CPUS*/]; - Addr last_miss_addr[64/*MAX_CPUS*/]; - - Tick latency; - int degree; - bool useCPUId; - - public: - - GHBPrefetcher(const BaseCacheParams *p) - : BasePrefetcher(p), latency(p->prefetch_latency), - degree(p->prefetch_degree), useCPUId(p->prefetch_use_cpu_id) - { - } - - ~GHBPrefetcher() {} - - void calculatePrefetch(PacketPtr &pkt, std::list &addresses, - std::list &delays); -}; - -#endif // __MEM_CACHE_PREFETCH_GHB_PREFETCHER_HH__ diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc new file mode 100644 index 000000000..8d957182a --- /dev/null +++ b/src/mem/cache/prefetch/stride.cc @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2005 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: Ron Dreslinski + * Steve Reinhardt + */ + +/** + * @file + * Stride Prefetcher template instantiations. + */ + +#include "mem/cache/prefetch/stride_prefetcher.hh" + +void +StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list &addresses, + std::list &delays) +{ +// Addr blkAddr = pkt->paddr & ~(Addr)(this->blkSize-1); + int cpuID = pkt->req->getCpuNum(); + if (!useCPUId) cpuID = 0; + + /* Scan Table for IAddr Match */ +/* std::list::iterator iter; + for (iter=table[cpuID].begin(); + iter !=table[cpuID].end(); + iter++) { + if ((*iter)->IAddr == pkt->pc) break; + } + + if (iter != table[cpuID].end()) { + //Hit in table + + int newStride = blkAddr - (*iter)->MAddr; + if (newStride == (*iter)->stride) { + (*iter)->confidence++; + } + else { + (*iter)->stride = newStride; + (*iter)->confidence--; + } + + (*iter)->MAddr = blkAddr; + + for (int d=1; d <= degree; d++) { + Addr newAddr = blkAddr + d * newStride; + if (this->pageStop && + (blkAddr & ~(TheISA::VMPageSize - 1)) != + (newAddr & ~(TheISA::VMPageSize - 1))) + { + //Spanned the page, so now stop + this->pfSpanPage += degree - d + 1; + return; + } + else + { + addresses.push_back(newAddr); + delays.push_back(latency); + } + } + } + else { + //Miss in table + //Find lowest confidence and replace + + } +*/ +} diff --git a/src/mem/cache/prefetch/stride.hh b/src/mem/cache/prefetch/stride.hh new file mode 100644 index 000000000..4d5ac2f0d --- /dev/null +++ b/src/mem/cache/prefetch/stride.hh @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2005 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: Ron Dreslinski + */ + +/** + * @file + * Describes a strided prefetcher. + */ + +#ifndef __MEM_CACHE_PREFETCH_STRIDE_PREFETCHER_HH__ +#define __MEM_CACHE_PREFETCH_STRIDE_PREFETCHER_HH__ + +#include "mem/cache/prefetch/base_prefetcher.hh" + +class StridePrefetcher : public BasePrefetcher +{ + protected: + + class strideEntry + { + public: + Addr IAddr; + Addr MAddr; + int stride; + int64_t confidence; + +/* bool operator < (strideEntry a,strideEntry b) + { + if (a.confidence == b.confidence) { + return true; //?????? + } + else return a.confidence < b.confidence; + }*/ + }; + Addr* lastMissAddr[64/*MAX_CPUS*/]; + + std::list table[64/*MAX_CPUS*/]; + Tick latency; + int degree; + bool useCPUId; + + + public: + + StridePrefetcher(const BaseCacheParams *p) + : BasePrefetcher(p), latency(p->prefetch_latency), + degree(p->prefetch_degree), useCPUId(p->prefetch_use_cpu_id) + { + } + + ~StridePrefetcher() {} + + void calculatePrefetch(PacketPtr &pkt, std::list &addresses, + std::list &delays); +}; + +#endif // __MEM_CACHE_PREFETCH_STRIDE_PREFETCHER_HH__ diff --git a/src/mem/cache/prefetch/stride_prefetcher.cc b/src/mem/cache/prefetch/stride_prefetcher.cc deleted file mode 100644 index 8d957182a..000000000 --- a/src/mem/cache/prefetch/stride_prefetcher.cc +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2005 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: Ron Dreslinski - * Steve Reinhardt - */ - -/** - * @file - * Stride Prefetcher template instantiations. - */ - -#include "mem/cache/prefetch/stride_prefetcher.hh" - -void -StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list &addresses, - std::list &delays) -{ -// Addr blkAddr = pkt->paddr & ~(Addr)(this->blkSize-1); - int cpuID = pkt->req->getCpuNum(); - if (!useCPUId) cpuID = 0; - - /* Scan Table for IAddr Match */ -/* std::list::iterator iter; - for (iter=table[cpuID].begin(); - iter !=table[cpuID].end(); - iter++) { - if ((*iter)->IAddr == pkt->pc) break; - } - - if (iter != table[cpuID].end()) { - //Hit in table - - int newStride = blkAddr - (*iter)->MAddr; - if (newStride == (*iter)->stride) { - (*iter)->confidence++; - } - else { - (*iter)->stride = newStride; - (*iter)->confidence--; - } - - (*iter)->MAddr = blkAddr; - - for (int d=1; d <= degree; d++) { - Addr newAddr = blkAddr + d * newStride; - if (this->pageStop && - (blkAddr & ~(TheISA::VMPageSize - 1)) != - (newAddr & ~(TheISA::VMPageSize - 1))) - { - //Spanned the page, so now stop - this->pfSpanPage += degree - d + 1; - return; - } - else - { - addresses.push_back(newAddr); - delays.push_back(latency); - } - } - } - else { - //Miss in table - //Find lowest confidence and replace - - } -*/ -} diff --git a/src/mem/cache/prefetch/stride_prefetcher.hh b/src/mem/cache/prefetch/stride_prefetcher.hh deleted file mode 100644 index 4d5ac2f0d..000000000 --- a/src/mem/cache/prefetch/stride_prefetcher.hh +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2005 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: Ron Dreslinski - */ - -/** - * @file - * Describes a strided prefetcher. - */ - -#ifndef __MEM_CACHE_PREFETCH_STRIDE_PREFETCHER_HH__ -#define __MEM_CACHE_PREFETCH_STRIDE_PREFETCHER_HH__ - -#include "mem/cache/prefetch/base_prefetcher.hh" - -class StridePrefetcher : public BasePrefetcher -{ - protected: - - class strideEntry - { - public: - Addr IAddr; - Addr MAddr; - int stride; - int64_t confidence; - -/* bool operator < (strideEntry a,strideEntry b) - { - if (a.confidence == b.confidence) { - return true; //?????? - } - else return a.confidence < b.confidence; - }*/ - }; - Addr* lastMissAddr[64/*MAX_CPUS*/]; - - std::list table[64/*MAX_CPUS*/]; - Tick latency; - int degree; - bool useCPUId; - - - public: - - StridePrefetcher(const BaseCacheParams *p) - : BasePrefetcher(p), latency(p->prefetch_latency), - degree(p->prefetch_degree), useCPUId(p->prefetch_use_cpu_id) - { - } - - ~StridePrefetcher() {} - - void calculatePrefetch(PacketPtr &pkt, std::list &addresses, - std::list &delays); -}; - -#endif // __MEM_CACHE_PREFETCH_STRIDE_PREFETCHER_HH__ diff --git a/src/mem/cache/prefetch/tagged.cc b/src/mem/cache/prefetch/tagged.cc new file mode 100644 index 000000000..b25cb5054 --- /dev/null +++ b/src/mem/cache/prefetch/tagged.cc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2005 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: Ron Dreslinski + */ + +/** + * @file + * Describes a tagged prefetcher based on template policies. + */ + +#include "arch/isa_traits.hh" +#include "mem/cache/prefetch/tagged_prefetcher.hh" + +TaggedPrefetcher::TaggedPrefetcher(const BaseCacheParams *p) + : BasePrefetcher(p), + latency(p->prefetch_latency), degree(p->prefetch_degree) +{ +} + +void +TaggedPrefetcher:: +calculatePrefetch(PacketPtr &pkt, std::list &addresses, + std::list &delays) +{ + Addr blkAddr = pkt->getAddr() & ~(Addr)(this->blkSize-1); + + for (int d=1; d <= degree; d++) { + Addr newAddr = blkAddr + d*(this->blkSize); + if (this->pageStop && + (blkAddr & ~(TheISA::VMPageSize - 1)) != + (newAddr & ~(TheISA::VMPageSize - 1))) + { + //Spanned the page, so now stop + this->pfSpanPage += degree - d + 1; + return; + } + else + { + addresses.push_back(newAddr); + delays.push_back(latency); + } + } +} + + diff --git a/src/mem/cache/prefetch/tagged.hh b/src/mem/cache/prefetch/tagged.hh new file mode 100644 index 000000000..f3094445f --- /dev/null +++ b/src/mem/cache/prefetch/tagged.hh @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2005 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: Ron Dreslinski + */ + +/** + * @file + * Describes a tagged prefetcher. + */ + +#ifndef __MEM_CACHE_PREFETCH_TAGGED_PREFETCHER_HH__ +#define __MEM_CACHE_PREFETCH_TAGGED_PREFETCHER_HH__ + +#include "mem/cache/prefetch/base_prefetcher.hh" + +class TaggedPrefetcher : public BasePrefetcher +{ + protected: + + Tick latency; + int degree; + + public: + + TaggedPrefetcher(const BaseCacheParams *p); + + ~TaggedPrefetcher() {} + + void calculatePrefetch(PacketPtr &pkt, std::list &addresses, + std::list &delays); +}; + +#endif // __MEM_CACHE_PREFETCH_TAGGED_PREFETCHER_HH__ diff --git a/src/mem/cache/prefetch/tagged_prefetcher.cc b/src/mem/cache/prefetch/tagged_prefetcher.cc deleted file mode 100644 index b25cb5054..000000000 --- a/src/mem/cache/prefetch/tagged_prefetcher.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2005 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: Ron Dreslinski - */ - -/** - * @file - * Describes a tagged prefetcher based on template policies. - */ - -#include "arch/isa_traits.hh" -#include "mem/cache/prefetch/tagged_prefetcher.hh" - -TaggedPrefetcher::TaggedPrefetcher(const BaseCacheParams *p) - : BasePrefetcher(p), - latency(p->prefetch_latency), degree(p->prefetch_degree) -{ -} - -void -TaggedPrefetcher:: -calculatePrefetch(PacketPtr &pkt, std::list &addresses, - std::list &delays) -{ - Addr blkAddr = pkt->getAddr() & ~(Addr)(this->blkSize-1); - - for (int d=1; d <= degree; d++) { - Addr newAddr = blkAddr + d*(this->blkSize); - if (this->pageStop && - (blkAddr & ~(TheISA::VMPageSize - 1)) != - (newAddr & ~(TheISA::VMPageSize - 1))) - { - //Spanned the page, so now stop - this->pfSpanPage += degree - d + 1; - return; - } - else - { - addresses.push_back(newAddr); - delays.push_back(latency); - } - } -} - - diff --git a/src/mem/cache/prefetch/tagged_prefetcher.hh b/src/mem/cache/prefetch/tagged_prefetcher.hh deleted file mode 100644 index f3094445f..000000000 --- a/src/mem/cache/prefetch/tagged_prefetcher.hh +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2005 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: Ron Dreslinski - */ - -/** - * @file - * Describes a tagged prefetcher. - */ - -#ifndef __MEM_CACHE_PREFETCH_TAGGED_PREFETCHER_HH__ -#define __MEM_CACHE_PREFETCH_TAGGED_PREFETCHER_HH__ - -#include "mem/cache/prefetch/base_prefetcher.hh" - -class TaggedPrefetcher : public BasePrefetcher -{ - protected: - - Tick latency; - int degree; - - public: - - TaggedPrefetcher(const BaseCacheParams *p); - - ~TaggedPrefetcher() {} - - void calculatePrefetch(PacketPtr &pkt, std::list &addresses, - std::list &delays); -}; - -#endif // __MEM_CACHE_PREFETCH_TAGGED_PREFETCHER_HH__ diff --git a/src/mem/cache/tags/Repl.py b/src/mem/cache/tags/Repl.py deleted file mode 100644 index b76aa1d6e..000000000 --- a/src/mem/cache/tags/Repl.py +++ /dev/null @@ -1,11 +0,0 @@ -from m5.SimObject import SimObject -from m5.params import * -class Repl(SimObject): - type = 'Repl' - abstract = True - -class GenRepl(Repl): - type = 'GenRepl' - fresh_res = Param.Int("Fresh pool residency time") - num_pools = Param.Int("Number of priority pools") - pool_res = Param.Int("Pool residency time") diff --git a/src/mem/cache/tags/SConscript b/src/mem/cache/tags/SConscript index 18ed8408b..9153d97e7 100644 --- a/src/mem/cache/tags/SConscript +++ b/src/mem/cache/tags/SConscript @@ -30,7 +30,7 @@ Import('*') -Source('base_tags.cc') +Source('base.cc') Source('fa_lru.cc') Source('iic.cc') Source('lru.cc') @@ -38,8 +38,8 @@ Source('split.cc') Source('split_lifo.cc') Source('split_lru.cc') -SimObject('Repl.py') -Source('repl/gen.cc') +SimObject('iic_repl/Repl.py') +Source('iic_repl/gen.cc') TraceFlag('IIC') TraceFlag('IICMore') diff --git a/src/mem/cache/tags/base.cc b/src/mem/cache/tags/base.cc new file mode 100644 index 000000000..153737300 --- /dev/null +++ b/src/mem/cache/tags/base.cc @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2003-2005 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: Erik Hallnor + * Ron Dreslinski + */ + +/** + * @file + * Definitions of BaseTags. + */ + +#include "mem/cache/tags/base_tags.hh" + +#include "mem/cache/base_cache.hh" +#include "cpu/smt.hh" //maxThreadsPerCPU +#include "sim/sim_exit.hh" + +using namespace std; + +void +BaseTags::setCache(BaseCache *_cache) +{ + cache = _cache; + objName = cache->name(); +} + +void +BaseTags::regStats(const string &name) +{ + using namespace Stats; + replacements + .init(maxThreadsPerCPU) + .name(name + ".replacements") + .desc("number of replacements") + .flags(total) + ; + + tagsInUse + .name(name + ".tagsinuse") + .desc("Cycle average of tags in use") + ; + + totalRefs + .name(name + ".total_refs") + .desc("Total number of references to valid blocks.") + ; + + sampledRefs + .name(name + ".sampled_refs") + .desc("Sample count of references to valid blocks.") + ; + + avgRefs + .name(name + ".avg_refs") + .desc("Average number of references to valid blocks.") + ; + + avgRefs = totalRefs/sampledRefs; + + warmupCycle + .name(name + ".warmup_cycle") + .desc("Cycle when the warmup percentage was hit.") + ; + + registerExitCallback(new BaseTagsCallback(this)); +} diff --git a/src/mem/cache/tags/base.hh b/src/mem/cache/tags/base.hh new file mode 100644 index 000000000..b7b0c7ef0 --- /dev/null +++ b/src/mem/cache/tags/base.hh @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2003-2005 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: Erik Hallnor + * Ron Dreslinski + */ + +/** + * @file + * Declaration of a common base class for cache tagstore objects. + */ + +#ifndef __BASE_TAGS_HH__ +#define __BASE_TAGS_HH__ + +#include +#include "base/statistics.hh" +#include "base/callback.hh" + +class BaseCache; + +/** + * A common base class of Cache tagstore objects. + */ +class BaseTags +{ + protected: + /** Pointer to the parent cache. */ + BaseCache *cache; + + /** Local copy of the parent cache name. Used for DPRINTF. */ + std::string objName; + + /** + * The number of tags that need to be touched to meet the warmup + * percentage. + */ + int warmupBound; + /** Marked true when the cache is warmed up. */ + bool warmedUp; + + // Statistics + /** + * @addtogroup CacheStatistics + * @{ + */ + + /** Number of replacements of valid blocks per thread. */ + Stats::Vector<> replacements; + /** Per cycle average of the number of tags that hold valid data. */ + Stats::Average<> tagsInUse; + + /** The total number of references to a block before it is replaced. */ + Stats::Scalar<> totalRefs; + + /** + * The number of reference counts sampled. This is different from + * replacements because we sample all the valid blocks when the simulator + * exits. + */ + Stats::Scalar<> sampledRefs; + + /** + * Average number of references to a block before is was replaced. + * @todo This should change to an average stat once we have them. + */ + Stats::Formula avgRefs; + + /** The cycle that the warmup percentage was hit. */ + Stats::Scalar<> warmupCycle; + /** + * @} + */ + + public: + + /** + * Destructor. + */ + virtual ~BaseTags() {} + + /** + * Set the parent cache back pointer. Also copies the cache name to + * objName. + * @param _cache Pointer to parent cache. + */ + void setCache(BaseCache *_cache); + + /** + * Return the parent cache name. + * @return the parent cache name. + */ + const std::string &name() const + { + return objName; + } + + /** + * Register local statistics. + * @param name The name to preceed each statistic name. + */ + void regStats(const std::string &name); + + /** + * Average in the reference count for valid blocks when the simulation + * exits. + */ + virtual void cleanupRefs() {} +}; + +class BaseTagsCallback : public Callback +{ + BaseTags *tags; + public: + BaseTagsCallback(BaseTags *t) : tags(t) {} + virtual void process() { tags->cleanupRefs(); }; +}; + +#endif //__BASE_TAGS_HH__ diff --git a/src/mem/cache/tags/base_tags.cc b/src/mem/cache/tags/base_tags.cc deleted file mode 100644 index 153737300..000000000 --- a/src/mem/cache/tags/base_tags.cc +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2003-2005 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: Erik Hallnor - * Ron Dreslinski - */ - -/** - * @file - * Definitions of BaseTags. - */ - -#include "mem/cache/tags/base_tags.hh" - -#include "mem/cache/base_cache.hh" -#include "cpu/smt.hh" //maxThreadsPerCPU -#include "sim/sim_exit.hh" - -using namespace std; - -void -BaseTags::setCache(BaseCache *_cache) -{ - cache = _cache; - objName = cache->name(); -} - -void -BaseTags::regStats(const string &name) -{ - using namespace Stats; - replacements - .init(maxThreadsPerCPU) - .name(name + ".replacements") - .desc("number of replacements") - .flags(total) - ; - - tagsInUse - .name(name + ".tagsinuse") - .desc("Cycle average of tags in use") - ; - - totalRefs - .name(name + ".total_refs") - .desc("Total number of references to valid blocks.") - ; - - sampledRefs - .name(name + ".sampled_refs") - .desc("Sample count of references to valid blocks.") - ; - - avgRefs - .name(name + ".avg_refs") - .desc("Average number of references to valid blocks.") - ; - - avgRefs = totalRefs/sampledRefs; - - warmupCycle - .name(name + ".warmup_cycle") - .desc("Cycle when the warmup percentage was hit.") - ; - - registerExitCallback(new BaseTagsCallback(this)); -} diff --git a/src/mem/cache/tags/base_tags.hh b/src/mem/cache/tags/base_tags.hh deleted file mode 100644 index b7b0c7ef0..000000000 --- a/src/mem/cache/tags/base_tags.hh +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2003-2005 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: Erik Hallnor - * Ron Dreslinski - */ - -/** - * @file - * Declaration of a common base class for cache tagstore objects. - */ - -#ifndef __BASE_TAGS_HH__ -#define __BASE_TAGS_HH__ - -#include -#include "base/statistics.hh" -#include "base/callback.hh" - -class BaseCache; - -/** - * A common base class of Cache tagstore objects. - */ -class BaseTags -{ - protected: - /** Pointer to the parent cache. */ - BaseCache *cache; - - /** Local copy of the parent cache name. Used for DPRINTF. */ - std::string objName; - - /** - * The number of tags that need to be touched to meet the warmup - * percentage. - */ - int warmupBound; - /** Marked true when the cache is warmed up. */ - bool warmedUp; - - // Statistics - /** - * @addtogroup CacheStatistics - * @{ - */ - - /** Number of replacements of valid blocks per thread. */ - Stats::Vector<> replacements; - /** Per cycle average of the number of tags that hold valid data. */ - Stats::Average<> tagsInUse; - - /** The total number of references to a block before it is replaced. */ - Stats::Scalar<> totalRefs; - - /** - * The number of reference counts sampled. This is different from - * replacements because we sample all the valid blocks when the simulator - * exits. - */ - Stats::Scalar<> sampledRefs; - - /** - * Average number of references to a block before is was replaced. - * @todo This should change to an average stat once we have them. - */ - Stats::Formula avgRefs; - - /** The cycle that the warmup percentage was hit. */ - Stats::Scalar<> warmupCycle; - /** - * @} - */ - - public: - - /** - * Destructor. - */ - virtual ~BaseTags() {} - - /** - * Set the parent cache back pointer. Also copies the cache name to - * objName. - * @param _cache Pointer to parent cache. - */ - void setCache(BaseCache *_cache); - - /** - * Return the parent cache name. - * @return the parent cache name. - */ - const std::string &name() const - { - return objName; - } - - /** - * Register local statistics. - * @param name The name to preceed each statistic name. - */ - void regStats(const std::string &name); - - /** - * Average in the reference count for valid blocks when the simulation - * exits. - */ - virtual void cleanupRefs() {} -}; - -class BaseTagsCallback : public Callback -{ - BaseTags *tags; - public: - BaseTagsCallback(BaseTags *t) : tags(t) {} - virtual void process() { tags->cleanupRefs(); }; -}; - -#endif //__BASE_TAGS_HH__ diff --git a/src/mem/cache/tags/iic_repl/Repl.py b/src/mem/cache/tags/iic_repl/Repl.py new file mode 100644 index 000000000..4c333e897 --- /dev/null +++ b/src/mem/cache/tags/iic_repl/Repl.py @@ -0,0 +1,39 @@ +# Copyright (c) 2005-2008 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: Nathan Binkert + +from m5.SimObject import SimObject +from m5.params import * +class Repl(SimObject): + type = 'Repl' + abstract = True + +class GenRepl(Repl): + type = 'GenRepl' + fresh_res = Param.Int("Fresh pool residency time") + num_pools = Param.Int("Number of priority pools") + pool_res = Param.Int("Pool residency time") diff --git a/src/mem/cache/tags/iic_repl/gen.cc b/src/mem/cache/tags/iic_repl/gen.cc new file mode 100644 index 000000000..bc4e6b86a --- /dev/null +++ b/src/mem/cache/tags/iic_repl/gen.cc @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2002-2005 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: Erik Hallnor + * Steve Reinhardt + */ + +/** + * @file + * Definitions of the Generational replacement policy. + */ + +#include + +#include "base/misc.hh" +#include "mem/cache/tags/iic.hh" +#include "mem/cache/tags/repl/gen.hh" +#include "params/GenRepl.hh" +#include "sim/host.hh" + +using namespace std; + +GenRepl::GenRepl(const Params *p) // fix this, should be set by cache + : Repl(p), num_pools(p->num_pools), fresh_res(p->fresh_res), + pool_res(p->pool_res), num_entries(0), num_pool_entries(0), misses(0), + pools(pools = new GenPool[num_pools+1]) +{ +} + +GenRepl::~GenRepl() +{ + delete [] pools; +} + +unsigned long +GenRepl::getRepl() +{ + unsigned long tmp; + GenReplEntry *re; + int i; + int num_seen = 0; + if (!(num_pool_entries>0)) { + fatal("No blks available to replace"); + } + num_entries--; + num_pool_entries--; + for (i = 0; i < num_pools; i++) { + while ((re = pools[i].pop())) { + num_seen++; + // Remove invalidated entries + if (!re->valid) { + delete re; + continue; + } + if (iic->clearRef(re->tag_ptr)) { + pools[(((i+1)== num_pools)? i :i+1)].push(re, misses); + } + else { + tmp = re->tag_ptr; + delete re; + + repl_pool.sample(i); + + return tmp; + } + } + } + fatal("No replacement found"); + return 0xffffffff; +} + +unsigned long * +GenRepl::getNRepl(int n) +{ + unsigned long *tmp; + GenReplEntry *re; + int i; + if (!(num_pool_entries>(n-1))) { + fatal("Not enough blks available to replace"); + } + num_entries -= n; + num_pool_entries -= n; + tmp = new unsigned long[n]; /* array of cache_blk pointers */ + int blk_index = 0; + for (i = 0; i < num_pools && blk_index < n; i++) { + while (blk_index < n && (re = pools[i].pop())) { + // Remove invalidated entries + if (!re->valid) { + delete re; + continue; + } + if (iic->clearRef(re->tag_ptr)) { + pools[(((i+1)== num_pools)? i :i+1)].push(re, misses); + } + else { + tmp[blk_index] = re->tag_ptr; + blk_index++; + delete re; + repl_pool.sample(i); + } + } + } + if (blk_index >= n) + return tmp; + /* search the fresh pool */ + + fatal("No N replacements found"); + return NULL; +} + +void +GenRepl::doAdvance(std::list &demoted) +{ + int i; + int num_seen = 0; + GenReplEntry *re; + misses++; + for (i=0; i pool_res && (re = pools[i].pop())!=NULL) { + if (iic->clearRef(re->tag_ptr)) { + pools[(((i+1)== num_pools)? i :i+1)].push(re, misses); + /** @todo Not really demoted, but use it for now. */ + demoted.push_back(re->tag_ptr); + advance_pool.sample(i); + } + else { + pools[(((i-1)<0)?i:i-1)].push(re, misses); + demoted.push_back(re->tag_ptr); + demote_pool.sample(i); + } + } + num_seen += pools[i].size; + } + while (misses-pools[num_pools].oldest > fresh_res + && (re = pools[num_pools].pop())!=NULL) { + num_pool_entries++; + if (iic->clearRef(re->tag_ptr)) { + pools[num_pools/2].push(re, misses); + /** @todo Not really demoted, but use it for now. */ + demoted.push_back(re->tag_ptr); + advance_pool.sample(num_pools); + } + else { + pools[num_pools/2-1].push(re, misses); + demoted.push_back(re->tag_ptr); + demote_pool.sample(num_pools); + } + } +} + +void* +GenRepl::add(unsigned long tag_index) +{ + GenReplEntry *re = new GenReplEntry; + re->tag_ptr = tag_index; + re->valid = true; + pools[num_pools].push(re, misses); + num_entries++; + return (void*)re; +} + +void +GenRepl::regStats(const string name) +{ + using namespace Stats; + + /** GEN statistics */ + repl_pool + .init(0, 16, 1) + .name(name + ".repl_pool_dist") + .desc("Dist. of Repl. across pools") + .flags(pdf) + ; + + advance_pool + .init(0, 16, 1) + .name(name + ".advance_pool_dist") + .desc("Dist. of Repl. across pools") + .flags(pdf) + ; + + demote_pool + .init(0, 16, 1) + .name(name + ".demote_pool_dist") + .desc("Dist. of Repl. across pools") + .flags(pdf) + ; +} + +int +GenRepl::fixTag(void* _re, unsigned long old_index, unsigned long new_index) +{ + GenReplEntry *re = (GenReplEntry*)_re; + assert(re->valid); + if (re->tag_ptr == old_index) { + re->tag_ptr = new_index; + return 1; + } + fatal("Repl entry: tag ptrs do not match"); + return 0; +} + +bool +GenRepl::findTagPtr(unsigned long index) +{ + for (int i = 0; i < num_pools + 1; ++i) { + list::const_iterator iter = pools[i].entries.begin(); + list::const_iterator end = pools[i].entries.end(); + for (; iter != end; ++iter) { + if ((*iter)->valid && (*iter)->tag_ptr == index) { + return true; + } + } + } + return false; +} + +GenRepl * +GenReplParams::create() +{ + return new GenRepl(this); +} diff --git a/src/mem/cache/tags/iic_repl/gen.hh b/src/mem/cache/tags/iic_repl/gen.hh new file mode 100644 index 000000000..09a8d5995 --- /dev/null +++ b/src/mem/cache/tags/iic_repl/gen.hh @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2002-2005 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: Erik Hallnor + */ + +/** + * @file + * Declarations of generational replacement policy + */ + +#ifndef ___GEN_HH__ +#define __GEN_HH__ + +#include + +#include "base/statistics.hh" +#include "mem/cache/tags/repl/repl.hh" +#include "params/GenRepl.hh" + +/** + * Generational Replacement entry. + */ +class GenReplEntry +{ + public: + /** Valid flag, used to quickly invalidate bogus entries. */ + bool valid; + /** The difference between this entry and the previous in the pool. */ + int delta; + /** Pointer to the corresponding tag in the IIC. */ + unsigned long tag_ptr; +}; + +/** + * Generational replacement pool + */ +class GenPool +{ + public: + /** The time the last entry was added. */ + Tick newest; + /** The time the oldest entry was added. */ + Tick oldest; + /** List of the replacement entries in this pool. */ + std::list entries; + + /** The number of entries in this pool. */ + int size; + + /** + * Simple constructor. + */ + GenPool() { + newest = 0; + oldest = 0; + size = 0; + } + + /** + * Add an entry to this pool. + * @param re The entry to add. + * @param now The current time. + */ + void push(GenReplEntry *re, Tick now) { + ++size; + if (!entries.empty()) { + re->delta = now - newest; + newest = now; + } else { + re->delta = 0; + newest = oldest = now; + } + entries.push_back(re); + } + + /** + * Remove an entry from the pool. + * @return The entry at the front of the list. + */ + GenReplEntry* pop() { + GenReplEntry *tmp = NULL; + if (!entries.empty()) { + --size; + tmp = entries.front(); + entries.pop_front(); + oldest += tmp->delta; + } + return tmp; + } + + /** + * Return the entry at the front of the list. + * @return the entry at the front of the list. + */ + GenReplEntry* top() { + return entries.front(); + } + + /** + * Destructor. + */ + ~GenPool() { + while (!entries.empty()) { + GenReplEntry *tmp = entries.front(); + entries.pop_front(); + delete tmp; + } + } +}; + +/** + * Generational replacement policy for use with the IIC. + * @todo update to use STL and for efficiency + */ +class GenRepl : public Repl +{ + public: + /** The number of pools. */ + int num_pools; + /** The amount of time to stay in the fresh pool. */ + int fresh_res; + /** The amount of time to stay in the normal pools. */ + int pool_res; + /** The maximum number of entries */ + int num_entries; + /** The number of entries currently in the pools. */ + int num_pool_entries; + /** The number of misses. Used as the internal time. */ + Tick misses; + /** The array of pools. */ + GenPool *pools; + + // Statistics + + /** + * @addtogroup CacheStatistics + * @{ + */ + /** The number of replacements from each pool. */ + Stats::Distribution<> repl_pool; + /** The number of advances out of each pool. */ + Stats::Distribution<> advance_pool; + /** The number of demotions from each pool. */ + Stats::Distribution<> demote_pool; + /** + * @} + */ + + typedef GenReplParams Params; + GenRepl(const Params *p); + + /** + * Destructor. + */ + ~GenRepl(); + + /** + * Returns the tag pointer of the cache block to replace. + * @return The tag to replace. + */ + virtual unsigned long getRepl(); + + /** + * Return an array of N tag pointers to replace. + * @param n The number of tag pointer to return. + * @return An array of tag pointers to replace. + */ + virtual unsigned long *getNRepl(int n); + + /** + * Update replacement data + */ + virtual void doAdvance(std::list &demoted); + + /** + * Add a tag to the replacement policy and return a pointer to the + * replacement entry. + * @param tag_index The tag to add. + * @return The replacement entry. + */ + virtual void* add(unsigned long tag_index); + + /** + * Register statistics. + * @param name The name to prepend to statistic descriptions. + */ + virtual void regStats(const std::string name); + + /** + * Update the tag pointer to when the tag moves. + * @param re The replacement entry of the tag. + * @param old_index The old tag pointer. + * @param new_index The new tag pointer. + * @return 1 if successful, 0 otherwise. + */ + virtual int fixTag(void *re, unsigned long old_index, + unsigned long new_index); + + /** + * Remove this entry from the replacement policy. + * @param re The replacement entry to remove + */ + virtual void removeEntry(void *re) + { + ((GenReplEntry*)re)->valid = false; + } + + protected: + /** + * Debug function to verify that there is only one repl entry per tag. + * @param index The tag index to check. + */ + bool findTagPtr(unsigned long index); +}; + +#endif /* __GEN_HH__ */ diff --git a/src/mem/cache/tags/iic_repl/repl.hh b/src/mem/cache/tags/iic_repl/repl.hh new file mode 100644 index 000000000..cdb5ae4b8 --- /dev/null +++ b/src/mem/cache/tags/iic_repl/repl.hh @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2002-2005 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: Erik Hallnor + * Steve Reinhardt + * Nathan Binkert + */ + +/** + * @file + * Declaration of a base replacement policy class. + */ + +#ifndef __REPL_HH__ +#define __REPL_HH__ + +#include +#include + +#include "cpu/smt.hh" +#include "sim/host.hh" +#include "sim/sim_object.hh" + + +class IIC; + +/** + * A pure virtual base class that defines the interface of a replacement + * policy. + */ +class Repl : public SimObject +{ + public: + /** Pointer to the IIC using this policy. */ + IIC *iic; + + Repl (const Params *params) + : SimObject(params) + { + iic = NULL; + } + + /** + * Set the back pointer to the IIC. + * @param iic_ptr Pointer to the IIC. + */ + void setIIC(IIC *iic_ptr) + { + iic = iic_ptr; + } + + /** + * Returns the tag pointer of the cache block to replace. + * @return The tag to replace. + */ + virtual unsigned long getRepl() = 0; + + /** + * Return an array of N tag pointers to replace. + * @param n The number of tag pointer to return. + * @return An array of tag pointers to replace. + */ + virtual unsigned long *getNRepl(int n) = 0; + + /** + * Update replacement data + */ + virtual void doAdvance(std::list &demoted) = 0; + + /** + * Add a tag to the replacement policy and return a pointer to the + * replacement entry. + * @param tag_index The tag to add. + * @return The replacement entry. + */ + virtual void* add(unsigned long tag_index) = 0; + + /** + * Register statistics. + * @param name The name to prepend to statistic descriptions. + */ + virtual void regStats(const std::string name) = 0; + + /** + * Update the tag pointer to when the tag moves. + * @param re The replacement entry of the tag. + * @param old_index The old tag pointer. + * @param new_index The new tag pointer. + * @return 1 if successful, 0 otherwise. + */ + virtual int fixTag(void *re, unsigned long old_index, + unsigned long new_index) = 0; + + /** + * Remove this entry from the replacement policy. + * @param re The replacement entry to remove + */ + virtual void removeEntry(void *re) = 0; +}; + +#endif /* SMT_REPL_HH */ diff --git a/src/mem/cache/tags/repl/gen.cc b/src/mem/cache/tags/repl/gen.cc deleted file mode 100644 index bc4e6b86a..000000000 --- a/src/mem/cache/tags/repl/gen.cc +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2002-2005 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: Erik Hallnor - * Steve Reinhardt - */ - -/** - * @file - * Definitions of the Generational replacement policy. - */ - -#include - -#include "base/misc.hh" -#include "mem/cache/tags/iic.hh" -#include "mem/cache/tags/repl/gen.hh" -#include "params/GenRepl.hh" -#include "sim/host.hh" - -using namespace std; - -GenRepl::GenRepl(const Params *p) // fix this, should be set by cache - : Repl(p), num_pools(p->num_pools), fresh_res(p->fresh_res), - pool_res(p->pool_res), num_entries(0), num_pool_entries(0), misses(0), - pools(pools = new GenPool[num_pools+1]) -{ -} - -GenRepl::~GenRepl() -{ - delete [] pools; -} - -unsigned long -GenRepl::getRepl() -{ - unsigned long tmp; - GenReplEntry *re; - int i; - int num_seen = 0; - if (!(num_pool_entries>0)) { - fatal("No blks available to replace"); - } - num_entries--; - num_pool_entries--; - for (i = 0; i < num_pools; i++) { - while ((re = pools[i].pop())) { - num_seen++; - // Remove invalidated entries - if (!re->valid) { - delete re; - continue; - } - if (iic->clearRef(re->tag_ptr)) { - pools[(((i+1)== num_pools)? i :i+1)].push(re, misses); - } - else { - tmp = re->tag_ptr; - delete re; - - repl_pool.sample(i); - - return tmp; - } - } - } - fatal("No replacement found"); - return 0xffffffff; -} - -unsigned long * -GenRepl::getNRepl(int n) -{ - unsigned long *tmp; - GenReplEntry *re; - int i; - if (!(num_pool_entries>(n-1))) { - fatal("Not enough blks available to replace"); - } - num_entries -= n; - num_pool_entries -= n; - tmp = new unsigned long[n]; /* array of cache_blk pointers */ - int blk_index = 0; - for (i = 0; i < num_pools && blk_index < n; i++) { - while (blk_index < n && (re = pools[i].pop())) { - // Remove invalidated entries - if (!re->valid) { - delete re; - continue; - } - if (iic->clearRef(re->tag_ptr)) { - pools[(((i+1)== num_pools)? i :i+1)].push(re, misses); - } - else { - tmp[blk_index] = re->tag_ptr; - blk_index++; - delete re; - repl_pool.sample(i); - } - } - } - if (blk_index >= n) - return tmp; - /* search the fresh pool */ - - fatal("No N replacements found"); - return NULL; -} - -void -GenRepl::doAdvance(std::list &demoted) -{ - int i; - int num_seen = 0; - GenReplEntry *re; - misses++; - for (i=0; i pool_res && (re = pools[i].pop())!=NULL) { - if (iic->clearRef(re->tag_ptr)) { - pools[(((i+1)== num_pools)? i :i+1)].push(re, misses); - /** @todo Not really demoted, but use it for now. */ - demoted.push_back(re->tag_ptr); - advance_pool.sample(i); - } - else { - pools[(((i-1)<0)?i:i-1)].push(re, misses); - demoted.push_back(re->tag_ptr); - demote_pool.sample(i); - } - } - num_seen += pools[i].size; - } - while (misses-pools[num_pools].oldest > fresh_res - && (re = pools[num_pools].pop())!=NULL) { - num_pool_entries++; - if (iic->clearRef(re->tag_ptr)) { - pools[num_pools/2].push(re, misses); - /** @todo Not really demoted, but use it for now. */ - demoted.push_back(re->tag_ptr); - advance_pool.sample(num_pools); - } - else { - pools[num_pools/2-1].push(re, misses); - demoted.push_back(re->tag_ptr); - demote_pool.sample(num_pools); - } - } -} - -void* -GenRepl::add(unsigned long tag_index) -{ - GenReplEntry *re = new GenReplEntry; - re->tag_ptr = tag_index; - re->valid = true; - pools[num_pools].push(re, misses); - num_entries++; - return (void*)re; -} - -void -GenRepl::regStats(const string name) -{ - using namespace Stats; - - /** GEN statistics */ - repl_pool - .init(0, 16, 1) - .name(name + ".repl_pool_dist") - .desc("Dist. of Repl. across pools") - .flags(pdf) - ; - - advance_pool - .init(0, 16, 1) - .name(name + ".advance_pool_dist") - .desc("Dist. of Repl. across pools") - .flags(pdf) - ; - - demote_pool - .init(0, 16, 1) - .name(name + ".demote_pool_dist") - .desc("Dist. of Repl. across pools") - .flags(pdf) - ; -} - -int -GenRepl::fixTag(void* _re, unsigned long old_index, unsigned long new_index) -{ - GenReplEntry *re = (GenReplEntry*)_re; - assert(re->valid); - if (re->tag_ptr == old_index) { - re->tag_ptr = new_index; - return 1; - } - fatal("Repl entry: tag ptrs do not match"); - return 0; -} - -bool -GenRepl::findTagPtr(unsigned long index) -{ - for (int i = 0; i < num_pools + 1; ++i) { - list::const_iterator iter = pools[i].entries.begin(); - list::const_iterator end = pools[i].entries.end(); - for (; iter != end; ++iter) { - if ((*iter)->valid && (*iter)->tag_ptr == index) { - return true; - } - } - } - return false; -} - -GenRepl * -GenReplParams::create() -{ - return new GenRepl(this); -} diff --git a/src/mem/cache/tags/repl/gen.hh b/src/mem/cache/tags/repl/gen.hh deleted file mode 100644 index 09a8d5995..000000000 --- a/src/mem/cache/tags/repl/gen.hh +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2002-2005 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: Erik Hallnor - */ - -/** - * @file - * Declarations of generational replacement policy - */ - -#ifndef ___GEN_HH__ -#define __GEN_HH__ - -#include - -#include "base/statistics.hh" -#include "mem/cache/tags/repl/repl.hh" -#include "params/GenRepl.hh" - -/** - * Generational Replacement entry. - */ -class GenReplEntry -{ - public: - /** Valid flag, used to quickly invalidate bogus entries. */ - bool valid; - /** The difference between this entry and the previous in the pool. */ - int delta; - /** Pointer to the corresponding tag in the IIC. */ - unsigned long tag_ptr; -}; - -/** - * Generational replacement pool - */ -class GenPool -{ - public: - /** The time the last entry was added. */ - Tick newest; - /** The time the oldest entry was added. */ - Tick oldest; - /** List of the replacement entries in this pool. */ - std::list entries; - - /** The number of entries in this pool. */ - int size; - - /** - * Simple constructor. - */ - GenPool() { - newest = 0; - oldest = 0; - size = 0; - } - - /** - * Add an entry to this pool. - * @param re The entry to add. - * @param now The current time. - */ - void push(GenReplEntry *re, Tick now) { - ++size; - if (!entries.empty()) { - re->delta = now - newest; - newest = now; - } else { - re->delta = 0; - newest = oldest = now; - } - entries.push_back(re); - } - - /** - * Remove an entry from the pool. - * @return The entry at the front of the list. - */ - GenReplEntry* pop() { - GenReplEntry *tmp = NULL; - if (!entries.empty()) { - --size; - tmp = entries.front(); - entries.pop_front(); - oldest += tmp->delta; - } - return tmp; - } - - /** - * Return the entry at the front of the list. - * @return the entry at the front of the list. - */ - GenReplEntry* top() { - return entries.front(); - } - - /** - * Destructor. - */ - ~GenPool() { - while (!entries.empty()) { - GenReplEntry *tmp = entries.front(); - entries.pop_front(); - delete tmp; - } - } -}; - -/** - * Generational replacement policy for use with the IIC. - * @todo update to use STL and for efficiency - */ -class GenRepl : public Repl -{ - public: - /** The number of pools. */ - int num_pools; - /** The amount of time to stay in the fresh pool. */ - int fresh_res; - /** The amount of time to stay in the normal pools. */ - int pool_res; - /** The maximum number of entries */ - int num_entries; - /** The number of entries currently in the pools. */ - int num_pool_entries; - /** The number of misses. Used as the internal time. */ - Tick misses; - /** The array of pools. */ - GenPool *pools; - - // Statistics - - /** - * @addtogroup CacheStatistics - * @{ - */ - /** The number of replacements from each pool. */ - Stats::Distribution<> repl_pool; - /** The number of advances out of each pool. */ - Stats::Distribution<> advance_pool; - /** The number of demotions from each pool. */ - Stats::Distribution<> demote_pool; - /** - * @} - */ - - typedef GenReplParams Params; - GenRepl(const Params *p); - - /** - * Destructor. - */ - ~GenRepl(); - - /** - * Returns the tag pointer of the cache block to replace. - * @return The tag to replace. - */ - virtual unsigned long getRepl(); - - /** - * Return an array of N tag pointers to replace. - * @param n The number of tag pointer to return. - * @return An array of tag pointers to replace. - */ - virtual unsigned long *getNRepl(int n); - - /** - * Update replacement data - */ - virtual void doAdvance(std::list &demoted); - - /** - * Add a tag to the replacement policy and return a pointer to the - * replacement entry. - * @param tag_index The tag to add. - * @return The replacement entry. - */ - virtual void* add(unsigned long tag_index); - - /** - * Register statistics. - * @param name The name to prepend to statistic descriptions. - */ - virtual void regStats(const std::string name); - - /** - * Update the tag pointer to when the tag moves. - * @param re The replacement entry of the tag. - * @param old_index The old tag pointer. - * @param new_index The new tag pointer. - * @return 1 if successful, 0 otherwise. - */ - virtual int fixTag(void *re, unsigned long old_index, - unsigned long new_index); - - /** - * Remove this entry from the replacement policy. - * @param re The replacement entry to remove - */ - virtual void removeEntry(void *re) - { - ((GenReplEntry*)re)->valid = false; - } - - protected: - /** - * Debug function to verify that there is only one repl entry per tag. - * @param index The tag index to check. - */ - bool findTagPtr(unsigned long index); -}; - -#endif /* __GEN_HH__ */ diff --git a/src/mem/cache/tags/repl/repl.hh b/src/mem/cache/tags/repl/repl.hh deleted file mode 100644 index cdb5ae4b8..000000000 --- a/src/mem/cache/tags/repl/repl.hh +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2002-2005 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: Erik Hallnor - * Steve Reinhardt - * Nathan Binkert - */ - -/** - * @file - * Declaration of a base replacement policy class. - */ - -#ifndef __REPL_HH__ -#define __REPL_HH__ - -#include -#include - -#include "cpu/smt.hh" -#include "sim/host.hh" -#include "sim/sim_object.hh" - - -class IIC; - -/** - * A pure virtual base class that defines the interface of a replacement - * policy. - */ -class Repl : public SimObject -{ - public: - /** Pointer to the IIC using this policy. */ - IIC *iic; - - Repl (const Params *params) - : SimObject(params) - { - iic = NULL; - } - - /** - * Set the back pointer to the IIC. - * @param iic_ptr Pointer to the IIC. - */ - void setIIC(IIC *iic_ptr) - { - iic = iic_ptr; - } - - /** - * Returns the tag pointer of the cache block to replace. - * @return The tag to replace. - */ - virtual unsigned long getRepl() = 0; - - /** - * Return an array of N tag pointers to replace. - * @param n The number of tag pointer to return. - * @return An array of tag pointers to replace. - */ - virtual unsigned long *getNRepl(int n) = 0; - - /** - * Update replacement data - */ - virtual void doAdvance(std::list &demoted) = 0; - - /** - * Add a tag to the replacement policy and return a pointer to the - * replacement entry. - * @param tag_index The tag to add. - * @return The replacement entry. - */ - virtual void* add(unsigned long tag_index) = 0; - - /** - * Register statistics. - * @param name The name to prepend to statistic descriptions. - */ - virtual void regStats(const std::string name) = 0; - - /** - * Update the tag pointer to when the tag moves. - * @param re The replacement entry of the tag. - * @param old_index The old tag pointer. - * @param new_index The new tag pointer. - * @return 1 if successful, 0 otherwise. - */ - virtual int fixTag(void *re, unsigned long old_index, - unsigned long new_index) = 0; - - /** - * Remove this entry from the replacement policy. - * @param re The replacement entry to remove - */ - virtual void removeEntry(void *re) = 0; -}; - -#endif /* SMT_REPL_HH */ -- cgit v1.2.3 From 9d7a69c582e87a2d461298fb32345686efe4113f Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Sun, 10 Feb 2008 14:45:25 -0800 Subject: Fix #include lines for renamed cache files. --HG-- extra : convert_revision : b5008115dc5b34958246608757e69a3fa43b85c5 --- src/cpu/memtest/memtest.cc | 3 --- src/cpu/ozone/simple_cpu_builder.cc | 2 +- src/mem/cache/base.cc | 4 ++-- src/mem/cache/base.hh | 2 +- src/mem/cache/blk.cc | 2 +- src/mem/cache/builder.cc | 8 ++++---- src/mem/cache/cache.hh | 6 +++--- src/mem/cache/cache_impl.hh | 6 +++--- src/mem/cache/mshr.cc | 2 +- src/mem/cache/mshr_queue.cc | 2 +- src/mem/cache/mshr_queue.hh | 2 +- src/mem/cache/prefetch/base.cc | 4 ++-- src/mem/cache/prefetch/ghb.cc | 2 +- src/mem/cache/prefetch/ghb.hh | 2 +- src/mem/cache/prefetch/stride.cc | 2 +- src/mem/cache/prefetch/stride.hh | 2 +- src/mem/cache/prefetch/tagged.cc | 2 +- src/mem/cache/prefetch/tagged.hh | 2 +- src/mem/cache/tags/base.cc | 4 ++-- src/mem/cache/tags/fa_lru.hh | 4 ++-- src/mem/cache/tags/iic.cc | 2 +- src/mem/cache/tags/iic.hh | 6 +++--- src/mem/cache/tags/iic_repl/gen.cc | 2 +- src/mem/cache/tags/iic_repl/gen.hh | 2 +- src/mem/cache/tags/lru.cc | 2 +- src/mem/cache/tags/lru.hh | 4 ++-- src/mem/cache/tags/split.cc | 2 +- src/mem/cache/tags/split.hh | 4 ++-- src/mem/cache/tags/split_blk.hh | 2 +- src/mem/cache/tags/split_lifo.cc | 2 +- src/mem/cache/tags/split_lifo.hh | 4 ++-- src/mem/cache/tags/split_lru.cc | 2 +- src/mem/cache/tags/split_lru.hh | 4 ++-- 33 files changed, 49 insertions(+), 52 deletions(-) diff --git a/src/cpu/memtest/memtest.cc b/src/cpu/memtest/memtest.cc index 819b95e70..42889163a 100644 --- a/src/cpu/memtest/memtest.cc +++ b/src/cpu/memtest/memtest.cc @@ -39,12 +39,9 @@ #include "base/misc.hh" #include "base/statistics.hh" #include "cpu/memtest/memtest.hh" -//#include "cpu/simple_thread.hh" -//#include "mem/cache/base_cache.hh" #include "mem/mem_object.hh" #include "mem/port.hh" #include "mem/packet.hh" -//#include "mem/physical.hh" #include "mem/request.hh" #include "sim/sim_events.hh" #include "sim/stats.hh" diff --git a/src/cpu/ozone/simple_cpu_builder.cc b/src/cpu/ozone/simple_cpu_builder.cc index 9cd56fdb4..fa83e2531 100644 --- a/src/cpu/ozone/simple_cpu_builder.cc +++ b/src/cpu/ozone/simple_cpu_builder.cc @@ -35,7 +35,7 @@ #include "cpu/ozone/cpu_impl.hh" #include "cpu/ozone/simple_impl.hh" #include "cpu/ozone/simple_params.hh" -#include "mem/cache/base_cache.hh" +#include "mem/cache/base.hh" #include "sim/SimpleOzoneCPU.hh" #include "sim/process.hh" #include "sim/sim_object.hh" diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc index 9fa9e2d29..ac0d54bf6 100644 --- a/src/mem/cache/base.cc +++ b/src/mem/cache/base.cc @@ -35,8 +35,8 @@ #include "cpu/base.hh" #include "cpu/smt.hh" -#include "mem/cache/base_cache.hh" -#include "mem/cache/miss/mshr.hh" +#include "mem/cache/base.hh" +#include "mem/cache/mshr.hh" using namespace std; diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index 604474524..d97021024 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -47,7 +47,7 @@ #include "base/misc.hh" #include "base/statistics.hh" #include "base/trace.hh" -#include "mem/cache/miss/mshr_queue.hh" +#include "mem/cache/mshr_queue.hh" #include "mem/mem_object.hh" #include "mem/packet.hh" #include "mem/tport.hh" diff --git a/src/mem/cache/blk.cc b/src/mem/cache/blk.cc index d4a2eaee8..4952ed758 100644 --- a/src/mem/cache/blk.cc +++ b/src/mem/cache/blk.cc @@ -27,7 +27,7 @@ */ #include "base/cprintf.hh" -#include "mem/cache/cache_blk.hh" +#include "mem/cache/blk.hh" void CacheBlkPrintWrapper::print(std::ostream &os, int verbosity, diff --git a/src/mem/cache/builder.cc b/src/mem/cache/builder.cc index d67a9c9a4..db900c64c 100644 --- a/src/mem/cache/builder.cc +++ b/src/mem/cache/builder.cc @@ -39,7 +39,7 @@ #include "enums/Prefetch.hh" #include "mem/config/cache.hh" #include "mem/config/prefetch.hh" -#include "mem/cache/base_cache.hh" +#include "mem/cache/base.hh" #include "mem/cache/cache.hh" #include "mem/bus.hh" #include "params/BaseCache.hh" @@ -67,13 +67,13 @@ //Prefetcher Headers #if defined(USE_GHB) -#include "mem/cache/prefetch/ghb_prefetcher.hh" +#include "mem/cache/prefetch/ghb.hh" #endif #if defined(USE_TAGGED) -#include "mem/cache/prefetch/tagged_prefetcher.hh" +#include "mem/cache/prefetch/tagged.hh" #endif #if defined(USE_STRIDED) -#include "mem/cache/prefetch/stride_prefetcher.hh" +#include "mem/cache/prefetch/stride.hh" #endif diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 170ba0cd1..073ce5ecb 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -41,9 +41,9 @@ #include "base/misc.hh" // fatal, panic, and warn -#include "mem/cache/base_cache.hh" -#include "mem/cache/cache_blk.hh" -#include "mem/cache/miss/mshr.hh" +#include "mem/cache/base.hh" +#include "mem/cache/blk.hh" +#include "mem/cache/mshr.hh" #include "sim/eventq.hh" diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index 7a06f9fc7..6e4b50ed9 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -42,9 +42,9 @@ #include "base/range_ops.hh" #include "mem/cache/cache.hh" -#include "mem/cache/cache_blk.hh" -#include "mem/cache/miss/mshr.hh" -#include "mem/cache/prefetch/base_prefetcher.hh" +#include "mem/cache/blk.hh" +#include "mem/cache/mshr.hh" +#include "mem/cache/prefetch/base.hh" #include "sim/sim_exit.hh" // for SimExitEvent diff --git a/src/mem/cache/mshr.cc b/src/mem/cache/mshr.cc index d711ca537..6537f6343 100644 --- a/src/mem/cache/mshr.cc +++ b/src/mem/cache/mshr.cc @@ -39,7 +39,7 @@ #include #include -#include "mem/cache/miss/mshr.hh" +#include "mem/cache/mshr.hh" #include "sim/core.hh" // for curTick #include "sim/host.hh" #include "base/misc.hh" diff --git a/src/mem/cache/mshr_queue.cc b/src/mem/cache/mshr_queue.cc index 71da7e4c1..45331c33d 100644 --- a/src/mem/cache/mshr_queue.cc +++ b/src/mem/cache/mshr_queue.cc @@ -32,7 +32,7 @@ * Definition of MSHRQueue class functions. */ -#include "mem/cache/miss/mshr_queue.hh" +#include "mem/cache/mshr_queue.hh" using namespace std; diff --git a/src/mem/cache/mshr_queue.hh b/src/mem/cache/mshr_queue.hh index e04745087..f481ca471 100644 --- a/src/mem/cache/mshr_queue.hh +++ b/src/mem/cache/mshr_queue.hh @@ -38,7 +38,7 @@ #include #include "mem/packet.hh" -#include "mem/cache/miss/mshr.hh" +#include "mem/cache/mshr.hh" /** * A Class for maintaining a list of pending and allocated memory requests. diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc index 1af900849..fcc02ff28 100644 --- a/src/mem/cache/prefetch/base.cc +++ b/src/mem/cache/prefetch/base.cc @@ -34,8 +34,8 @@ */ #include "base/trace.hh" -#include "mem/cache/base_cache.hh" -#include "mem/cache/prefetch/base_prefetcher.hh" +#include "mem/cache/base.hh" +#include "mem/cache/prefetch/base.hh" #include "mem/request.hh" #include diff --git a/src/mem/cache/prefetch/ghb.cc b/src/mem/cache/prefetch/ghb.cc index d7d819a2d..f5b88e1a6 100644 --- a/src/mem/cache/prefetch/ghb.cc +++ b/src/mem/cache/prefetch/ghb.cc @@ -34,7 +34,7 @@ * GHB Prefetcher implementation. */ -#include "mem/cache/prefetch/ghb_prefetcher.hh" +#include "mem/cache/prefetch/ghb.hh" #include "arch/isa_traits.hh" void diff --git a/src/mem/cache/prefetch/ghb.hh b/src/mem/cache/prefetch/ghb.hh index c44e9c456..4fb692016 100644 --- a/src/mem/cache/prefetch/ghb.hh +++ b/src/mem/cache/prefetch/ghb.hh @@ -36,7 +36,7 @@ #ifndef __MEM_CACHE_PREFETCH_GHB_PREFETCHER_HH__ #define __MEM_CACHE_PREFETCH_GHB_PREFETCHER_HH__ -#include "mem/cache/prefetch/base_prefetcher.hh" +#include "mem/cache/prefetch/base.hh" class GHBPrefetcher : public BasePrefetcher { diff --git a/src/mem/cache/prefetch/stride.cc b/src/mem/cache/prefetch/stride.cc index 8d957182a..b116b66c7 100644 --- a/src/mem/cache/prefetch/stride.cc +++ b/src/mem/cache/prefetch/stride.cc @@ -34,7 +34,7 @@ * Stride Prefetcher template instantiations. */ -#include "mem/cache/prefetch/stride_prefetcher.hh" +#include "mem/cache/prefetch/stride.hh" void StridePrefetcher::calculatePrefetch(PacketPtr &pkt, std::list &addresses, diff --git a/src/mem/cache/prefetch/stride.hh b/src/mem/cache/prefetch/stride.hh index 4d5ac2f0d..f6bdbc424 100644 --- a/src/mem/cache/prefetch/stride.hh +++ b/src/mem/cache/prefetch/stride.hh @@ -36,7 +36,7 @@ #ifndef __MEM_CACHE_PREFETCH_STRIDE_PREFETCHER_HH__ #define __MEM_CACHE_PREFETCH_STRIDE_PREFETCHER_HH__ -#include "mem/cache/prefetch/base_prefetcher.hh" +#include "mem/cache/prefetch/base.hh" class StridePrefetcher : public BasePrefetcher { diff --git a/src/mem/cache/prefetch/tagged.cc b/src/mem/cache/prefetch/tagged.cc index b25cb5054..6afe1c6c2 100644 --- a/src/mem/cache/prefetch/tagged.cc +++ b/src/mem/cache/prefetch/tagged.cc @@ -34,7 +34,7 @@ */ #include "arch/isa_traits.hh" -#include "mem/cache/prefetch/tagged_prefetcher.hh" +#include "mem/cache/prefetch/tagged.hh" TaggedPrefetcher::TaggedPrefetcher(const BaseCacheParams *p) : BasePrefetcher(p), diff --git a/src/mem/cache/prefetch/tagged.hh b/src/mem/cache/prefetch/tagged.hh index f3094445f..78e20083d 100644 --- a/src/mem/cache/prefetch/tagged.hh +++ b/src/mem/cache/prefetch/tagged.hh @@ -36,7 +36,7 @@ #ifndef __MEM_CACHE_PREFETCH_TAGGED_PREFETCHER_HH__ #define __MEM_CACHE_PREFETCH_TAGGED_PREFETCHER_HH__ -#include "mem/cache/prefetch/base_prefetcher.hh" +#include "mem/cache/prefetch/base.hh" class TaggedPrefetcher : public BasePrefetcher { diff --git a/src/mem/cache/tags/base.cc b/src/mem/cache/tags/base.cc index 153737300..e18026a21 100644 --- a/src/mem/cache/tags/base.cc +++ b/src/mem/cache/tags/base.cc @@ -34,9 +34,9 @@ * Definitions of BaseTags. */ -#include "mem/cache/tags/base_tags.hh" +#include "mem/cache/tags/base.hh" -#include "mem/cache/base_cache.hh" +#include "mem/cache/base.hh" #include "cpu/smt.hh" //maxThreadsPerCPU #include "sim/sim_exit.hh" diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh index 8cbc79813..cabcf18b4 100644 --- a/src/mem/cache/tags/fa_lru.hh +++ b/src/mem/cache/tags/fa_lru.hh @@ -38,10 +38,10 @@ #include -#include "mem/cache/cache_blk.hh" +#include "mem/cache/blk.hh" #include "mem/packet.hh" #include "base/hashmap.hh" -#include "mem/cache/tags/base_tags.hh" +#include "mem/cache/tags/base.hh" /** * A fully associative cache block. diff --git a/src/mem/cache/tags/iic.cc b/src/mem/cache/tags/iic.cc index 20babe6bb..2825599f6 100644 --- a/src/mem/cache/tags/iic.cc +++ b/src/mem/cache/tags/iic.cc @@ -39,7 +39,7 @@ #include -#include "mem/cache/base_cache.hh" +#include "mem/cache/base.hh" #include "mem/cache/tags/iic.hh" #include "base/intmath.hh" #include "sim/core.hh" // for curTick diff --git a/src/mem/cache/tags/iic.hh b/src/mem/cache/tags/iic.hh index 082b3d15e..c9d080683 100644 --- a/src/mem/cache/tags/iic.hh +++ b/src/mem/cache/tags/iic.hh @@ -39,11 +39,11 @@ #include #include -#include "mem/cache/cache_blk.hh" -#include "mem/cache/tags/repl/repl.hh" +#include "mem/cache/blk.hh" +#include "mem/cache/tags/iic_repl/repl.hh" #include "mem/packet.hh" #include "base/statistics.hh" -#include "mem/cache/tags/base_tags.hh" +#include "mem/cache/tags/base.hh" class BaseCache; // Forward declaration diff --git a/src/mem/cache/tags/iic_repl/gen.cc b/src/mem/cache/tags/iic_repl/gen.cc index bc4e6b86a..487b227da 100644 --- a/src/mem/cache/tags/iic_repl/gen.cc +++ b/src/mem/cache/tags/iic_repl/gen.cc @@ -38,7 +38,7 @@ #include "base/misc.hh" #include "mem/cache/tags/iic.hh" -#include "mem/cache/tags/repl/gen.hh" +#include "mem/cache/tags/iic_repl/gen.hh" #include "params/GenRepl.hh" #include "sim/host.hh" diff --git a/src/mem/cache/tags/iic_repl/gen.hh b/src/mem/cache/tags/iic_repl/gen.hh index 09a8d5995..22436b384 100644 --- a/src/mem/cache/tags/iic_repl/gen.hh +++ b/src/mem/cache/tags/iic_repl/gen.hh @@ -39,7 +39,7 @@ #include #include "base/statistics.hh" -#include "mem/cache/tags/repl/repl.hh" +#include "mem/cache/tags/iic_repl/repl.hh" #include "params/GenRepl.hh" /** diff --git a/src/mem/cache/tags/lru.cc b/src/mem/cache/tags/lru.cc index 0a8587c20..7f352e9c4 100644 --- a/src/mem/cache/tags/lru.cc +++ b/src/mem/cache/tags/lru.cc @@ -35,7 +35,7 @@ #include -#include "mem/cache/base_cache.hh" +#include "mem/cache/base.hh" #include "base/intmath.hh" #include "mem/cache/tags/lru.hh" #include "sim/core.hh" diff --git a/src/mem/cache/tags/lru.hh b/src/mem/cache/tags/lru.hh index 26038d709..ea5606cde 100644 --- a/src/mem/cache/tags/lru.hh +++ b/src/mem/cache/tags/lru.hh @@ -39,10 +39,10 @@ #include #include -#include "mem/cache/cache_blk.hh" // base class +#include "mem/cache/blk.hh" // base class #include "mem/packet.hh" // for inlined functions #include -#include "mem/cache/tags/base_tags.hh" +#include "mem/cache/tags/base.hh" class BaseCache; diff --git a/src/mem/cache/tags/split.cc b/src/mem/cache/tags/split.cc index ae284766d..0df85cc92 100644 --- a/src/mem/cache/tags/split.cc +++ b/src/mem/cache/tags/split.cc @@ -41,7 +41,7 @@ #include "base/intmath.hh" #include "base/output.hh" #include "base/trace.hh" -#include "mem/cache/base_cache.hh" +#include "mem/cache/base.hh" #include "mem/cache/tags/split.hh" #include "mem/cache/tags/split_lifo.hh" #include "mem/cache/tags/split_lru.hh" diff --git a/src/mem/cache/tags/split.hh b/src/mem/cache/tags/split.hh index ab48ce769..e8954f791 100644 --- a/src/mem/cache/tags/split.hh +++ b/src/mem/cache/tags/split.hh @@ -39,11 +39,11 @@ #include #include -#include "mem/cache/cache_blk.hh" // base class +#include "mem/cache/blk.hh" // base class #include "mem/cache/tags/split_blk.hh" #include "mem/packet.hh" // for inlined functions #include -#include "mem/cache/tags/base_tags.hh" +#include "mem/cache/tags/base.hh" #include "base/hashmap.hh" class BaseCache; diff --git a/src/mem/cache/tags/split_blk.hh b/src/mem/cache/tags/split_blk.hh index f38516180..d2efe08df 100644 --- a/src/mem/cache/tags/split_blk.hh +++ b/src/mem/cache/tags/split_blk.hh @@ -36,7 +36,7 @@ #ifndef __SPLIT_BLK_HH__ #define __SPLIT_BLK_HH__ -#include "mem/cache/cache_blk.hh" // base class +#include "mem/cache/blk.hh" // base class /** * Split cache block. diff --git a/src/mem/cache/tags/split_lifo.cc b/src/mem/cache/tags/split_lifo.cc index 4ee2473a4..3bdc7cae9 100644 --- a/src/mem/cache/tags/split_lifo.cc +++ b/src/mem/cache/tags/split_lifo.cc @@ -35,7 +35,7 @@ #include -#include "mem/cache/base_cache.hh" +#include "mem/cache/base.hh" #include "base/intmath.hh" #include "mem/cache/tags/split_lifo.hh" #include "sim/core.hh" diff --git a/src/mem/cache/tags/split_lifo.hh b/src/mem/cache/tags/split_lifo.hh index 13ccf7ef4..0fd5f5c3c 100644 --- a/src/mem/cache/tags/split_lifo.hh +++ b/src/mem/cache/tags/split_lifo.hh @@ -39,12 +39,12 @@ #include #include -#include "mem/cache/cache_blk.hh" // base class +#include "mem/cache/blk.hh" // base class #include "mem/cache/tags/split_blk.hh" #include "mem/packet.hh" // for inlined functions #include "base/hashmap.hh" #include -#include "mem/cache/tags/base_tags.hh" +#include "mem/cache/tags/base.hh" class BaseCache; diff --git a/src/mem/cache/tags/split_lru.cc b/src/mem/cache/tags/split_lru.cc index 4d271a92a..bcccdcb30 100644 --- a/src/mem/cache/tags/split_lru.cc +++ b/src/mem/cache/tags/split_lru.cc @@ -35,7 +35,7 @@ #include -#include "mem/cache/base_cache.hh" +#include "mem/cache/base.hh" #include "base/intmath.hh" #include "mem/cache/tags/split_lru.hh" #include "sim/core.hh" diff --git a/src/mem/cache/tags/split_lru.hh b/src/mem/cache/tags/split_lru.hh index a708ef740..d41b6efa7 100644 --- a/src/mem/cache/tags/split_lru.hh +++ b/src/mem/cache/tags/split_lru.hh @@ -39,11 +39,11 @@ #include #include -#include "mem/cache/cache_blk.hh" // base class +#include "mem/cache/blk.hh" // base class #include "mem/cache/tags/split_blk.hh" #include "mem/packet.hh" // for inlined functions #include -#include "mem/cache/tags/base_tags.hh" +#include "mem/cache/tags/base.hh" class BaseCache; -- cgit v1.2.3 From d167e2bb971327f030f1a7a71a45b7588a1dd3dc Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Sun, 10 Feb 2008 19:32:12 -0500 Subject: IGbE: Fix a couple of bugs. --HG-- extra : convert_revision : a1f16bd82b6fbd5b6b5dc0f08b9e69858bea86ca --- src/dev/i8254xGBe.cc | 38 ++++++++++++++++++-------------------- src/dev/i8254xGBe.hh | 30 +++++++++++++++--------------- 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 460f6a9fb..3f56ec53a 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -691,7 +691,7 @@ IGbE::RxDescCache::RxDescCache(IGbE *i, const std::string n, int s) { } -bool +void IGbE::RxDescCache::writePacket(EthPacketPtr packet) { // We shouldn't have to deal with any of these yet @@ -707,7 +707,6 @@ IGbE::RxDescCache::writePacket(EthPacketPtr packet) pktDone = false; igbe->dmaWrite(igbe->platform->pciToDma(unusedCache.front()->buf), packet->length, &pktEvent, packet->data); - return true; } void @@ -717,7 +716,6 @@ IGbE::RxDescCache::pktComplete() RxDesc *desc; desc = unusedCache.front(); - uint16_t crcfixup = igbe->regs.rctl.secrc() ? 0 : 4 ; desc->len = htole((uint16_t)(pktPtr->length + crcfixup)); DPRINTF(EthernetDesc, "pktPtr->length: %d stripcrc offset: %d value written: %d %d\n", @@ -938,6 +936,7 @@ IGbE::TxDescCache::pktComplete() DPRINTF(EthernetDesc, "DMA of packet complete\n"); + desc = unusedCache.front(); assert((TxdOp::isLegacy(desc) || TxdOp::isData(desc)) && TxdOp::getLen(desc)); @@ -1215,6 +1214,7 @@ IGbE::txStateMachine() return; } + int size; size = txDescCache.getPacketSize(); if (size > 0 && txFifo.avail() > size) { @@ -1261,6 +1261,7 @@ IGbE::ethRxPkt(EthPacketPtr pkt) postInterrupt(IT_RXO, true); return false; } + return true; } @@ -1290,6 +1291,8 @@ IGbE::rxStateMachine() if (descLeft == 0) { rxDescCache.writeback(0); + DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing" + " writeback and stopping ticking\n"); rxTick = false; } @@ -1342,16 +1345,14 @@ IGbE::rxStateMachine() EthPacketPtr pkt; pkt = rxFifo.front(); - DPRINTF(EthernetSM, "RXS: Writing packet into memory\n"); - if (rxDescCache.writePacket(pkt)) { - DPRINTF(EthernetSM, "RXS: Removing packet from FIFO\n"); - rxFifo.pop(); - DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n"); - rxTick = false; - rxDmaPacket = true; - return; - } + rxDescCache.writePacket(pkt); + DPRINTF(EthernetSM, "RXS: Writing packet into memory\n"); + DPRINTF(EthernetSM, "RXS: Removing packet from FIFO\n"); + rxFifo.pop(); + DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n"); + rxTick = false; + rxDmaPacket = true; } void @@ -1362,10 +1363,8 @@ IGbE::txWire() return; } - if (etherInt->askBusy()) { - // We'll get woken up when the packet ethTxDone() gets called - txFifoTick = false; - } else { + + if (etherInt->sendPacket(txFifo.front())) { if (DTRACE(EthernetSM)) { IpPtr ip(txFifo.front()); if (ip) @@ -1374,13 +1373,12 @@ IGbE::txWire() else DPRINTF(EthernetSM, "Transmitting Non-Ip packet\n"); } - - bool r = etherInt->sendPacket(txFifo.front()); - assert(r); - r += 1; DPRINTF(EthernetSM, "TxFIFO: Successful transmit, bytes available in fifo: %d\n", txFifo.avail()); txFifo.pop(); + } else { + // We'll get woken up when the packet ethTxDone() gets called + txFifoTick = false; } } diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 30aa6430e..9403c87b6 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -282,8 +282,12 @@ class IGbE : public EtherDevice wbOut = max_to_wb; - for (int x = 0; x < wbOut; x++) - memcpy(&wbBuf[x], usedCache[x], sizeof(T)); + for (int x = 0; x < wbOut; x++) { + assert(usedCache.size()); + memcpy(&wbBuf[x], usedCache[0], sizeof(T)); + delete usedCache[0]; + usedCache.pop_front(); + } assert(wbOut); @@ -298,13 +302,17 @@ class IGbE : public EtherDevice { size_t max_to_fetch; + if (curFetching) + return; + if (descTail() >= cachePnt) max_to_fetch = descTail() - cachePnt; else max_to_fetch = descLen() - cachePnt; - max_to_fetch = std::min(max_to_fetch, (size - usedCache.size() - - unusedCache.size())); + size_t free_cache = size - usedCache.size() - unusedCache.size(); + + max_to_fetch = std::min(max_to_fetch, free_cache); DPRINTF(EthernetDesc, "Fetching descriptors head: %d tail: " "%d len: %d cachePnt: %d max_to_fetch: %d descleft: %d\n", @@ -312,7 +320,7 @@ class IGbE : public EtherDevice max_to_fetch, descLeft()); // Nothing to do - if (max_to_fetch == 0 || curFetching) + if (max_to_fetch == 0) return; // So we don't have two descriptor fetches going on at once @@ -322,7 +330,6 @@ class IGbE : public EtherDevice descBase() + cachePnt * sizeof(T), igbe->platform->pciToDma(descBase() + cachePnt * sizeof(T)), curFetching * sizeof(T)); - assert(curFetching); igbe->dmaRead(igbe->platform->pciToDma(descBase() + cachePnt * sizeof(T)), curFetching * sizeof(T), &fetchEvent, (uint8_t*)fetchBuf); @@ -369,11 +376,6 @@ class IGbE : public EtherDevice #ifndef NDEBUG long oldHead = curHead; #endif - for (int x = 0; x < wbOut; x++) { - assert(usedCache.size()); - delete usedCache[0]; - usedCache.pop_front(); - }; curHead += wbOut; wbOut = 0; @@ -523,7 +525,7 @@ class IGbE : public EtherDevice * @param packet ethernet packet to write * @return if the packet could be written (there was a free descriptor) */ - bool writePacket(EthPacketPtr packet); + void writePacket(EthPacketPtr packet); /** Called by event when dma to write packet is completed */ void pktComplete(); @@ -553,9 +555,7 @@ class IGbE : public EtherDevice virtual long descLen() const { return igbe->regs.tdlen() >> 4; } virtual void updateHead(long h) { igbe->regs.tdh(h); } virtual void enableSm(); - virtual void intAfterWb() const { - igbe->postInterrupt(iGbReg::IT_TXDW); - } + virtual void intAfterWb() const { igbe->postInterrupt(iGbReg::IT_TXDW); } virtual void fetchAfterWb() { if (!igbe->txTick && igbe->getState() == SimObject::Running) fetchDescriptors(); -- cgit v1.2.3 From 4c7eb211191055f72c6f157913cb384f47cf4334 Mon Sep 17 00:00:00 2001 From: Nicolas Zea Date: Sun, 10 Feb 2008 19:41:03 -0500 Subject: Bus: Only update port cache when there is an item to update it with. --HG-- extra : convert_revision : 84848fd48bb9e6693a0518c862364142b1969aa8 --- src/mem/bus.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mem/bus.cc b/src/mem/bus.cc index 66b20703f..f47d48d0b 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -307,9 +307,10 @@ Bus::findPort(Addr addr) dest_id = checkPortCache(addr); if (dest_id == -1) { PortIter i = portMap.find(RangeSize(addr,1)); - if (i != portMap.end()) - dest_id = i->second; - updatePortCache(dest_id, i->first.start, i->first.end); + if (i != portMap.end()) { + dest_id = i->second; + updatePortCache(dest_id, i->first.start, i->first.end); + } } // Check if this matches the default range -- cgit v1.2.3