diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2012-01-28 07:24:01 -0800 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2012-01-28 07:24:01 -0800 |
commit | c3d41a2def15cdaf2ac3984315f452dacc6a0884 (patch) | |
tree | 5324ebec3add54b934a841eee901983ac3463a7f /src | |
parent | da2a4acc26ba264c3c4a12495776fd6a1c4fb133 (diff) | |
parent | 4acca8a0536d4445ed25b67edf571ae460446ab9 (diff) | |
download | gem5-c3d41a2def15cdaf2ac3984315f452dacc6a0884.tar.xz |
Merge with the main repo.
--HG--
rename : src/mem/vport.hh => src/mem/fs_translating_port_proxy.hh
rename : src/mem/translating_port.cc => src/mem/se_translating_port_proxy.cc
rename : src/mem/translating_port.hh => src/mem/se_translating_port_proxy.hh
Diffstat (limited to 'src')
185 files changed, 2907 insertions, 2421 deletions
diff --git a/src/arch/alpha/freebsd/system.cc b/src/arch/alpha/freebsd/system.cc index 6c7da711f..81aea8696 100644 --- a/src/arch/alpha/freebsd/system.cc +++ b/src/arch/alpha/freebsd/system.cc @@ -41,9 +41,7 @@ #include "arch/vtophys.hh" #include "base/loader/symtab.hh" #include "cpu/thread_context.hh" -#include "mem/physical.hh" -#include "mem/port.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" #include "sim/byteswap.hh" #define TIMER_FREQUENCY 1193180 @@ -78,8 +76,8 @@ FreebsdAlphaSystem::doCalibrateClocks(ThreadContext *tc) ppc_vaddr = (Addr)tc->readIntReg(17); timer_vaddr = (Addr)tc->readIntReg(18); - virtPort->write(ppc_vaddr, (uint32_t)SimClock::Frequency); - virtPort->write(timer_vaddr, (uint32_t)TIMER_FREQUENCY); + virtProxy->write(ppc_vaddr, (uint32_t)SimClock::Frequency); + virtProxy->write(timer_vaddr, (uint32_t)TIMER_FREQUENCY); } void diff --git a/src/arch/alpha/linux/process.cc b/src/arch/alpha/linux/process.cc index 97df1feca..f4457b389 100644 --- a/src/arch/alpha/linux/process.cc +++ b/src/arch/alpha/linux/process.cc @@ -56,7 +56,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->machine, "alpha"); - name.copyOut(tc->getMemPort()); + name.copyOut(tc->getMemProxy()); return 0; } @@ -78,7 +78,7 @@ osf_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, TypedBufferArg<uint64_t> fpcr(bufPtr); // I don't think this exactly matches the HW FPCR *fpcr = 0; - fpcr.copyOut(tc->getMemPort()); + fpcr.copyOut(tc->getMemProxy()); return 0; } @@ -106,7 +106,7 @@ osf_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, case 14: { // SSI_IEEE_FP_CONTROL TypedBufferArg<uint64_t> fpcr(bufPtr); // I don't think this exactly matches the HW FPCR - fpcr.copyIn(tc->getMemPort()); + fpcr.copyIn(tc->getMemProxy()); DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): " " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr)); return 0; diff --git a/src/arch/alpha/linux/system.cc b/src/arch/alpha/linux/system.cc index e662ef9ce..6f3cf6b32 100644 --- a/src/arch/alpha/linux/system.cc +++ b/src/arch/alpha/linux/system.cc @@ -63,6 +63,17 @@ using namespace Linux; LinuxAlphaSystem::LinuxAlphaSystem(Params *p) : AlphaSystem(p) { +} + +void +LinuxAlphaSystem::initState() +{ + // Moved from the constructor to here since it relies on the + // address map being resolved in the interconnect + + // Call the initialisation of the super class + AlphaSystem::initState(); + Addr addr = 0; /** @@ -77,8 +88,9 @@ LinuxAlphaSystem::LinuxAlphaSystem(Params *p) * Since we aren't using a bootloader, we have to copy the * kernel arguments directly into the kernel's memory. */ - virtPort->writeBlob(CommandLine(), (uint8_t*)params()->boot_osflags.c_str(), - params()->boot_osflags.length()+1); + virtProxy->writeBlob(CommandLine(), + (uint8_t*)params()->boot_osflags.c_str(), + params()->boot_osflags.length()+1); /** * find the address of the est_cycle_freq variable and insert it @@ -86,8 +98,8 @@ LinuxAlphaSystem::LinuxAlphaSystem(Params *p) * calculated it by using the PIT, RTC, etc. */ if (kernelSymtab->findAddress("est_cycle_freq", addr)) - virtPort->write(addr, (uint64_t)(SimClock::Frequency / - p->boot_cpu_frequency)); + virtProxy->write(addr, (uint64_t)(SimClock::Frequency / + params()->boot_cpu_frequency)); /** @@ -97,7 +109,7 @@ LinuxAlphaSystem::LinuxAlphaSystem(Params *p) * 255 ASNs. */ if (kernelSymtab->findAddress("dp264_mv", addr)) - virtPort->write(addr + 0x18, LittleEndianGuest::htog((uint32_t)127)); + virtProxy->write(addr + 0x18, LittleEndianGuest::htog((uint32_t)127)); else panic("could not find dp264_mv\n"); @@ -164,9 +176,9 @@ LinuxAlphaSystem::setDelayLoop(ThreadContext *tc) if (kernelSymtab->findAddress("loops_per_jiffy", addr)) { Tick cpuFreq = tc->getCpuPtr()->frequency(); assert(intrFreq); - VirtualPort *vp; + FSTranslatingPortProxy* vp; - vp = tc->getVirtPort(); + vp = tc->getVirtProxy(); vp->writeHtoG(addr, (uint32_t)((cpuFreq / intrFreq) * 0.9988)); } } diff --git a/src/arch/alpha/linux/system.hh b/src/arch/alpha/linux/system.hh index 3e4de7b2a..5436a27b2 100644 --- a/src/arch/alpha/linux/system.hh +++ b/src/arch/alpha/linux/system.hh @@ -128,7 +128,14 @@ class LinuxAlphaSystem : public AlphaSystem LinuxAlphaSystem(Params *p); ~LinuxAlphaSystem(); + /** + * Initialise the system + */ + virtual void initState(); + void setDelayLoop(ThreadContext *tc); + + const Params *params() const { return (const Params *)_params; } }; #endif // __ARCH_ALPHA_LINUX_SYSTEM_HH__ diff --git a/src/arch/alpha/linux/threadinfo.hh b/src/arch/alpha/linux/threadinfo.hh index 6144cb773..262da9007 100644 --- a/src/arch/alpha/linux/threadinfo.hh +++ b/src/arch/alpha/linux/threadinfo.hh @@ -78,7 +78,7 @@ class ThreadInfo if (!addr) addr = tc->readMiscRegNoEffect(AlphaISA::IPR_PALtemp23); - FunctionalPort *p = tc->getPhysPort(); + PortProxy* p = tc->getPhysProxy(); p->readBlob(addr, (uint8_t *)&sp, sizeof(Addr)); return sp & ~ULL(0x3fff); diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc index 4b285e7ec..aaf9ecb3c 100644 --- a/src/arch/alpha/remote_gdb.cc +++ b/src/arch/alpha/remote_gdb.cc @@ -188,7 +188,7 @@ RemoteGDB::acc(Addr va, size_t len) Addr ptbr = context->readMiscRegNoEffect(IPR_PALtemp20); PageTableEntry pte = - kernel_pte_lookup(context->getPhysPort(), ptbr, va); + kernel_pte_lookup(context->getPhysProxy(), ptbr, va); if (!pte.valid()) { DPRINTF(GDBAcc, "acc: %#x pte is invalid\n", va); return false; @@ -312,3 +312,11 @@ RemoteGDB::write(Addr vaddr, size_t size, const char *data) } } + +bool +RemoteGDB::insertHardBreak(Addr addr, size_t len) +{ + warn_once("Breakpoints do not work in Alpha PAL mode.\n" + " See PCEventQueue::doService() in cpu/pc_event.cc.\n"); + return BaseRemoteGDB::insertHardBreak(addr, len); +} diff --git a/src/arch/alpha/remote_gdb.hh b/src/arch/alpha/remote_gdb.hh index b7aef5f64..7223fea55 100644 --- a/src/arch/alpha/remote_gdb.hh +++ b/src/arch/alpha/remote_gdb.hh @@ -63,6 +63,8 @@ class RemoteGDB : public BaseRemoteGDB bool acc(Addr addr, size_t len); bool write(Addr addr, size_t size, const char *data); + virtual bool insertHardBreak(Addr addr, size_t len); + public: RemoteGDB(System *system, ThreadContext *context); }; diff --git a/src/arch/alpha/stacktrace.cc b/src/arch/alpha/stacktrace.cc index 9744d56d1..e83827630 100644 --- a/src/arch/alpha/stacktrace.cc +++ b/src/arch/alpha/stacktrace.cc @@ -37,7 +37,7 @@ #include "base/trace.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" #include "sim/system.hh" using namespace std; @@ -48,7 +48,7 @@ ProcessInfo::ProcessInfo(ThreadContext *_tc) : tc(_tc) { Addr addr = 0; - VirtualPort *vp = tc->getVirtPort(); + FSTranslatingPortProxy* vp = tc->getVirtProxy(); SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; if (!symtab->findAddress("thread_info_size", addr)) @@ -81,9 +81,9 @@ ProcessInfo::task(Addr ksp) const Addr tsk; - VirtualPort *vp; + FSTranslatingPortProxy* vp; - vp = tc->getVirtPort(); + vp = tc->getVirtProxy(); tsk = vp->readGtoH<Addr>(base + task_off); return tsk; @@ -98,9 +98,9 @@ ProcessInfo::pid(Addr ksp) const uint16_t pd; - VirtualPort *vp; + FSTranslatingPortProxy* vp; - vp = tc->getVirtPort(); + vp = tc->getVirtProxy(); pd = vp->readGtoH<uint16_t>(task + pid_off); return pd; diff --git a/src/arch/alpha/system.cc b/src/arch/alpha/system.cc index f1afda76e..656ab4d6f 100644 --- a/src/arch/alpha/system.cc +++ b/src/arch/alpha/system.cc @@ -38,8 +38,7 @@ #include "base/loader/symtab.hh" #include "base/trace.hh" #include "debug/Loader.hh" -#include "mem/physical.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" #include "params/AlphaSystem.hh" #include "sim/byteswap.hh" @@ -64,11 +63,30 @@ AlphaSystem::AlphaSystem(Params *p) pal = createObjectFile(params()->pal); if (pal == NULL) fatal("Could not load PALcode file %s", params()->pal); +} + +AlphaSystem::~AlphaSystem() +{ + delete consoleSymtab; + delete console; + delete pal; +#ifdef DEBUG + delete consolePanicEvent; +#endif +} + +void +AlphaSystem::initState() +{ + // Moved from the constructor to here since it relies on the + // address map being resolved in the interconnect + // Call the initialisation of the super class + System::initState(); // Load program sections into memory - pal->loadSections(functionalPort, loadAddrMask); - console->loadSections(functionalPort, loadAddrMask); + pal->loadSections(physProxy, loadAddrMask); + console->loadSections(physProxy, loadAddrMask); // load symbols if (!console->loadGlobalSymbols(consoleSymtab)) @@ -101,8 +119,8 @@ AlphaSystem::AlphaSystem(Params *p) * others do.) */ if (consoleSymtab->findAddress("env_booted_osflags", addr)) { - virtPort->writeBlob(addr, (uint8_t*)params()->boot_osflags.c_str(), - strlen(params()->boot_osflags.c_str())); + virtProxy->writeBlob(addr, (uint8_t*)params()->boot_osflags.c_str(), + strlen(params()->boot_osflags.c_str())); } /** @@ -112,23 +130,13 @@ AlphaSystem::AlphaSystem(Params *p) if (consoleSymtab->findAddress("m5_rpb", addr)) { uint64_t data; data = htog(params()->system_type); - virtPort->write(addr+0x50, data); + virtProxy->write(addr+0x50, data); data = htog(params()->system_rev); - virtPort->write(addr+0x58, data); + virtProxy->write(addr+0x58, data); } else panic("could not find hwrpb\n"); } -AlphaSystem::~AlphaSystem() -{ - delete consoleSymtab; - delete console; - delete pal; -#ifdef DEBUG - delete consolePanicEvent; -#endif -} - /** * This function fixes up addresses that are used to match PCs for * hooking simulator events on to target function executions. @@ -170,8 +178,8 @@ AlphaSystem::fixFuncEventAddr(Addr addr) // lda gp,Y(gp): opcode 8, Ra = 29, rb = 29 const uint32_t gp_lda_pattern = (8 << 26) | (29 << 21) | (29 << 16); - uint32_t i1 = virtPort->read<uint32_t>(addr); - uint32_t i2 = virtPort->read<uint32_t>(addr + sizeof(MachInst)); + uint32_t i1 = virtProxy->read<uint32_t>(addr); + uint32_t i2 = virtProxy->read<uint32_t>(addr + sizeof(MachInst)); if ((i1 & inst_mask) == gp_ldah_pattern && (i2 & inst_mask) == gp_lda_pattern) { @@ -188,7 +196,7 @@ AlphaSystem::setAlphaAccess(Addr access) { Addr addr = 0; if (consoleSymtab->findAddress("m5AlphaAccess", addr)) { - virtPort->write(addr, htog(Phys2K0Seg(access))); + virtProxy->write(addr, htog(Phys2K0Seg(access))); } else { panic("could not find m5AlphaAccess\n"); } diff --git a/src/arch/alpha/system.hh b/src/arch/alpha/system.hh index a74aa206f..0e809cb94 100644 --- a/src/arch/alpha/system.hh +++ b/src/arch/alpha/system.hh @@ -50,6 +50,12 @@ class AlphaSystem : public System ~AlphaSystem(); public: + + /** + * Initialise the state of the system. + */ + virtual void initState(); + /** * Serialization stuff */ diff --git a/src/arch/alpha/tru64/process.cc b/src/arch/alpha/tru64/process.cc index 96fe2725f..071428d5e 100644 --- a/src/arch/alpha/tru64/process.cc +++ b/src/arch/alpha/tru64/process.cc @@ -55,7 +55,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, strcpy(name->version, "732"); strcpy(name->machine, "alpha"); - name.copyOut(tc->getMemPort()); + name.copyOut(tc->getMemProxy()); return 0; } @@ -74,21 +74,21 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, case AlphaTru64::GSI_MAX_CPU: { TypedBufferArg<uint32_t> max_cpu(bufPtr); *max_cpu = htog((uint32_t)process->numCpus()); - max_cpu.copyOut(tc->getMemPort()); + max_cpu.copyOut(tc->getMemProxy()); return 1; } case AlphaTru64::GSI_CPUS_IN_BOX: { TypedBufferArg<uint32_t> cpus_in_box(bufPtr); *cpus_in_box = htog((uint32_t)process->numCpus()); - cpus_in_box.copyOut(tc->getMemPort()); + cpus_in_box.copyOut(tc->getMemProxy()); return 1; } case AlphaTru64::GSI_PHYSMEM: { TypedBufferArg<uint64_t> physmem(bufPtr); *physmem = htog((uint64_t)1024 * 1024); // physical memory in KB - physmem.copyOut(tc->getMemPort()); + physmem.copyOut(tc->getMemProxy()); return 1; } @@ -105,14 +105,14 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, infop->cpu_ex_binding = htog(0); infop->mhz = htog(667); - infop.copyOut(tc->getMemPort()); + infop.copyOut(tc->getMemProxy()); return 1; } case AlphaTru64::GSI_PROC_TYPE: { TypedBufferArg<uint64_t> proc_type(bufPtr); *proc_type = htog((uint64_t)11); - proc_type.copyOut(tc->getMemPort()); + proc_type.copyOut(tc->getMemProxy()); return 1; } @@ -121,14 +121,14 @@ getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, strncpy((char *)bufArg.bufferPtr(), "COMPAQ Professional Workstation XP1000", nbytes); - bufArg.copyOut(tc->getMemPort()); + bufArg.copyOut(tc->getMemProxy()); return 1; } case AlphaTru64::GSI_CLK_TCK: { TypedBufferArg<uint64_t> clk_hz(bufPtr); *clk_hz = htog((uint64_t)1024); - clk_hz.copyOut(tc->getMemPort()); + clk_hz.copyOut(tc->getMemProxy()); return 1; } @@ -193,7 +193,7 @@ tableFunc(SyscallDesc *desc, int callnum, LiveProcess *process, elp->si_phz = htog(clk_hz); elp->si_boottime = htog(seconds_since_epoch); // seconds since epoch? elp->si_max_procs = htog(process->numCpus()); - elp.copyOut(tc->getMemPort()); + elp.copyOut(tc->getMemProxy()); return 0; } diff --git a/src/arch/alpha/tru64/system.cc b/src/arch/alpha/tru64/system.cc index 5a47addbd..13cc93247 100644 --- a/src/arch/alpha/tru64/system.cc +++ b/src/arch/alpha/tru64/system.cc @@ -38,9 +38,7 @@ #include "cpu/thread_context.hh" #include "kern/tru64/tru64_events.hh" #include "kern/system_events.hh" -#include "mem/physical.hh" -#include "mem/port.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" using namespace std; @@ -49,7 +47,7 @@ Tru64AlphaSystem::Tru64AlphaSystem(Tru64AlphaSystem::Params *p) { Addr addr = 0; if (kernelSymtab->findAddress("enable_async_printf", addr)) { - virtPort->write(addr, (uint32_t)0); + virtProxy->write(addr, (uint32_t)0); } #ifdef DEBUG diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc index 0048e43e9..efafec4bc 100644 --- a/src/arch/alpha/utility.cc +++ b/src/arch/alpha/utility.cc @@ -31,7 +31,7 @@ #include "arch/alpha/utility.hh" #include "arch/alpha/vtophys.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" #include "sim/full_system.hh" namespace AlphaISA { @@ -48,7 +48,7 @@ getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) return tc->readIntReg(16 + number); } else { Addr sp = tc->readIntReg(StackPointerReg); - VirtualPort *vp = tc->getVirtPort(); + FSTranslatingPortProxy* vp = tc->getVirtProxy(); uint64_t arg = vp->read<uint64_t>(sp + (number-NumArgumentRegs) * sizeof(uint64_t)); return arg; diff --git a/src/arch/alpha/vtophys.cc b/src/arch/alpha/vtophys.cc index c51cddd11..453c48444 100644 --- a/src/arch/alpha/vtophys.cc +++ b/src/arch/alpha/vtophys.cc @@ -38,14 +38,14 @@ #include "base/trace.hh" #include "cpu/thread_context.hh" #include "debug/VtoPhys.hh" -#include "mem/vport.hh" +#include "mem/port_proxy.hh" using namespace std; namespace AlphaISA { PageTableEntry -kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, VAddr vaddr) +kernel_pte_lookup(PortProxy* mem, Addr ptbr, VAddr vaddr) { Addr level1_pte = ptbr + vaddr.level1(); PageTableEntry level1 = mem->read<uint64_t>(level1_pte); @@ -103,7 +103,7 @@ vtophys(ThreadContext *tc, Addr addr) paddr = vaddr; } else { PageTableEntry pte = - kernel_pte_lookup(tc->getPhysPort(), ptbr, vaddr); + kernel_pte_lookup(tc->getPhysProxy(), ptbr, vaddr); if (pte.valid()) paddr = pte.paddr() | vaddr.offset(); } diff --git a/src/arch/alpha/vtophys.hh b/src/arch/alpha/vtophys.hh index b13afd090..1695676cb 100644 --- a/src/arch/alpha/vtophys.hh +++ b/src/arch/alpha/vtophys.hh @@ -37,11 +37,11 @@ #include "arch/alpha/utility.hh" class ThreadContext; -class FunctionalPort; +class PortProxy; namespace AlphaISA { -PageTableEntry kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, +PageTableEntry kernel_pte_lookup(PortProxy* mem, Addr ptbr, VAddr vaddr); Addr vtophys(Addr vaddr); diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc index c65962d00..1074b0362 100644 --- a/src/arch/arm/linux/process.cc +++ b/src/arch/arm/linux/process.cc @@ -70,7 +70,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->machine, "armv7l"); - name.copyOut(tc->getMemPort()); + name.copyOut(tc->getMemProxy()); return 0; } @@ -452,7 +452,7 @@ setTLSFunc(SyscallDesc *desc, int callnum, LiveProcess *process, int index = 0; uint32_t tlsPtr = process->getSyscallArg(tc, index); - tc->getMemPort()->writeBlob(ArmLinuxProcess::commPage + 0x0ff0, + tc->getMemProxy()->writeBlob(ArmLinuxProcess::commPage + 0x0ff0, (uint8_t *)&tlsPtr, sizeof(tlsPtr)); tc->setMiscReg(MISCREG_TPIDRURO,tlsPtr); return 0; @@ -512,7 +512,7 @@ ArmLinuxProcess::initState() // Fill this page with swi -1 so we'll no if we land in it somewhere. for (Addr addr = 0; addr < PageBytes; addr += sizeof(swiNeg1)) { - tc->getMemPort()->writeBlob(commPage + addr, + tc->getMemProxy()->writeBlob(commPage + addr, swiNeg1, sizeof(swiNeg1)); } @@ -521,7 +521,7 @@ ArmLinuxProcess::initState() 0x5f, 0xf0, 0x7f, 0xf5, // dmb 0x0e, 0xf0, 0xa0, 0xe1 // return }; - tc->getMemPort()->writeBlob(commPage + 0x0fa0, memory_barrier, + tc->getMemProxy()->writeBlob(commPage + 0x0fa0, memory_barrier, sizeof(memory_barrier)); uint8_t cmpxchg[] = @@ -535,7 +535,7 @@ ArmLinuxProcess::initState() 0x5f, 0xf0, 0x7f, 0xf5, // dmb 0x0e, 0xf0, 0xa0, 0xe1 // return }; - tc->getMemPort()->writeBlob(commPage + 0x0fc0, cmpxchg, sizeof(cmpxchg)); + tc->getMemProxy()->writeBlob(commPage + 0x0fc0, cmpxchg, sizeof(cmpxchg)); uint8_t get_tls[] = { @@ -543,7 +543,7 @@ ArmLinuxProcess::initState() 0x70, 0x0f, 0x1d, 0xee, // mrc p15, 0, r0, c13, c0, 3 0x0e, 0xf0, 0xa0, 0xe1 // return }; - tc->getMemPort()->writeBlob(commPage + 0x0fe0, get_tls, sizeof(get_tls)); + tc->getMemProxy()->writeBlob(commPage + 0x0fe0, get_tls, sizeof(get_tls)); } ArmISA::IntReg diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc index 66f4f26af..a764edaca 100644 --- a/src/arch/arm/linux/system.cc +++ b/src/arch/arm/linux/system.cc @@ -49,6 +49,7 @@ #include "cpu/thread_context.hh" #include "debug/Loader.hh" #include "kern/linux/events.hh" +#include "mem/fs_translating_port_proxy.hh" #include "mem/physical.hh" using namespace ArmISA; @@ -57,6 +58,27 @@ using namespace Linux; LinuxArmSystem::LinuxArmSystem(Params *p) : ArmSystem(p) { +} + +bool +LinuxArmSystem::adderBootUncacheable(Addr a) +{ + Addr block = a & ~ULL(0x7F); + if (block == secDataPtrAddr || block == secDataAddr || + block == penReleaseAddr) + return true; + return false; +} + +void +LinuxArmSystem::initState() +{ + // Moved from the constructor to here since it relies on the + // address map being resolved in the interconnect + + // Call the initialisation of the super class + ArmSystem::initState(); + // Load symbols at physical address, we might not want // to do this perminately, for but early bootup work // it is helpfulp. @@ -92,7 +114,7 @@ LinuxArmSystem::LinuxArmSystem(Params *p) DPRINTF(Loader, "Boot atags was %d bytes in total\n", size << 2); DDUMP(Loader, boot_data, size << 2); - functionalPort->writeBlob(ParamsList, boot_data, size << 2); + physProxy->writeBlob(ParamsList, boot_data, size << 2); #ifndef NDEBUG kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic"); @@ -128,22 +150,6 @@ LinuxArmSystem::LinuxArmSystem(Params *p) secDataPtrAddr &= ~ULL(0x7F); secDataAddr &= ~ULL(0x7F); penReleaseAddr &= ~ULL(0x7F); -} - -bool -LinuxArmSystem::adderBootUncacheable(Addr a) -{ - Addr block = a & ~ULL(0x7F); - if (block == secDataPtrAddr || block == secDataAddr || - block == penReleaseAddr) - return true; - return false; -} - -void -LinuxArmSystem::initState() -{ - ArmSystem::initState(); for (int i = 0; i < threadContexts.size(); i++) { threadContexts[i]->setIntReg(0, 0); diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index aa5d7dfce..c149f5409 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -50,7 +50,6 @@ #include "cpu/thread_context.hh" #include "debug/Stack.hh" #include "mem/page_table.hh" -#include "mem/translating_port.hh" #include "sim/byteswap.hh" #include "sim/process_impl.hh" #include "sim/system.hh" diff --git a/src/arch/arm/stacktrace.cc b/src/arch/arm/stacktrace.cc index 31376cdae..69d0f354c 100644 --- a/src/arch/arm/stacktrace.cc +++ b/src/arch/arm/stacktrace.cc @@ -37,7 +37,7 @@ #include "base/trace.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" #include "sim/system.hh" using namespace std; @@ -48,9 +48,9 @@ namespace ArmISA { Addr addr = 0; - VirtualPort *vp; + FSTranslatingPortProxy* vp; - vp = tc->getVirtPort(); + vp = tc->getVirtProxy(); if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) panic("thread info not compiled into kernel\n"); diff --git a/src/arch/arm/system.cc b/src/arch/arm/system.cc index 4d4dff4d9..ca5bfc471 100644 --- a/src/arch/arm/system.cc +++ b/src/arch/arm/system.cc @@ -47,6 +47,7 @@ #include "base/loader/symtab.hh" #include "cpu/thread_context.hh" #include "mem/physical.hh" +#include "mem/fs_translating_port_proxy.hh" using namespace std; using namespace Linux; @@ -55,6 +56,18 @@ ArmSystem::ArmSystem(Params *p) : System(p), bootldr(NULL) { debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk"); +} + +void +ArmSystem::initState() +{ + // Moved from the constructor to here since it relies on the + // address map being resolved in the interconnect + + // Call the initialisation of the super class + System::initState(); + + const Params* p = params(); if ((p->boot_loader == "") != (p->boot_loader_mem == NULL)) fatal("If boot_loader is specifed, memory to load it must be also.\n"); @@ -65,29 +78,18 @@ ArmSystem::ArmSystem(Params *p) if (!bootldr) fatal("Could not read bootloader: %s\n", p->boot_loader); - Port *mem_port; - FunctionalPort fp(name() + "-fport"); - mem_port = p->boot_loader_mem->getPort("functional"); - fp.setPeer(mem_port); - mem_port->setPeer(&fp); - - bootldr->loadSections(&fp); + bootldr->loadSections(physProxy); bootldr->loadGlobalSymbols(debugSymbolTable); uint8_t jump_to_bl[] = { 0x07, 0xf0, 0xa0, 0xe1 // branch to r7 }; - functionalPort->writeBlob(0x0, jump_to_bl, sizeof(jump_to_bl)); + physProxy->writeBlob(0x0, jump_to_bl, sizeof(jump_to_bl)); inform("Using bootloader at address %#x\n", bootldr->entryPoint()); } -} -void -ArmSystem::initState() -{ - System::initState(); if (bootldr) { // Put the address of the boot loader into r7 so we know // where to branch to after the reset fault @@ -98,16 +100,16 @@ ArmSystem::initState() threadContexts[i]->setIntReg(5, params()->flags_addr); threadContexts[i]->setIntReg(7, bootldr->entryPoint()); } - if (!params()->gic_cpu_addr || !params()->flags_addr) + if (!p->gic_cpu_addr || !p->flags_addr) fatal("gic_cpu_addr && flags_addr must be set with bootloader\n"); } else { // Set the initial PC to be at start of the kernel code threadContexts[0]->pcState(kernelEntry & loadAddrMask); } for (int i = 0; i < threadContexts.size(); i++) { - if (params()->midr_regval) { + if (p->midr_regval) { threadContexts[i]->setMiscReg(ArmISA::MISCREG_MIDR, - params()->midr_regval); + p->midr_regval); } } diff --git a/src/arch/arm/system.hh b/src/arch/arm/system.hh index 32b48a85b..7cf36fd6c 100644 --- a/src/arch/arm/system.hh +++ b/src/arch/arm/system.hh @@ -76,7 +76,10 @@ class ArmSystem : public System ArmSystem(Params *p); ~ArmSystem(); - void initState(); + /** + * Initialise the system + */ + virtual void initState(); /** Check if an address should be uncacheable until all caches are enabled. * This exits because coherence on some addresses at boot is maintained via diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc index 6c2997a27..42b5be181 100644 --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -44,7 +44,7 @@ #include "arch/arm/utility.hh" #include "arch/arm/vtophys.hh" #include "cpu/thread_context.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" #include "sim/full_system.hh" namespace ArmISA { @@ -86,7 +86,7 @@ getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) } } else { Addr sp = tc->readIntReg(StackPointerReg); - VirtualPort *vp = tc->getVirtPort(); + FSTranslatingPortProxy* vp = tc->getVirtProxy(); uint64_t arg; if (size == sizeof(uint64_t)) { // If the argument is even it must be aligned diff --git a/src/arch/arm/vtophys.cc b/src/arch/arm/vtophys.cc index 1691a387c..45e6f1849 100644 --- a/src/arch/arm/vtophys.cc +++ b/src/arch/arm/vtophys.cc @@ -51,7 +51,7 @@ #include "base/chunk_generator.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" using namespace std; using namespace ArmISA; @@ -101,7 +101,7 @@ ArmISA::vtophys(ThreadContext *tc, Addr addr) N = 0; } - FunctionalPort *port = tc->getPhysPort(); + PortProxy* port = tc->getPhysProxy(); Addr l1desc_addr = mbits(ttbr, 31, 14-N) | (bits(addr,31-N,20) << 2); TableWalker::L1Descriptor l1desc; diff --git a/src/arch/mips/linux/process.cc b/src/arch/mips/linux/process.cc index 0982e05cb..fda32b97b 100644 --- a/src/arch/mips/linux/process.cc +++ b/src/arch/mips/linux/process.cc @@ -59,7 +59,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->machine, "mips"); - name.copyOut(tc->getMemPort()); + name.copyOut(tc->getMemProxy()); return 0; } @@ -82,7 +82,7 @@ sys_getsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, TypedBufferArg<uint64_t> fpcr(bufPtr); // I don't think this exactly matches the HW FPCR *fpcr = 0; - fpcr.copyOut(tc->getMemPort()); + fpcr.copyOut(tc->getMemProxy()); return 0; } default: @@ -111,7 +111,7 @@ sys_setsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, // SSI_IEEE_FP_CONTROL TypedBufferArg<uint64_t> fpcr(bufPtr); // I don't think this exactly matches the HW FPCR - fpcr.copyIn(tc->getMemPort()); + fpcr.copyIn(tc->getMemProxy()); DPRINTFR(SyscallVerbose, "sys_setsysinfo(SSI_IEEE_FP_CONTROL): " " setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr)); return 0; diff --git a/src/arch/mips/linux/system.cc b/src/arch/mips/linux/system.cc index 30e0f95e9..f97426f85 100644 --- a/src/arch/mips/linux/system.cc +++ b/src/arch/mips/linux/system.cc @@ -63,91 +63,10 @@ using namespace Linux; LinuxMipsSystem::LinuxMipsSystem(Params *p) : MipsSystem(p) { - Addr addr = 0; - - /** - * The symbol swapper_pg_dir marks the beginning of the kernel and - * the location of bootloader passed arguments - */ - if (!kernelSymtab->findAddress("swapper_pg_dir", KernelStart)) { - panic("Could not determine start location of kernel"); - } - - /** - * Since we aren't using a bootloader, we have to copy the - * kernel arguments directly into the kernel's memory. - */ - virtPort->writeBlob(CommandLine(), (uint8_t*)params()->boot_osflags.c_str(), - params()->boot_osflags.length()+1); - - /** - * find the address of the est_cycle_freq variable and insert it - * so we don't through the lengthly process of trying to - * calculated it by using the PIT, RTC, etc. - */ - if (kernelSymtab->findAddress("est_cycle_freq", addr)) - virtPort->write(addr, (uint64_t)(SimClock::Frequency / - p->boot_cpu_frequency)); - - /** - * EV5 only supports 127 ASNs so we are going to tell the kernel that the - * paritiuclar EV6 we have only supports 127 asns. - * @todo At some point we should change ev5.hh and the palcode to support - * 255 ASNs. - */ - if (kernelSymtab->findAddress("dp264_mv", addr)) - virtPort->write(addr + 0x18, LittleEndianGuest::htog((uint32_t)127)); - else - panic("could not find dp264_mv\n"); - -#ifndef NDEBUG - kernelPanicEvent = addKernelFuncEvent<BreakPCEvent>("panic"); - if (!kernelPanicEvent) - panic("could not find kernel symbol \'panic\'"); - -#endif - - /** - * Any time ide_delay_50ms, calibarte_delay or - * determine_cpu_caches is called just skip the - * function. Currently determine_cpu_caches only is used put - * information in proc, however if that changes in the future we - * will have to fill in the cache size variables appropriately. - */ - - skipIdeDelay50msEvent = - addKernelFuncEvent<SkipFuncEvent>("ide_delay_50ms"); - skipDelayLoopEvent = - addKernelFuncEvent<SkipDelayLoopEvent>("calibrate_delay"); - skipCacheProbeEvent = - addKernelFuncEvent<SkipFuncEvent>("determine_cpu_caches"); - debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk"); - idleStartEvent = addKernelFuncEvent<IdleStartEvent>("cpu_idle"); - - // Disable for now as it runs into panic() calls in VPTr methods - // (see sim/vptr.hh). Once those bugs are fixed, we can - // re-enable, but we should find a better way to turn it on than - // using DTRACE(Thread), since looking at a trace flag at tick 0 - // leads to non-intuitive behavior with --trace-start. - if (false && kernelSymtab->findAddress("mips_switch_to", addr)) { - printThreadEvent = new PrintThreadInfo(&pcEventQueue, "threadinfo", - addr + sizeof(MachInst) * 6); - } else { - printThreadEvent = NULL; - } } LinuxMipsSystem::~LinuxMipsSystem() { -#ifndef NDEBUG - delete kernelPanicEvent; -#endif - delete skipIdeDelay50msEvent; - delete skipDelayLoopEvent; - delete skipCacheProbeEvent; - delete debugPrintkEvent; - delete idleStartEvent; - delete printThreadEvent; } diff --git a/src/arch/mips/linux/threadinfo.hh b/src/arch/mips/linux/threadinfo.hh index 20a4033dd..40dd435d6 100644 --- a/src/arch/mips/linux/threadinfo.hh +++ b/src/arch/mips/linux/threadinfo.hh @@ -79,7 +79,7 @@ class ThreadInfo if (!addr) addr = tc->readMiscRegNoEffect(0/*MipsISA::IPR_PALtemp23*/); - FunctionalPort *p = tc->getPhysPort(); + PortProxy* p = tc->getPhysProxy(); p->readBlob(addr, (uint8_t *)&sp, sizeof(Addr)); return sp & ~ULL(0x3fff); diff --git a/src/arch/mips/stacktrace.cc b/src/arch/mips/stacktrace.cc index 50f6e1fb0..d4548b4bb 100644 --- a/src/arch/mips/stacktrace.cc +++ b/src/arch/mips/stacktrace.cc @@ -37,7 +37,7 @@ #include "base/trace.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" #include "sim/system.hh" using namespace std; @@ -55,9 +55,9 @@ ProcessInfo::task(Addr ksp) const Addr tsk; - VirtualPort *vp; + FSTranslatingPortProxy* vp; - vp = tc->getVirtPort(); + vp = tc->getVirtProxy(); tsk = vp->readGtoH<Addr>(base + task_off); return tsk; @@ -72,9 +72,9 @@ ProcessInfo::pid(Addr ksp) const uint16_t pd; - VirtualPort *vp; + FSTranslatingPortProxy* vp; - vp = tc->getVirtPort(); + vp = tc->getVirtProxy(); pd = vp->readGtoH<uint16_t>(task + pid_off); return pd; diff --git a/src/arch/mips/system.cc b/src/arch/mips/system.cc index d367acd64..f0d4c250e 100755 --- a/src/arch/mips/system.cc +++ b/src/arch/mips/system.cc @@ -38,7 +38,6 @@ #include "base/loader/symtab.hh" #include "base/trace.hh" #include "mem/physical.hh" -#include "mem/vport.hh" #include "params/MipsSystem.hh" #include "sim/byteswap.hh" @@ -46,67 +45,6 @@ using namespace LittleEndianGuest; MipsSystem::MipsSystem(Params *p) : System(p) { - if (p->bare_iron == true) { - hexFile = new HexFile(params()->hex_file_name); - if (!hexFile->loadSections(functionalPort)) - panic("Could not load hex file\n"); - } - - Addr addr = 0; - - consoleSymtab = new SymbolTable; - - - /** - * Load the console code into memory - */ - // Load Console Code - console = createObjectFile(params()->console); - - warn("console code is located at: %s\n", params()->console); - - if (console == NULL) - fatal("Could not load console file %s", params()->console); - //Load program sections into memory - console->loadSections(functionalPort, loadAddrMask); - - //load symbols - if (!console->loadGlobalSymbols(consoleSymtab)) - panic("could not load console symbols\n"); - - if (!console->loadGlobalSymbols(debugSymbolTable)) - panic("could not load console symbols\n"); - - -#ifndef NDEBUG - consolePanicEvent = addConsoleFuncEvent<BreakPCEvent>("panic"); -#endif - - /** - * Copy the osflags (kernel arguments) into the consoles - * memory. (Presently Linux does not use the console service - * routine to get these command line arguments, but Tru64 and - * others do.) - */ - if (consoleSymtab->findAddress("env_booted_osflags", addr)) { - warn("writing addr starting from %#x", addr); - virtPort->writeBlob(addr, (uint8_t*)params()->boot_osflags.c_str(), - strlen(params()->boot_osflags.c_str())); - } - - /** - * Set the hardware reset parameter block system type and revision - * information to Tsunami. - */ - if (consoleSymtab->findAddress("m5_rpb", addr)) { - uint64_t data; - data = htog(params()->system_type); - virtPort->write(addr + 0x50, data); - data = htog(params()->system_rev); - virtPort->write(addr + 0x58, data); - } else { - panic("could not find hwrpb\n"); - } } MipsSystem::~MipsSystem() diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc index 1f3b19c7b..65432b4ea 100644 --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -31,17 +31,16 @@ #include <cmath> #include "arch/mips/isa_traits.hh" +#include "arch/mips/registers.hh" #include "arch/mips/utility.hh" +#include "arch/mips/vtophys.hh" #include "base/bitfield.hh" #include "base/misc.hh" #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" +#include "mem/fs_translating_port_proxy.hh" #include "sim/serialize.hh" -#include "arch/mips/registers.hh" -#include "arch/mips/vtophys.hh" -#include "mem/vport.hh" - using namespace MipsISA; using namespace std; diff --git a/src/arch/mips/vtophys.cc b/src/arch/mips/vtophys.cc index c6a317df8..60d9bc1ba 100755 --- a/src/arch/mips/vtophys.cc +++ b/src/arch/mips/vtophys.cc @@ -38,7 +38,6 @@ #include "base/trace.hh" #include "cpu/thread_context.hh" #include "debug/VtoPhys.hh" -#include "mem/vport.hh" using namespace std; using namespace MipsISA; diff --git a/src/arch/power/linux/process.cc b/src/arch/power/linux/process.cc index 1c1b2827f..f83df41d1 100644 --- a/src/arch/power/linux/process.cc +++ b/src/arch/power/linux/process.cc @@ -59,7 +59,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->machine, "power"); - name.copyOut(tc->getMemPort()); + name.copyOut(tc->getMemProxy()); return 0; } diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc index 788c7cc0c..4a5c06673 100644 --- a/src/arch/power/process.cc +++ b/src/arch/power/process.cc @@ -39,7 +39,6 @@ #include "cpu/thread_context.hh" #include "debug/Stack.hh" #include "mem/page_table.hh" -#include "mem/translating_port.hh" #include "sim/process_impl.hh" #include "sim/system.hh" diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc index 034c38bef..9433cb508 100644 --- a/src/arch/sparc/linux/syscalls.cc +++ b/src/arch/sparc/linux/syscalls.cc @@ -50,7 +50,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->machine, "sparc"); - name.copyOut(tc->getMemPort()); + name.copyOut(tc->getMemProxy()); return 0; } @@ -69,19 +69,19 @@ getresuidFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) if (ruid) { BufferArg ruidBuff(ruid, sizeof(IntReg)); memcpy(ruidBuff.bufferPtr(), &id, sizeof(IntReg)); - ruidBuff.copyOut(tc->getMemPort()); + ruidBuff.copyOut(tc->getMemProxy()); } // Set the euid if (euid) { BufferArg euidBuff(euid, sizeof(IntReg)); memcpy(euidBuff.bufferPtr(), &id, sizeof(IntReg)); - euidBuff.copyOut(tc->getMemPort()); + euidBuff.copyOut(tc->getMemProxy()); } // Set the suid if (suid) { BufferArg suidBuff(suid, sizeof(IntReg)); memcpy(suidBuff.bufferPtr(), &id, sizeof(IntReg)); - suidBuff.copyOut(tc->getMemPort()); + suidBuff.copyOut(tc->getMemProxy()); } return 0; } diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 5c594dcbc..cc39ecf31 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -41,7 +41,6 @@ #include "cpu/thread_context.hh" #include "debug/Stack.hh" #include "mem/page_table.hh" -#include "mem/translating_port.hh" #include "sim/process_impl.hh" #include "sim/system.hh" @@ -448,7 +447,7 @@ void Sparc32LiveProcess::flushWindows(ThreadContext *tc) for (int index = 16; index < 32; index++) { uint32_t regVal = tc->readIntReg(index); regVal = htog(regVal); - if (!tc->getMemPort()->tryWriteBlob( + if (!tc->getMemProxy()->tryWriteBlob( sp + (index - 16) * 4, (uint8_t *)®Val, 4)) { warn("Failed to save register to the stack when " "flushing windows.\n"); @@ -483,7 +482,7 @@ Sparc64LiveProcess::flushWindows(ThreadContext *tc) for (int index = 16; index < 32; index++) { IntReg regVal = tc->readIntReg(index); regVal = htog(regVal); - if (!tc->getMemPort()->tryWriteBlob( + if (!tc->getMemProxy()->tryWriteBlob( sp + 2047 + (index - 16) * 8, (uint8_t *)®Val, 8)) { warn("Failed to save register to the stack when " "flushing windows.\n"); diff --git a/src/arch/sparc/solaris/process.cc b/src/arch/sparc/solaris/process.cc index e47377d42..f929877f3 100644 --- a/src/arch/sparc/solaris/process.cc +++ b/src/arch/sparc/solaris/process.cc @@ -55,7 +55,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, strcpy(name->version, "Generic_118558-21"); strcpy(name->machine, "sun4u"); - name.copyOut(tc->getMemPort()); + name.copyOut(tc->getMemProxy()); return 0; } diff --git a/src/arch/sparc/system.cc b/src/arch/sparc/system.cc index 9988702d2..ab5f7432e 100644 --- a/src/arch/sparc/system.cc +++ b/src/arch/sparc/system.cc @@ -40,10 +40,7 @@ using namespace BigEndianGuest; SparcSystem::SparcSystem(Params *p) - : System(p), sysTick(0),funcRomPort(p->name + "-fromport"), - funcNvramPort(p->name + "-fnvramport"), - funcHypDescPort(p->name + "-fhypdescport"), - funcPartDescPort(p->name + "-fpartdescport") + : System(p), sysTick(0) { resetSymtab = new SymbolTable; hypervisorSymtab = new SymbolTable; @@ -51,23 +48,13 @@ SparcSystem::SparcSystem(Params *p) nvramSymtab = new SymbolTable; hypervisorDescSymtab = new SymbolTable; partitionDescSymtab = new SymbolTable; +} - Port *rom_port; - rom_port = params()->rom->getPort("functional"); - funcRomPort.setPeer(rom_port); - rom_port->setPeer(&funcRomPort); - - rom_port = params()->nvram->getPort("functional"); - funcNvramPort.setPeer(rom_port); - rom_port->setPeer(&funcNvramPort); - - rom_port = params()->hypervisor_desc->getPort("functional"); - funcHypDescPort.setPeer(rom_port); - rom_port->setPeer(&funcHypDescPort); - - rom_port = params()->partition_desc->getPort("functional"); - funcPartDescPort.setPeer(rom_port); - rom_port->setPeer(&funcPartDescPort); +void +SparcSystem::initState() +{ + // Call the initialisation of the super class + System::initState(); /** * Load the boot code, and hypervisor into memory. @@ -107,22 +94,22 @@ SparcSystem::SparcSystem(Params *p) // Load reset binary into memory reset->setTextBase(params()->reset_addr); - reset->loadSections(&funcRomPort); + reset->loadSections(physProxy); // Load the openboot binary openboot->setTextBase(params()->openboot_addr); - openboot->loadSections(&funcRomPort); + openboot->loadSections(physProxy); // Load the hypervisor binary hypervisor->setTextBase(params()->hypervisor_addr); - hypervisor->loadSections(&funcRomPort); + hypervisor->loadSections(physProxy); // Load the nvram image nvram->setTextBase(params()->nvram_addr); - nvram->loadSections(&funcNvramPort); + nvram->loadSections(physProxy); // Load the hypervisor description image hypervisor_desc->setTextBase(params()->hypervisor_desc_addr); - hypervisor_desc->loadSections(&funcHypDescPort); + hypervisor_desc->loadSections(physProxy); // Load the partition description image partition_desc->setTextBase(params()->partition_desc_addr); - partition_desc->loadSections(&funcPartDescPort); + partition_desc->loadSections(physProxy); // load symbols if (!reset->loadGlobalSymbols(resetSymtab)) diff --git a/src/arch/sparc/system.hh b/src/arch/sparc/system.hh index 292f56b60..4b3da6287 100644 --- a/src/arch/sparc/system.hh +++ b/src/arch/sparc/system.hh @@ -48,6 +48,8 @@ class SparcSystem : public System SparcSystem(Params *p); ~SparcSystem(); + virtual void initState(); + /** * Serialization stuff */ @@ -94,18 +96,6 @@ class SparcSystem : public System /** System Tick for syncronized tick across all cpus. */ Tick sysTick; - /** functional port to ROM */ - FunctionalPort funcRomPort; - - /** functional port to nvram */ - FunctionalPort funcNvramPort; - - /** functional port to hypervisor description */ - FunctionalPort funcHypDescPort; - - /** functional port to partition description */ - FunctionalPort funcPartDescPort; - protected: const Params *params() const { return (const Params *)_params; } diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc index 63b8e7960..74b1b2794 100644 --- a/src/arch/sparc/utility.cc +++ b/src/arch/sparc/utility.cc @@ -32,7 +32,7 @@ #include "arch/sparc/faults.hh" #include "arch/sparc/utility.hh" #include "arch/sparc/vtophys.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" namespace SparcISA { @@ -52,7 +52,7 @@ getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) return tc->readIntReg(8 + number); } else { Addr sp = tc->readIntReg(StackPointerReg); - VirtualPort *vp = tc->getVirtPort(); + FSTranslatingPortProxy* vp = tc->getVirtProxy(); uint64_t arg = vp->read<uint64_t>(sp + 92 + (number-NumArgumentRegs) * sizeof(uint64_t)); return arg; diff --git a/src/arch/sparc/vtophys.cc b/src/arch/sparc/vtophys.cc index edcf88828..7e3c5fe01 100644 --- a/src/arch/sparc/vtophys.cc +++ b/src/arch/sparc/vtophys.cc @@ -37,7 +37,7 @@ #include "base/trace.hh" #include "cpu/thread_context.hh" #include "debug/VtoPhys.hh" -#include "mem/vport.hh" +#include "mem/port_proxy.hh" using namespace std; @@ -81,7 +81,7 @@ vtophys(ThreadContext *tc, Addr addr) int pri_context = bits(tlbdata,47,32); // int sec_context = bits(tlbdata,63,48); - FunctionalPort *mem = tc->getPhysPort(); + PortProxy* mem = tc->getPhysProxy(); TLB* itb = tc->getITBPtr(); TLB* dtb = tc->getDTBPtr(); TlbEntry* tbe; diff --git a/src/arch/x86/bios/intelmp.cc b/src/arch/x86/bios/intelmp.cc index af32709aa..974af28a5 100644 --- a/src/arch/x86/bios/intelmp.cc +++ b/src/arch/x86/bios/intelmp.cc @@ -41,7 +41,7 @@ #include "arch/x86/isa_traits.hh" #include "base/misc.hh" #include "base/types.hh" -#include "mem/port.hh" +#include "mem/port_proxy.hh" #include "sim/byteswap.hh" // Config entry types @@ -70,10 +70,10 @@ const char X86ISA::IntelMP::FloatingPointer::signature[] = "_MP_"; template<class T> uint8_t -writeOutField(FunctionalPort * port, Addr addr, T val) +writeOutField(PortProxy* proxy, Addr addr, T val) { T guestVal = X86ISA::htog(val); - port->writeBlob(addr, (uint8_t *)(&guestVal), sizeof(T)); + proxy->writeBlob(addr, (uint8_t *)(&guestVal), sizeof(T)); uint8_t checkSum = 0; while(guestVal) { @@ -84,7 +84,7 @@ writeOutField(FunctionalPort * port, Addr addr, T val) } uint8_t -writeOutString(FunctionalPort * port, Addr addr, string str, int length) +writeOutString(PortProxy* proxy, Addr addr, string str, int length) { char cleanedString[length + 1]; cleanedString[length] = 0; @@ -97,7 +97,7 @@ writeOutString(FunctionalPort * port, Addr addr, string str, int length) memcpy(cleanedString, str.c_str(), str.length()); memset(cleanedString + str.length(), 0, length - str.length()); } - port->writeBlob(addr, (uint8_t *)(&cleanedString), length); + proxy->writeBlob(addr, (uint8_t *)(&cleanedString), length); uint8_t checkSum = 0; for (int i = 0; i < length; i++) @@ -107,7 +107,7 @@ writeOutString(FunctionalPort * port, Addr addr, string str, int length) } Addr -X86ISA::IntelMP::FloatingPointer::writeOut(FunctionalPort * port, Addr addr) +X86ISA::IntelMP::FloatingPointer::writeOut(PortProxy* proxy, Addr addr) { // Make sure that either a config table is present or a default // configuration was found but not both. @@ -120,28 +120,28 @@ X86ISA::IntelMP::FloatingPointer::writeOut(FunctionalPort * port, Addr addr) uint8_t checkSum = 0; - port->writeBlob(addr, (uint8_t *)signature, 4); + proxy->writeBlob(addr, (uint8_t *)signature, 4); for (int i = 0; i < 4; i++) checkSum += signature[i]; - checkSum += writeOutField(port, addr + 4, tableAddr); + checkSum += writeOutField(proxy, addr + 4, tableAddr); // The length of the structure in paragraphs, aka 16 byte chunks. uint8_t length = 1; - port->writeBlob(addr + 8, &length, 1); + proxy->writeBlob(addr + 8, &length, 1); checkSum += length; - port->writeBlob(addr + 9, &specRev, 1); + proxy->writeBlob(addr + 9, &specRev, 1); checkSum += specRev; - port->writeBlob(addr + 11, &defaultConfig, 1); + proxy->writeBlob(addr + 11, &defaultConfig, 1); checkSum += defaultConfig; uint32_t features2_5 = imcrPresent ? (1 << 7) : 0; - checkSum += writeOutField(port, addr + 12, features2_5); + checkSum += writeOutField(proxy, addr + 12, features2_5); checkSum = -checkSum; - port->writeBlob(addr + 10, &checkSum, 1); + proxy->writeBlob(addr + 10, &checkSum, 1); return 16; } @@ -158,10 +158,10 @@ X86IntelMPFloatingPointerParams::create() } Addr -X86ISA::IntelMP::BaseConfigEntry::writeOut(FunctionalPort * port, +X86ISA::IntelMP::BaseConfigEntry::writeOut(PortProxy* proxy, Addr addr, uint8_t &checkSum) { - port->writeBlob(addr, &type, 1); + proxy->writeBlob(addr, &type, 1); checkSum += type; return 1; } @@ -171,12 +171,12 @@ X86ISA::IntelMP::BaseConfigEntry::BaseConfigEntry(Params * p, uint8_t _type) : {} Addr -X86ISA::IntelMP::ExtConfigEntry::writeOut(FunctionalPort * port, +X86ISA::IntelMP::ExtConfigEntry::writeOut(PortProxy* proxy, Addr addr, uint8_t &checkSum) { - port->writeBlob(addr, &type, 1); + proxy->writeBlob(addr, &type, 1); checkSum += type; - port->writeBlob(addr + 1, &length, 1); + proxy->writeBlob(addr + 1, &length, 1); checkSum += length; return 1; } @@ -189,59 +189,59 @@ X86ISA::IntelMP::ExtConfigEntry::ExtConfigEntry(Params * p, const char X86ISA::IntelMP::ConfigTable::signature[] = "PCMP"; Addr -X86ISA::IntelMP::ConfigTable::writeOut(FunctionalPort * port, Addr addr) +X86ISA::IntelMP::ConfigTable::writeOut(PortProxy* proxy, Addr addr) { uint8_t checkSum = 0; - port->writeBlob(addr, (uint8_t *)signature, 4); + proxy->writeBlob(addr, (uint8_t *)signature, 4); for (int i = 0; i < 4; i++) checkSum += signature[i]; // Base table length goes here but will be calculated later. - port->writeBlob(addr + 6, (uint8_t *)(&specRev), 1); + proxy->writeBlob(addr + 6, (uint8_t *)(&specRev), 1); checkSum += specRev; // The checksum goes here but is still being calculated. - checkSum += writeOutString(port, addr + 8, oemID, 8); - checkSum += writeOutString(port, addr + 16, productID, 12); + checkSum += writeOutString(proxy, addr + 8, oemID, 8); + checkSum += writeOutString(proxy, addr + 16, productID, 12); - checkSum += writeOutField(port, addr + 28, oemTableAddr); - checkSum += writeOutField(port, addr + 32, oemTableSize); - checkSum += writeOutField(port, addr + 34, (uint16_t)baseEntries.size()); - checkSum += writeOutField(port, addr + 36, localApic); + checkSum += writeOutField(proxy, addr + 28, oemTableAddr); + checkSum += writeOutField(proxy, addr + 32, oemTableSize); + checkSum += writeOutField(proxy, addr + 34, (uint16_t)baseEntries.size()); + checkSum += writeOutField(proxy, addr + 36, localApic); uint8_t reserved = 0; - port->writeBlob(addr + 43, &reserved, 1); + proxy->writeBlob(addr + 43, &reserved, 1); checkSum += reserved; vector<BaseConfigEntry *>::iterator baseEnt; uint16_t offset = 44; for (baseEnt = baseEntries.begin(); baseEnt != baseEntries.end(); baseEnt++) { - offset += (*baseEnt)->writeOut(port, addr + offset, checkSum); + offset += (*baseEnt)->writeOut(proxy, addr + offset, checkSum); } // We've found the end of the base table this point. - checkSum += writeOutField(port, addr + 4, offset); + checkSum += writeOutField(proxy, addr + 4, offset); vector<ExtConfigEntry *>::iterator extEnt; uint16_t extOffset = 0; uint8_t extCheckSum = 0; for (extEnt = extEntries.begin(); extEnt != extEntries.end(); extEnt++) { - extOffset += (*extEnt)->writeOut(port, + extOffset += (*extEnt)->writeOut(proxy, addr + offset + extOffset, extCheckSum); } - checkSum += writeOutField(port, addr + 40, extOffset); + checkSum += writeOutField(proxy, addr + 40, extOffset); extCheckSum = -extCheckSum; - checkSum += writeOutField(port, addr + 42, extCheckSum); + checkSum += writeOutField(proxy, addr + 42, extCheckSum); // And now, we finally have the whole check sum completed. checkSum = -checkSum; - writeOutField(port, addr + 7, checkSum); + writeOutField(proxy, addr + 7, checkSum); return offset + extOffset; }; @@ -261,18 +261,18 @@ X86IntelMPConfigTableParams::create() Addr X86ISA::IntelMP::Processor::writeOut( - FunctionalPort * port, Addr addr, uint8_t &checkSum) + PortProxy* proxy, Addr addr, uint8_t &checkSum) { - BaseConfigEntry::writeOut(port, addr, checkSum); - checkSum += writeOutField(port, addr + 1, localApicID); - checkSum += writeOutField(port, addr + 2, localApicVersion); - checkSum += writeOutField(port, addr + 3, cpuFlags); - checkSum += writeOutField(port, addr + 4, cpuSignature); - checkSum += writeOutField(port, addr + 8, featureFlags); + BaseConfigEntry::writeOut(proxy, addr, checkSum); + checkSum += writeOutField(proxy, addr + 1, localApicID); + checkSum += writeOutField(proxy, addr + 2, localApicVersion); + checkSum += writeOutField(proxy, addr + 3, cpuFlags); + checkSum += writeOutField(proxy, addr + 4, cpuSignature); + checkSum += writeOutField(proxy, addr + 8, featureFlags); uint32_t reserved = 0; - port->writeBlob(addr + 12, (uint8_t *)(&reserved), 4); - port->writeBlob(addr + 16, (uint8_t *)(&reserved), 4); + proxy->writeBlob(addr + 12, (uint8_t *)(&reserved), 4); + proxy->writeBlob(addr + 16, (uint8_t *)(&reserved), 4); return 20; } @@ -298,11 +298,11 @@ X86IntelMPProcessorParams::create() Addr X86ISA::IntelMP::Bus::writeOut( - FunctionalPort * port, Addr addr, uint8_t &checkSum) + PortProxy* proxy, Addr addr, uint8_t &checkSum) { - BaseConfigEntry::writeOut(port, addr, checkSum); - checkSum += writeOutField(port, addr + 1, busID); - checkSum += writeOutString(port, addr + 2, busType, 6); + BaseConfigEntry::writeOut(proxy, addr, checkSum); + checkSum += writeOutField(proxy, addr + 1, busID); + checkSum += writeOutString(proxy, addr + 2, busType, 6); return 8; } @@ -318,13 +318,13 @@ X86IntelMPBusParams::create() Addr X86ISA::IntelMP::IOAPIC::writeOut( - FunctionalPort * port, Addr addr, uint8_t &checkSum) + PortProxy* proxy, Addr addr, uint8_t &checkSum) { - BaseConfigEntry::writeOut(port, addr, checkSum); - checkSum += writeOutField(port, addr + 1, id); - checkSum += writeOutField(port, addr + 2, version); - checkSum += writeOutField(port, addr + 3, flags); - checkSum += writeOutField(port, addr + 4, address); + BaseConfigEntry::writeOut(proxy, addr, checkSum); + checkSum += writeOutField(proxy, addr + 1, id); + checkSum += writeOutField(proxy, addr + 2, version); + checkSum += writeOutField(proxy, addr + 3, flags); + checkSum += writeOutField(proxy, addr + 4, address); return 8; } @@ -343,15 +343,15 @@ X86IntelMPIOAPICParams::create() Addr X86ISA::IntelMP::IntAssignment::writeOut( - FunctionalPort * port, Addr addr, uint8_t &checkSum) + PortProxy* proxy, Addr addr, uint8_t &checkSum) { - BaseConfigEntry::writeOut(port, addr, checkSum); - checkSum += writeOutField(port, addr + 1, interruptType); - checkSum += writeOutField(port, addr + 2, flags); - checkSum += writeOutField(port, addr + 4, sourceBusID); - checkSum += writeOutField(port, addr + 5, sourceBusIRQ); - checkSum += writeOutField(port, addr + 6, destApicID); - checkSum += writeOutField(port, addr + 7, destApicIntIn); + BaseConfigEntry::writeOut(proxy, addr, checkSum); + checkSum += writeOutField(proxy, addr + 1, interruptType); + checkSum += writeOutField(proxy, addr + 2, flags); + checkSum += writeOutField(proxy, addr + 4, sourceBusID); + checkSum += writeOutField(proxy, addr + 5, sourceBusIRQ); + checkSum += writeOutField(proxy, addr + 6, destApicID); + checkSum += writeOutField(proxy, addr + 7, destApicIntIn); return 8; } @@ -381,13 +381,13 @@ X86IntelMPLocalIntAssignmentParams::create() Addr X86ISA::IntelMP::AddrSpaceMapping::writeOut( - FunctionalPort * port, Addr addr, uint8_t &checkSum) + PortProxy* proxy, Addr addr, uint8_t &checkSum) { - ExtConfigEntry::writeOut(port, addr, checkSum); - checkSum += writeOutField(port, addr + 2, busID); - checkSum += writeOutField(port, addr + 3, addrType); - checkSum += writeOutField(port, addr + 4, addr); - checkSum += writeOutField(port, addr + 12, addrLength); + ExtConfigEntry::writeOut(proxy, addr, checkSum); + checkSum += writeOutField(proxy, addr + 2, busID); + checkSum += writeOutField(proxy, addr + 3, addrType); + checkSum += writeOutField(proxy, addr + 4, addr); + checkSum += writeOutField(proxy, addr + 12, addrLength); return length; } @@ -405,15 +405,15 @@ X86IntelMPAddrSpaceMappingParams::create() Addr X86ISA::IntelMP::BusHierarchy::writeOut( - FunctionalPort * port, Addr addr, uint8_t &checkSum) + PortProxy* proxy, Addr addr, uint8_t &checkSum) { - ExtConfigEntry::writeOut(port, addr, checkSum); - checkSum += writeOutField(port, addr + 2, busID); - checkSum += writeOutField(port, addr + 3, info); - checkSum += writeOutField(port, addr + 4, parentBus); + ExtConfigEntry::writeOut(proxy, addr, checkSum); + checkSum += writeOutField(proxy, addr + 2, busID); + checkSum += writeOutField(proxy, addr + 3, info); + checkSum += writeOutField(proxy, addr + 4, parentBus); uint32_t reserved = 0; - port->writeBlob(addr + 5, (uint8_t *)(&reserved), 3); + proxy->writeBlob(addr + 5, (uint8_t *)(&reserved), 3); return length; } @@ -434,12 +434,12 @@ X86IntelMPBusHierarchyParams::create() Addr X86ISA::IntelMP::CompatAddrSpaceMod::writeOut( - FunctionalPort * port, Addr addr, uint8_t &checkSum) + PortProxy* proxy, Addr addr, uint8_t &checkSum) { - ExtConfigEntry::writeOut(port, addr, checkSum); - checkSum += writeOutField(port, addr + 2, busID); - checkSum += writeOutField(port, addr + 3, mod); - checkSum += writeOutField(port, addr + 4, rangeList); + ExtConfigEntry::writeOut(proxy, addr, checkSum); + checkSum += writeOutField(proxy, addr + 2, busID); + checkSum += writeOutField(proxy, addr + 3, mod); + checkSum += writeOutField(proxy, addr + 4, rangeList); return length; } diff --git a/src/arch/x86/bios/intelmp.hh b/src/arch/x86/bios/intelmp.hh index 117466b48..0ddb62b8d 100644 --- a/src/arch/x86/bios/intelmp.hh +++ b/src/arch/x86/bios/intelmp.hh @@ -51,7 +51,7 @@ #include "enums/X86IntelMPTriggerMode.hh" #include "sim/sim_object.hh" -class FunctionalPort; +class PortProxy; // Config entry types class X86IntelMPBaseConfigEntryParams; @@ -93,7 +93,7 @@ class FloatingPointer : public SimObject public: - Addr writeOut(FunctionalPort * port, Addr addr); + Addr writeOut(PortProxy* proxy, Addr addr); Addr getTableAddr() { @@ -117,7 +117,7 @@ class BaseConfigEntry : public SimObject public: - virtual Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + virtual Addr writeOut(PortProxy* proxy, Addr addr, uint8_t &checkSum); BaseConfigEntry(Params * p, uint8_t _type); }; @@ -132,7 +132,7 @@ class ExtConfigEntry : public SimObject public: - virtual Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + virtual Addr writeOut(PortProxy* proxy, Addr addr, uint8_t &checkSum); ExtConfigEntry(Params * p, uint8_t _type, uint8_t _length); }; @@ -155,7 +155,7 @@ class ConfigTable : public SimObject std::vector<ExtConfigEntry *> extEntries; public: - Addr writeOut(FunctionalPort * port, Addr addr); + Addr writeOut(PortProxy* proxy, Addr addr); ConfigTable(Params * p); }; @@ -172,7 +172,7 @@ class Processor : public BaseConfigEntry uint32_t featureFlags; public: - Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + Addr writeOut(PortProxy* proxy, Addr addr, uint8_t &checkSum); Processor(Params * p); }; @@ -186,7 +186,7 @@ class Bus : public BaseConfigEntry std::string busType; public: - Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + Addr writeOut(PortProxy* proxy, Addr addr, uint8_t &checkSum); Bus(Params * p); }; @@ -202,7 +202,7 @@ class IOAPIC : public BaseConfigEntry uint32_t address; public: - Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + Addr writeOut(PortProxy* proxy, Addr addr, uint8_t &checkSum); IOAPIC(Params * p); }; @@ -221,7 +221,7 @@ class IntAssignment : public BaseConfigEntry uint8_t destApicIntIn; public: - Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + Addr writeOut(PortProxy* proxy, Addr addr, uint8_t &checkSum); IntAssignment(X86IntelMPBaseConfigEntryParams * p, Enums::X86IntelMPInterruptType _interruptType, @@ -269,7 +269,7 @@ class AddrSpaceMapping : public ExtConfigEntry uint64_t addrLength; public: - Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + Addr writeOut(PortProxy* proxy, Addr addr, uint8_t &checkSum); AddrSpaceMapping(Params * p); }; @@ -284,7 +284,7 @@ class BusHierarchy : public ExtConfigEntry uint8_t parentBus; public: - Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + Addr writeOut(PortProxy* proxy, Addr addr, uint8_t &checkSum); BusHierarchy(Params * p); }; @@ -299,7 +299,7 @@ class CompatAddrSpaceMod : public ExtConfigEntry uint32_t rangeList; public: - Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum); + Addr writeOut(PortProxy* proxy, Addr addr, uint8_t &checkSum); CompatAddrSpaceMod(Params * p); }; diff --git a/src/arch/x86/bios/smbios.cc b/src/arch/x86/bios/smbios.cc index c9015df0f..a85ece1ec 100644 --- a/src/arch/x86/bios/smbios.cc +++ b/src/arch/x86/bios/smbios.cc @@ -43,7 +43,7 @@ #include "arch/x86/bios/smbios.hh" #include "arch/x86/isa_traits.hh" #include "base/types.hh" -#include "mem/port.hh" +#include "mem/port_proxy.hh" #include "params/X86SMBiosBiosInformation.hh" #include "params/X86SMBiosSMBiosStructure.hh" #include "params/X86SMBiosSMBiosTable.hh" @@ -74,15 +74,15 @@ composeBitVector(T vec) } uint16_t -X86ISA::SMBios::SMBiosStructure::writeOut(FunctionalPort * port, Addr addr) +X86ISA::SMBios::SMBiosStructure::writeOut(PortProxy* proxy, Addr addr) { - port->writeBlob(addr, (uint8_t *)(&type), 1); + proxy->writeBlob(addr, (uint8_t *)(&type), 1); uint8_t length = getLength(); - port->writeBlob(addr + 1, (uint8_t *)(&length), 1); + proxy->writeBlob(addr + 1, (uint8_t *)(&length), 1); uint16_t handleGuest = X86ISA::htog(handle); - port->writeBlob(addr + 2, (uint8_t *)(&handleGuest), 2); + proxy->writeBlob(addr + 2, (uint8_t *)(&handleGuest), 2); return length + getStringLength(); } @@ -93,7 +93,7 @@ X86ISA::SMBios::SMBiosStructure::SMBiosStructure(Params * p, uint8_t _type) : void X86ISA::SMBios::SMBiosStructure::writeOutStrings( - FunctionalPort * port, Addr addr) + PortProxy* proxy, Addr addr) { std::vector<std::string>::iterator it; Addr offset = 0; @@ -103,16 +103,16 @@ X86ISA::SMBios::SMBiosStructure::writeOutStrings( // If there are string fields but none of them are used, that's a // special case which is handled by this if. if (strings.size() == 0 && stringFields) { - port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1); + proxy->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1); offset++; } else { for (it = strings.begin(); it != strings.end(); it++) { - port->writeBlob(addr + offset, + proxy->writeBlob(addr + offset, (uint8_t *)it->c_str(), it->length() + 1); offset += it->length() + 1; } } - port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1); + proxy->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1); } int @@ -172,32 +172,32 @@ X86ISA::SMBios::BiosInformation::BiosInformation(Params * p) : } uint16_t -X86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr) +X86ISA::SMBios::BiosInformation::writeOut(PortProxy* proxy, Addr addr) { - uint8_t size = SMBiosStructure::writeOut(port, addr); + uint8_t size = SMBiosStructure::writeOut(proxy, addr); - port->writeBlob(addr + 0x4, (uint8_t *)(&vendor), 1); - port->writeBlob(addr + 0x5, (uint8_t *)(&version), 1); + proxy->writeBlob(addr + 0x4, (uint8_t *)(&vendor), 1); + proxy->writeBlob(addr + 0x5, (uint8_t *)(&version), 1); uint16_t startingAddrSegmentGuest = X86ISA::htog(startingAddrSegment); - port->writeBlob(addr + 0x6, (uint8_t *)(&startingAddrSegmentGuest), 2); + proxy->writeBlob(addr + 0x6, (uint8_t *)(&startingAddrSegmentGuest), 2); - port->writeBlob(addr + 0x8, (uint8_t *)(&releaseDate), 1); - port->writeBlob(addr + 0x9, (uint8_t *)(&romSize), 1); + proxy->writeBlob(addr + 0x8, (uint8_t *)(&releaseDate), 1); + proxy->writeBlob(addr + 0x9, (uint8_t *)(&romSize), 1); uint64_t characteristicsGuest = X86ISA::htog(characteristics); - port->writeBlob(addr + 0xA, (uint8_t *)(&characteristicsGuest), 8); + proxy->writeBlob(addr + 0xA, (uint8_t *)(&characteristicsGuest), 8); uint16_t characteristicExtBytesGuest = X86ISA::htog(characteristicExtBytes); - port->writeBlob(addr + 0x12, (uint8_t *)(&characteristicExtBytesGuest), 2); + proxy->writeBlob(addr + 0x12, (uint8_t *)(&characteristicExtBytesGuest), 2); - port->writeBlob(addr + 0x14, (uint8_t *)(&majorVer), 1); - port->writeBlob(addr + 0x15, (uint8_t *)(&minorVer), 1); - port->writeBlob(addr + 0x16, (uint8_t *)(&embContFirmwareMajor), 1); - port->writeBlob(addr + 0x17, (uint8_t *)(&embContFirmwareMinor), 1); + proxy->writeBlob(addr + 0x14, (uint8_t *)(&majorVer), 1); + proxy->writeBlob(addr + 0x15, (uint8_t *)(&minorVer), 1); + proxy->writeBlob(addr + 0x16, (uint8_t *)(&embContFirmwareMajor), 1); + proxy->writeBlob(addr + 0x17, (uint8_t *)(&embContFirmwareMinor), 1); - writeOutStrings(port, addr + getLength()); + writeOutStrings(proxy, addr + getLength()); return size; } @@ -214,7 +214,7 @@ X86ISA::SMBios::SMBiosTable::SMBiosTable(Params * p) : } void -X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr, +X86ISA::SMBios::SMBiosTable::writeOut(PortProxy* proxy, Addr addr, Addr &headerSize, Addr &structSize) { headerSize = 0x1F; @@ -224,26 +224,26 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr, */ uint8_t mainChecksum = 0; - port->writeBlob(addr, (uint8_t *)smbiosHeader.anchorString, 4); + proxy->writeBlob(addr, (uint8_t *)smbiosHeader.anchorString, 4); for (int i = 0; i < 4; i++) mainChecksum += smbiosHeader.anchorString[i]; // The checksum goes here, but we're figuring it out as we go. - port->writeBlob(addr + 0x5, + proxy->writeBlob(addr + 0x5, (uint8_t *)(&smbiosHeader.entryPointLength), 1); mainChecksum += smbiosHeader.entryPointLength; - port->writeBlob(addr + 0x6, + proxy->writeBlob(addr + 0x6, (uint8_t *)(&smbiosHeader.majorVersion), 1); mainChecksum += smbiosHeader.majorVersion; - port->writeBlob(addr + 0x7, + proxy->writeBlob(addr + 0x7, (uint8_t *)(&smbiosHeader.minorVersion), 1); mainChecksum += smbiosHeader.minorVersion; // Maximum structure size goes here, but we'll figure it out later. - port->writeBlob(addr + 0xA, + proxy->writeBlob(addr + 0xA, (uint8_t *)(&smbiosHeader.entryPointRevision), 1); mainChecksum += smbiosHeader.entryPointRevision; - port->writeBlob(addr + 0xB, + proxy->writeBlob(addr + 0xB, (uint8_t *)(&smbiosHeader.formattedArea), 5); for (int i = 0; i < 5; i++) mainChecksum += smbiosHeader.formattedArea[i]; @@ -253,7 +253,7 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr, */ uint8_t intChecksum = 0; - port->writeBlob(addr + 0x10, + proxy->writeBlob(addr + 0x10, (uint8_t *)smbiosHeader.intermediateHeader.anchorString, 5); for (int i = 0; i < 5; i++) intChecksum += smbiosHeader.intermediateHeader.anchorString[i]; @@ -263,20 +263,20 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr, uint32_t tableAddrGuest = X86ISA::htog(smbiosHeader.intermediateHeader.tableAddr); - port->writeBlob(addr + 0x18, (uint8_t *)(&tableAddrGuest), 4); + proxy->writeBlob(addr + 0x18, (uint8_t *)(&tableAddrGuest), 4); for (int i = 0; i < 4; i++) { intChecksum += tableAddrGuest; tableAddrGuest >>= 8; } uint16_t numStructs = X86ISA::gtoh(structures.size()); - port->writeBlob(addr + 0x1C, (uint8_t *)(&numStructs), 2); + proxy->writeBlob(addr + 0x1C, (uint8_t *)(&numStructs), 2); for (int i = 0; i < 2; i++) { intChecksum += numStructs; numStructs >>= 8; } - port->writeBlob(addr + 0x1E, + proxy->writeBlob(addr + 0x1E, (uint8_t *)(&smbiosHeader.intermediateHeader.smbiosBCDRevision), 1); intChecksum += smbiosHeader.intermediateHeader.smbiosBCDRevision; @@ -290,7 +290,7 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr, uint16_t maxSize = 0; std::vector<SMBiosStructure *>::iterator it; for (it = structures.begin(); it != structures.end(); it++) { - uint16_t size = (*it)->writeOut(port, base + offset); + uint16_t size = (*it)->writeOut(proxy, base + offset); if (size > maxSize) maxSize = size; offset += size; @@ -303,7 +303,7 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr, */ maxSize = X86ISA::htog(maxSize); - port->writeBlob(addr + 0x8, (uint8_t *)(&maxSize), 2); + proxy->writeBlob(addr + 0x8, (uint8_t *)(&maxSize), 2); for (int i = 0; i < 2; i++) { mainChecksum += maxSize; maxSize >>= 8; @@ -311,7 +311,7 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr, // Set the checksum mainChecksum = -mainChecksum; - port->writeBlob(addr + 0x4, (uint8_t *)(&mainChecksum), 1); + proxy->writeBlob(addr + 0x4, (uint8_t *)(&mainChecksum), 1); /* * Intermediate header @@ -319,14 +319,14 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr, uint16_t tableSize = offset; tableSize = X86ISA::htog(tableSize); - port->writeBlob(addr + 0x16, (uint8_t *)(&tableSize), 2); + proxy->writeBlob(addr + 0x16, (uint8_t *)(&tableSize), 2); for (int i = 0; i < 2; i++) { intChecksum += tableSize; tableSize >>= 8; } intChecksum = -intChecksum; - port->writeBlob(addr + 0x15, (uint8_t *)(&intChecksum), 1); + proxy->writeBlob(addr + 0x15, (uint8_t *)(&intChecksum), 1); } X86ISA::SMBios::BiosInformation * diff --git a/src/arch/x86/bios/smbios.hh b/src/arch/x86/bios/smbios.hh index b9c35bd09..9fa6cd6dc 100644 --- a/src/arch/x86/bios/smbios.hh +++ b/src/arch/x86/bios/smbios.hh @@ -51,7 +51,7 @@ #include "enums/ExtCharacteristic.hh" #include "sim/sim_object.hh" -class FunctionalPort; +class PortProxy; class X86SMBiosBiosInformationParams; class X86SMBiosSMBiosStructureParams; class X86SMBiosSMBiosTableParams; @@ -89,7 +89,7 @@ class SMBiosStructure : public SimObject return 4; } - virtual uint16_t writeOut(FunctionalPort * port, Addr addr); + virtual uint16_t writeOut(PortProxy* proxy, Addr addr); protected: bool stringFields; @@ -98,7 +98,7 @@ class SMBiosStructure : public SimObject std::vector<std::string> strings; - void writeOutStrings(FunctionalPort * port, Addr addr); + void writeOutStrings(PortProxy* proxy, Addr addr); int getStringLength(); @@ -145,7 +145,7 @@ class BiosInformation : public SMBiosStructure BiosInformation(Params * p); uint8_t getLength() { return 0x18; } - uint16_t writeOut(FunctionalPort * port, Addr addr); + uint16_t writeOut(PortProxy* proxy, Addr addr); }; class SMBiosTable : public SimObject @@ -223,7 +223,7 @@ class SMBiosTable : public SimObject smbiosHeader.intermediateHeader.tableAddr = addr; } - void writeOut(FunctionalPort * port, Addr addr, + void writeOut(PortProxy* proxy, Addr addr, Addr &headerSize, Addr &structSize); }; diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index 28f1ac04d..612244f49 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -351,25 +351,27 @@ X86ISA::Interrupts::recvResponse(PacketPtr pkt) } -void -X86ISA::Interrupts::addressRanges(AddrRangeList &range_list) +AddrRangeList +X86ISA::Interrupts::getAddrRanges() { - range_list.clear(); + AddrRangeList ranges; Range<Addr> range = RangeEx(x86LocalAPICAddress(initialApicId, 0), x86LocalAPICAddress(initialApicId, 0) + PageBytes); - range_list.push_back(range); + ranges.push_back(range); pioAddr = range.start; + return ranges; } -void -X86ISA::Interrupts::getIntAddrRange(AddrRangeList &range_list) +AddrRangeList +X86ISA::Interrupts::getIntAddrRange() { - range_list.clear(); - range_list.push_back(RangeEx(x86InterruptAddress(initialApicId, 0), - x86InterruptAddress(initialApicId, 0) + - PhysAddrAPICRangeSize)); + AddrRangeList ranges; + ranges.push_back(RangeEx(x86InterruptAddress(initialApicId, 0), + x86InterruptAddress(initialApicId, 0) + + PhysAddrAPICRangeSize)); + return ranges; } diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh index 389eb4f42..8567b30f0 100644 --- a/src/arch/x86/interrupts.hh +++ b/src/arch/x86/interrupts.hh @@ -220,8 +220,8 @@ class Interrupts : public BasicPioDevice, IntDev return entry.periodic; } - void addressRanges(AddrRangeList &range_list); - void getIntAddrRange(AddrRangeList &range_list); + AddrRangeList getAddrRanges(); + AddrRangeList getIntAddrRange(); Port *getPort(const std::string &if_name, int idx = -1) { diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc index 5ccb14394..c6faf391b 100644 --- a/src/arch/x86/linux/syscalls.cc +++ b/src/arch/x86/linux/syscalls.cc @@ -59,7 +59,7 @@ unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process, strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->machine, "x86_64"); - name.copyOut(tc->getMemPort()); + name.copyOut(tc->getMemProxy()); return 0; } @@ -81,7 +81,7 @@ archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, int code = process->getSyscallArg(tc, index); uint64_t addr = process->getSyscallArg(tc, index); uint64_t fsBase, gsBase; - TranslatingPort *p = tc->getMemPort(); + SETranslatingPortProxy* p = tc->getMemProxy(); switch(code) { //Each of these valid options should actually check addr. @@ -149,10 +149,10 @@ setThreadArea32Func(SyscallDesc *desc, int callnum, gdt(x86lp->gdtStart() + minTLSEntry * sizeof(uint64_t), numTLSEntries * sizeof(uint64_t)); - if (!userDesc.copyIn(tc->getMemPort())) + if (!userDesc.copyIn(tc->getMemProxy())) return -EFAULT; - if (!gdt.copyIn(tc->getMemPort())) + if (!gdt.copyIn(tc->getMemProxy())) panic("Failed to copy in GDT for %s.\n", desc->name); if (userDesc->entry_number == (uint32_t)(-1)) { @@ -204,9 +204,9 @@ setThreadArea32Func(SyscallDesc *desc, int callnum, gdt[index] = (uint64_t)segDesc; - if (!userDesc.copyOut(tc->getMemPort())) + if (!userDesc.copyOut(tc->getMemProxy())) return -EFAULT; - if (!gdt.copyOut(tc->getMemPort())) + if (!gdt.copyOut(tc->getMemProxy())) panic("Failed to copy out GDT for %s.\n", desc->name); return 0; diff --git a/src/arch/x86/linux/system.cc b/src/arch/x86/linux/system.cc index 104f93372..a933868d1 100644 --- a/src/arch/x86/linux/system.cc +++ b/src/arch/x86/linux/system.cc @@ -43,7 +43,7 @@ #include "arch/vtophys.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" -#include "mem/physical.hh" +#include "mem/port_proxy.hh" #include "params/LinuxX86System.hh" #include "sim/byteswap.hh" @@ -67,8 +67,8 @@ LinuxX86System::initState() // The location of the real mode data structure. const Addr realModeData = 0x90200; - // A port to write to memory. - FunctionalPort * physPort = threadContexts[0]->getPhysPort(); + // A port proxy to write to memory. + PortProxy* physProxy = threadContexts[0]->getPhysProxy(); /* * Deal with the command line stuff. @@ -82,14 +82,14 @@ LinuxX86System::initState() if (commandLine.length() + 1 > realModeData - commandLineBuff) panic("Command line \"%s\" is longer than %d characters.\n", commandLine, realModeData - commandLineBuff - 1); - physPort->writeBlob(commandLineBuff, + physProxy->writeBlob(commandLineBuff, (uint8_t *)commandLine.c_str(), commandLine.length() + 1); // Generate a pointer of the right size and endianness to put into // commandLinePointer. uint32_t guestCommandLineBuff = X86ISA::htog((uint32_t)commandLineBuff); - physPort->writeBlob(commandLinePointer, + physProxy->writeBlob(commandLinePointer, (uint8_t *)&guestCommandLineBuff, sizeof(guestCommandLineBuff)); /* @@ -127,7 +127,7 @@ LinuxX86System::initState() // A pointer to the buffer for E820 entries. const Addr e820MapPointer = realModeData + 0x2d0; - e820Table->writeTo(physPort, e820MapNrPointer, e820MapPointer); + e820Table->writeTo(getSystemPort(), e820MapNrPointer, e820MapPointer); /* * Pass the location of the real mode data structure to the kernel diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc index c80fe10fc..5b1730f0c 100644 --- a/src/arch/x86/pagetable_walker.cc +++ b/src/arch/x86/pagetable_walker.cc @@ -154,17 +154,8 @@ Walker::WalkerPort::recvFunctional(PacketPtr pkt) } void -Walker::WalkerPort::recvStatusChange(Status status) +Walker::WalkerPort::recvRangeChange() { - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("Unexpected recvStatusChange.\n"); } void diff --git a/src/arch/x86/pagetable_walker.hh b/src/arch/x86/pagetable_walker.hh index b0edc434f..73e185148 100644 --- a/src/arch/x86/pagetable_walker.hh +++ b/src/arch/x86/pagetable_walker.hh @@ -63,26 +63,18 @@ namespace X86ISA { public: WalkerPort(const std::string &_name, Walker * _walker) : - Port(_name, _walker), walker(_walker), - snoopRangeSent(false) + Port(_name, _walker), walker(_walker) {} protected: Walker * walker; - bool snoopRangeSent; - bool recvTiming(PacketPtr pkt); Tick recvAtomic(PacketPtr pkt); void recvFunctional(PacketPtr pkt); - void recvStatusChange(Status status); + void recvRangeChange(); void recvRetry(); - void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { - resp.clear(); - snoop = true; - } + bool isSnooping() { return true; } }; friend class WalkerPort; diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index f5ba787c9..32fc8ca70 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -53,7 +53,6 @@ #include "cpu/thread_context.hh" #include "debug/Stack.hh" #include "mem/page_table.hh" -#include "mem/translating_port.hh" #include "sim/process_impl.hh" #include "sim/syscall_emul.hh" #include "sim/system.hh" diff --git a/src/arch/x86/stacktrace.cc b/src/arch/x86/stacktrace.cc index e2ec04fa7..e3d30d5cd 100644 --- a/src/arch/x86/stacktrace.cc +++ b/src/arch/x86/stacktrace.cc @@ -37,7 +37,7 @@ #include "base/trace.hh" #include "cpu/base.hh" #include "cpu/thread_context.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" #include "sim/system.hh" using namespace std; @@ -48,9 +48,9 @@ namespace X86ISA { Addr addr = 0; - VirtualPort *vp; + FSTranslatingPortProxy* vp; - vp = tc->getVirtPort(); + vp = tc->getVirtProxy(); if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) panic("thread info not compiled into kernel\n"); @@ -82,9 +82,9 @@ namespace X86ISA Addr tsk; - VirtualPort *vp; + FSTranslatingPortProxy* vp; - vp = tc->getVirtPort(); + vp = tc->getVirtProxy(); tsk = vp->readGtoH<Addr>(base + task_off); return tsk; @@ -99,9 +99,9 @@ namespace X86ISA uint16_t pd; - VirtualPort *vp; + FSTranslatingPortProxy* vp; - vp = tc->getVirtPort(); + vp = tc->getVirtProxy(); pd = vp->readGtoH<uint16_t>(task + pid_off); return pd; diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc index d287e3947..ca13fd5ce 100644 --- a/src/arch/x86/system.cc +++ b/src/arch/x86/system.cc @@ -48,7 +48,7 @@ #include "base/intmath.hh" #include "base/trace.hh" #include "cpu/thread_context.hh" -#include "mem/physical.hh" +#include "mem/port_proxy.hh" #include "params/X86System.hh" #include "sim/byteswap.hh" @@ -61,8 +61,6 @@ X86System::X86System(Params *p) : mpConfigTable(p->intel_mp_table), rsdp(p->acpi_description_table_pointer) { - if (kernel->getArch() == ObjectFile::I386) - fatal("Loading a 32 bit x86 kernel is not supported.\n"); } static void @@ -116,6 +114,9 @@ X86System::initState() { System::initState(); + if (kernel->getArch() == ObjectFile::I386) + fatal("Loading a 32 bit x86 kernel is not supported.\n"); + ThreadContext *tc = threadContexts[0]; // This is the boot strap processor (BSP). Initialize it to look like // the boot loader has just turned control over to the 64 bit OS. We @@ -137,8 +138,8 @@ X86System::initState() const int PDPTBits = 9; const int PDTBits = 9; - // Get a port to write the page tables and descriptor tables. - FunctionalPort * physPort = tc->getPhysPort(); + // Get a port proxy to write the page tables and descriptor tables. + PortProxy* physProxy = tc->getPhysProxy(); /* * Set up the gdt. @@ -146,7 +147,7 @@ X86System::initState() uint8_t numGDTEntries = 0; // Place holder at selector 0 uint64_t nullDescriptor = 0; - physPort->writeBlob(GDTBase + numGDTEntries * 8, + physProxy->writeBlob(GDTBase + numGDTEntries * 8, (uint8_t *)(&nullDescriptor), 8); numGDTEntries++; @@ -168,7 +169,7 @@ X86System::initState() //it's beginning in memory and it's actual data, we'll use an //intermediary. uint64_t csDescVal = csDesc; - physPort->writeBlob(GDTBase + numGDTEntries * 8, + physProxy->writeBlob(GDTBase + numGDTEntries * 8, (uint8_t *)(&csDescVal), 8); numGDTEntries++; @@ -191,7 +192,7 @@ X86System::initState() dsDesc.limitHigh = 0xF; dsDesc.limitLow = 0xFF; uint64_t dsDescVal = dsDesc; - physPort->writeBlob(GDTBase + numGDTEntries * 8, + physProxy->writeBlob(GDTBase + numGDTEntries * 8, (uint8_t *)(&dsDescVal), 8); numGDTEntries++; @@ -219,7 +220,7 @@ X86System::initState() tssDesc.limitHigh = 0xF; tssDesc.limitLow = 0xFF; uint64_t tssDescVal = tssDesc; - physPort->writeBlob(GDTBase + numGDTEntries * 8, + physProxy->writeBlob(GDTBase + numGDTEntries * 8, (uint8_t *)(&tssDescVal), 8); numGDTEntries++; @@ -249,24 +250,24 @@ X86System::initState() // read/write, user, not present uint64_t pml4e = X86ISA::htog(0x6); for (int offset = 0; offset < (1 << PML4Bits) * 8; offset += 8) { - physPort->writeBlob(PageMapLevel4 + offset, (uint8_t *)(&pml4e), 8); + physProxy->writeBlob(PageMapLevel4 + offset, (uint8_t *)(&pml4e), 8); } // Point to the only PDPT pml4e = X86ISA::htog(0x7 | PageDirPtrTable); - physPort->writeBlob(PageMapLevel4, (uint8_t *)(&pml4e), 8); + physProxy->writeBlob(PageMapLevel4, (uint8_t *)(&pml4e), 8); // Page Directory Pointer Table // read/write, user, not present uint64_t pdpe = X86ISA::htog(0x6); for (int offset = 0; offset < (1 << PDPTBits) * 8; offset += 8) { - physPort->writeBlob(PageDirPtrTable + offset, + physProxy->writeBlob(PageDirPtrTable + offset, (uint8_t *)(&pdpe), 8); } // Point to the PDTs for (int table = 0; table < NumPDTs; table++) { pdpe = X86ISA::htog(0x7 | PageDirTable[table]); - physPort->writeBlob(PageDirPtrTable + table * 8, + physProxy->writeBlob(PageDirPtrTable + table * 8, (uint8_t *)(&pdpe), 8); } @@ -278,7 +279,7 @@ X86System::initState() for (int offset = 0; offset < (1 << PDTBits) * 8; offset += 8) { // read/write, user, present, 4MB uint64_t pdte = X86ISA::htog(0x87 | base); - physPort->writeBlob(PageDirTable[table] + offset, + physProxy->writeBlob(PageDirTable[table] + offset, (uint8_t *)(&pdte), 8); base += pageSize; } @@ -341,8 +342,8 @@ void X86System::writeOutSMBiosTable(Addr header, Addr &headerSize, Addr &structSize, Addr table) { - // Get a port to write the table and header to memory. - FunctionalPort * physPort = threadContexts[0]->getPhysPort(); + // Get a port proxy to write the table and header to memory. + PortProxy* physProxy = threadContexts[0]->getPhysProxy(); // If the table location isn't specified, just put it after the header. // The header size as of the 2.5 SMBios specification is 0x1F bytes @@ -350,7 +351,7 @@ X86System::writeOutSMBiosTable(Addr header, table = header + 0x1F; smbiosTable->setTableAddr(table); - smbiosTable->writeOut(physPort, header, headerSize, structSize); + smbiosTable->writeOut(physProxy, header, headerSize, structSize); // Do some bounds checking to make sure we at least didn't step on // ourselves. @@ -362,8 +363,8 @@ void X86System::writeOutMPTable(Addr fp, Addr &fpSize, Addr &tableSize, Addr table) { - // Get a port to write the table and header to memory. - FunctionalPort * physPort = threadContexts[0]->getPhysPort(); + // Get a port proxy to write the table and header to memory. + PortProxy* physProxy = threadContexts[0]->getPhysProxy(); // If the table location isn't specified and it exists, just put // it after the floating pointer. The fp size as of the 1.4 Intel MP @@ -374,9 +375,9 @@ X86System::writeOutMPTable(Addr fp, mpFloatingPointer->setTableAddr(table); } - fpSize = mpFloatingPointer->writeOut(physPort, fp); + fpSize = mpFloatingPointer->writeOut(physProxy, fp); if (mpConfigTable) - tableSize = mpConfigTable->writeOut(physPort, table); + tableSize = mpConfigTable->writeOut(physProxy, table); else tableSize = 0; diff --git a/src/base/debug.cc b/src/base/debug.cc index 71675aada..ba154f377 100644 --- a/src/base/debug.cc +++ b/src/base/debug.cc @@ -134,7 +134,7 @@ struct AllFlags : public Flag FlagsMap::iterator end = allFlags().end(); for (; i != end; ++i) if (i->second != this) - i->second->enable(); + i->second->disable(); } }; diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc index 1b1841a45..80800e862 100644 --- a/src/base/loader/elf_object.cc +++ b/src/base/loader/elf_object.cc @@ -414,15 +414,15 @@ ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask) } bool -ElfObject::loadSections(Port *memPort, Addr addrMask) +ElfObject::loadSections(PortProxy* memProxy, Addr addrMask) { - if (!ObjectFile::loadSections(memPort, addrMask)) + if (!ObjectFile::loadSections(memProxy, addrMask)) return false; vector<Segment>::iterator extraIt; for (extraIt = extraSegments.begin(); extraIt != extraSegments.end(); extraIt++) { - if (!loadSection(&(*extraIt), memPort, addrMask)) { + if (!loadSection(&(*extraIt), memProxy, addrMask)) { return false; } } diff --git a/src/base/loader/elf_object.hh b/src/base/loader/elf_object.hh index fe75927c5..afb61c21d 100644 --- a/src/base/loader/elf_object.hh +++ b/src/base/loader/elf_object.hh @@ -65,7 +65,7 @@ class ElfObject : public ObjectFile public: virtual ~ElfObject() {} - bool loadSections(Port *memPort, + bool loadSections(PortProxy *memProxy, Addr addrMask = std::numeric_limits<Addr>::max()); virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask = std::numeric_limits<Addr>::max()); diff --git a/src/base/loader/hex_file.cc b/src/base/loader/hex_file.cc index 854834b2b..d38c0fb62 100755 --- a/src/base/loader/hex_file.cc +++ b/src/base/loader/hex_file.cc @@ -36,7 +36,7 @@ #include "base/loader/hex_file.hh" #include "base/loader/symtab.hh" #include "base/cprintf.hh" -#include "mem/translating_port.hh" +#include "mem/port_proxy.hh" using namespace std; /* @@ -59,7 +59,7 @@ HexFile::~HexFile() } bool -HexFile::loadSections(Port *memPort) +HexFile::loadSections(PortProxy* memProxy) { char Line[64]; Addr MemAddr; @@ -71,7 +71,7 @@ HexFile::loadSections(Port *memPort) parseLine(Line, &MemAddr, &Data); if (MemAddr != 0) { // Now, write to memory - memPort->writeBlob(MemAddr << 2, (uint8_t *)&Data, sizeof(Data)); + memProxy->writeBlob(MemAddr << 2, (uint8_t *)&Data, sizeof(Data)); } } return true; diff --git a/src/base/loader/hex_file.hh b/src/base/loader/hex_file.hh index 87a7eb0f3..514a02a1e 100755 --- a/src/base/loader/hex_file.hh +++ b/src/base/loader/hex_file.hh @@ -37,7 +37,7 @@ #include "base/types.hh" -class Port; +class PortProxy; class HexFile { @@ -52,7 +52,7 @@ class HexFile virtual ~HexFile(); void close(); - bool loadSections(Port *memPort); + bool loadSections(PortProxy* memProxy); }; #endif // __BASE_LOADER_HEX_FILE_HH__ diff --git a/src/base/loader/object_file.cc b/src/base/loader/object_file.cc index 9dcbd7936..eaf0443bf 100644 --- a/src/base/loader/object_file.cc +++ b/src/base/loader/object_file.cc @@ -45,7 +45,7 @@ #include "base/loader/raw_object.hh" #include "base/loader/symtab.hh" #include "base/cprintf.hh" -#include "mem/translating_port.hh" +#include "mem/port_proxy.hh" using namespace std; @@ -65,16 +65,16 @@ ObjectFile::~ObjectFile() bool -ObjectFile::loadSection(Section *sec, Port *memPort, Addr addrMask) +ObjectFile::loadSection(Section *sec, PortProxy* memProxy, Addr addrMask) { if (sec->size != 0) { Addr addr = sec->baseAddr & addrMask; if (sec->fileImage) { - memPort->writeBlob(addr, sec->fileImage, sec->size); + memProxy->writeBlob(addr, sec->fileImage, sec->size); } else { // no image: must be bss - memPort->memsetBlob(addr, 0, sec->size); + memProxy->memsetBlob(addr, 0, sec->size); } } return true; @@ -82,11 +82,11 @@ ObjectFile::loadSection(Section *sec, Port *memPort, Addr addrMask) bool -ObjectFile::loadSections(Port *memPort, Addr addrMask) +ObjectFile::loadSections(PortProxy* memProxy, Addr addrMask) { - return (loadSection(&text, memPort, addrMask) - && loadSection(&data, memPort, addrMask) - && loadSection(&bss, memPort, addrMask)); + return (loadSection(&text, memProxy, addrMask) + && loadSection(&data, memProxy, addrMask) + && loadSection(&bss, memProxy, addrMask)); } diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh index bffab0cc5..ce58a2c4f 100644 --- a/src/base/loader/object_file.hh +++ b/src/base/loader/object_file.hh @@ -37,7 +37,7 @@ #include "base/types.hh" -class Port; +class PortProxy; class SymbolTable; class ObjectFile @@ -83,7 +83,7 @@ class ObjectFile void close(); - virtual bool loadSections(Port *memPort, Addr addrMask = + virtual bool loadSections(PortProxy *memProxy, Addr addrMask = std::numeric_limits<Addr>::max()); virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask = std::numeric_limits<Addr>::max()) = 0; @@ -111,7 +111,7 @@ class ObjectFile Section data; Section bss; - bool loadSection(Section *sec, Port *memPort, Addr addrMask); + bool loadSection(Section *sec, PortProxy* memProxy, Addr addrMask); void setGlobalPointer(Addr global_ptr) { globalPtr = global_ptr; } public: diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index 021ef3684..7b38753e2 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -132,8 +132,8 @@ #include "cpu/thread_context.hh" #include "debug/GDBAll.hh" #include "mem/port.hh" -#include "mem/translating_port.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" +#include "mem/se_translating_port_proxy.hh" #include "sim/full_system.hh" #include "sim/system.hh" @@ -461,10 +461,10 @@ BaseRemoteGDB::read(Addr vaddr, size_t size, char *data) DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size); if (FullSystem) { - VirtualPort *port = context->getVirtPort(); + FSTranslatingPortProxy *port = context->getVirtProxy(); port->readBlob(vaddr, (uint8_t*)data, size); } else { - TranslatingPort *port = context->getMemPort(); + SETranslatingPortProxy *port = context->getMemProxy(); port->readBlob(vaddr, (uint8_t*)data, size); } @@ -504,10 +504,10 @@ BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data) DPRINTFNR("\n"); } if (FullSystem) { - VirtualPort *port = context->getVirtPort(); + FSTranslatingPortProxy *port = context->getVirtProxy(); port->writeBlob(vaddr, (uint8_t*)data, size); } else { - TranslatingPort *port = context->getMemPort(); + SETranslatingPortProxy *port = context->getMemProxy(); port->writeBlob(vaddr, (uint8_t*)data, size); delete port; } diff --git a/src/base/remote_gdb.hh b/src/base/remote_gdb.hh index 7c1228e59..899c7c29e 100644 --- a/src/base/remote_gdb.hh +++ b/src/base/remote_gdb.hh @@ -216,7 +216,7 @@ class BaseRemoteGDB bool insertSoftBreak(Addr addr, size_t len); bool removeSoftBreak(Addr addr, size_t len); - bool insertHardBreak(Addr addr, size_t len); + virtual bool insertHardBreak(Addr addr, size_t len); bool removeHardBreak(Addr addr, size_t len); protected: diff --git a/src/cpu/BaseCPU.py b/src/cpu/BaseCPU.py index 50a8501e2..19464acbc 100644 --- a/src/cpu/BaseCPU.py +++ b/src/cpu/BaseCPU.py @@ -138,9 +138,12 @@ class BaseCPU(MemObject): tracer = Param.InstTracer(default_tracer, "Instruction tracer") - _cached_ports = [] + icache_port = Port("Instruction Port") + dcache_port = Port("Data Port") + _cached_ports = ['icache_port', 'dcache_port'] + if buildEnv['TARGET_ISA'] in ['x86', 'arm']: - _cached_ports = ["itb.walker.port", "dtb.walker.port"] + _cached_ports += ["itb.walker.port", "dtb.walker.port"] _uncached_ports = [] if buildEnv['TARGET_ISA'] == 'x86': diff --git a/src/cpu/base.cc b/src/cpu/base.cc index a0785ac10..d174995a9 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * Copyright (c) 2011 Regents of the University of California * All rights reserved. @@ -470,3 +482,36 @@ BaseCPU::traceFunctionsInternal(Addr pc) functionEntryTick = curTick(); } } + +bool +BaseCPU::CpuPort::recvTiming(PacketPtr pkt) +{ + panic("BaseCPU doesn't expect recvTiming callback!"); + return true; +} + +void +BaseCPU::CpuPort::recvRetry() +{ + panic("BaseCPU doesn't expect recvRetry callback!"); +} + +Tick +BaseCPU::CpuPort::recvAtomic(PacketPtr pkt) +{ + panic("BaseCPU doesn't expect recvAtomic callback!"); + return curTick(); +} + +void +BaseCPU::CpuPort::recvFunctional(PacketPtr pkt) +{ + // No internal storage to update (in the general case). In the + // long term this should never be called, but that assumed a split + // into master/slave and request/response. +} + +void +BaseCPU::CpuPort::recvRangeChange() +{ +} diff --git a/src/cpu/base.hh b/src/cpu/base.hh index a4ffb4716..41c79dff6 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * Copyright (c) 2011 Regents of the University of California * All rights reserved. @@ -92,6 +104,42 @@ class BaseCPU : public MemObject // therefore no setCpuId() method is provided int _cpuId; + /** + * Define a base class for the CPU ports (instruction and data) + * that is refined in the subclasses. This class handles the + * common cases, i.e. the functional accesses and the status + * changes and address range queries. The default behaviour for + * both atomic and timing access is to panic and the corresponding + * subclasses have to override these methods. + */ + class CpuPort : public Port + { + public: + + /** + * Create a CPU port with a name and a structural owner. + * + * @param _name port name including the owner + * @param _name structural owner of this port + */ + CpuPort(const std::string& _name, MemObject* _owner) : + Port(_name, _owner) + { } + + protected: + + virtual bool recvTiming(PacketPtr pkt); + + virtual Tick recvAtomic(PacketPtr pkt); + + virtual void recvRetry(); + + void recvFunctional(PacketPtr pkt); + + void recvRangeChange(); + + }; + public: /** Reads this CPU's ID. */ int cpuId() { return _cpuId; } diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index 6c3c50a9c..178ded80e 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -98,12 +98,12 @@ class CheckerThreadContext : public ThreadContext Process *getProcessPtr() { return actualTC->getProcessPtr(); } - TranslatingPort *getMemPort() { return actualTC->getMemPort(); } + PortProxy* getPhysProxy() { return actualTC->getPhysProxy(); } - VirtualPort *getVirtPort() - { return actualTC->getVirtPort(); } + FSTranslatingPortProxy* getVirtProxy() + { return actualTC->getVirtProxy(); } - FunctionalPort *getPhysPort() { return actualTC->getPhysPort(); } + SETranslatingPortProxy* getMemProxy() { return actualTC->getMemProxy(); } Status status() const { return actualTC->status(); } diff --git a/src/cpu/inorder/InOrderCPU.py b/src/cpu/inorder/InOrderCPU.py index 4766a1ac1..40af48b19 100644 --- a/src/cpu/inorder/InOrderCPU.py +++ b/src/cpu/inorder/InOrderCPU.py @@ -44,9 +44,6 @@ class InOrderCPU(BaseCPU): fetchMemPort = Param.String("icache_port" , "Name of Memory Port to get instructions from") dataMemPort = Param.String("dcache_port" , "Name of Memory Port to get data from") - icache_port = Port("Instruction Port") - dcache_port = Port("Data Port") - _cached_ports = ['icache_port', 'dcache_port'] fetchBuffSize = Param.Unsigned(4, "Fetch Buffer Size (Number of Cache Blocks Stored)") memBlockSize = Param.Unsigned(64, "Memory Block Size") diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 010bdb512..5a14e92a7 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -54,7 +54,6 @@ #include "debug/RefCount.hh" #include "debug/SkedCache.hh" #include "debug/Quiesce.hh" -#include "mem/translating_port.hh" #include "params/InOrderCPU.hh" #include "sim/full_system.hh" #include "sim/process.hh" @@ -758,6 +757,8 @@ InOrderCPU::init() for (ThreadID tid = 0; tid < numThreads; tid++) { ThreadContext *src_tc = threadContexts[tid]; TheISA::initCPU(src_tc, src_tc->contextId()); + // Initialise the ThreadContext's memory proxies + thread[tid]->initMemProxies(thread[tid]->getTC()); } } @@ -860,7 +861,6 @@ InOrderCPU::getInterrupts() return interrupts->getInterrupt(threadContexts[0]); } - void InOrderCPU::processInterrupts(Fault interrupt) { @@ -880,16 +880,6 @@ InOrderCPU::processInterrupts(Fault interrupt) } void -InOrderCPU::updateMemPorts() -{ - // Update all ThreadContext's memory ports (Functional/Virtual - // Ports) - ThreadID size = thread.size(); - for (ThreadID i = 0; i < size; ++i) - thread[i]->connectMemPorts(thread[i]->getTC()); -} - -void InOrderCPU::trapContext(Fault fault, ThreadID tid, DynInstPtr inst, int delay) { scheduleCpuEvent(Trap, fault, tid, inst, delay); diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index bbd02e027..7d22bc902 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -428,10 +428,6 @@ class InOrderCPU : public BaseCPU /** Halts the CPU. */ void halt() { panic("Halt not implemented!\n"); } - /** Update the Virt and Phys ports of all ThreadContexts to - * reflect change in memory connections. */ - void updateMemPorts(); - /** Check if this address is a valid instruction address. */ bool validInstAddr(Addr addr) { return true; } diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 90ed83d68..0ab9f0579 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -82,17 +82,8 @@ CacheUnit::CachePort::recvFunctional(PacketPtr pkt) } void -CacheUnit::CachePort::recvStatusChange(Status status) +CacheUnit::CachePort::recvRangeChange() { - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("CacheUnit::CachePort doesn't expect recvStatusChange callback!"); } bool @@ -145,18 +136,6 @@ CacheUnit::tlb() } -void -CacheUnit::CachePort::setPeer(Port *port) -{ - Port::setPeer(port); - - // Update the ThreadContext's memory ports (Functional/Virtual - // Ports) - if (cachePortUnit->resName == "dcache_port") { - cachePortUnit->cpu->updateMemPorts(); - } -} - Port * CacheUnit::getPort(const string &if_name, int idx) { diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh index a8dde512b..2155c920c 100644 --- a/src/cpu/inorder/resources/cache_unit.hh +++ b/src/cpu/inorder/resources/cache_unit.hh @@ -90,13 +90,9 @@ class CacheUnit : public Resource CachePort(CacheUnit *_cachePortUnit) : Port(_cachePortUnit->name() + "-cache-port", (MemObject*)_cachePortUnit->cpu), - cachePortUnit(_cachePortUnit), snoopRangeSent(false) + cachePortUnit(_cachePortUnit) { } - bool snoopRangeSent; - - void setPeer(Port *port); - protected: /** Atomic version of receive. Panics. */ Tick recvAtomic(PacketPtr pkt); @@ -104,13 +100,8 @@ class CacheUnit : public Resource /** Functional version of receive.*/ void recvFunctional(PacketPtr pkt); - /** Receives status change. Other than range changing, panics. */ - void recvStatusChange(Status status); - - /** Returns the address ranges of this device. */ - void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = true; } + /** Receives range changes. */ + void recvRangeChange(); /** Timing version of receive */ bool recvTiming(PacketPtr pkt); diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc index 5f141a1b3..acfcf0939 100644 --- a/src/cpu/inorder/thread_context.cc +++ b/src/cpu/inorder/thread_context.cc @@ -38,10 +38,10 @@ using namespace TheISA; -VirtualPort * -InOrderThreadContext::getVirtPort() +FSTranslatingPortProxy* +InOrderThreadContext::getVirtProxy() { - return thread->getVirtPort(); + return thread->getVirtProxy(); } void diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index 84d62137e..7fe0fb5ef 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -117,8 +117,12 @@ class InOrderThreadContext : public ThreadContext TheISA::Kernel::Statistics *getKernelStats() { return thread->kernelStats; } - void connectMemPorts(ThreadContext *tc) - { thread->connectMemPorts(tc); } + PortProxy* getPhysProxy() { return thread->getPhysProxy(); } + + FSTranslatingPortProxy* getVirtProxy(); + + void initMemProxies(ThreadContext *tc) + { thread->initMemProxies(tc); } /** Dumps the function profiling information. * @todo: Implement. @@ -142,14 +146,11 @@ class InOrderThreadContext : public ThreadContext return this->thread->quiesceEvent; } + SETranslatingPortProxy* getMemProxy() { return thread->getMemProxy(); } + /** Returns a pointer to this thread's process. */ Process *getProcessPtr() { return thread->getProcessPtr(); } - TranslatingPort *getMemPort() { return thread->getMemPort(); } - - VirtualPort *getVirtPort(); - FunctionalPort *getPhysPort() { return thread->getPhysPort(); } - /** Returns this thread's status. */ Status status() const { return thread->status(); } diff --git a/src/cpu/o3/O3CPU.py b/src/cpu/o3/O3CPU.py index 1d8950a73..ffc817e81 100644 --- a/src/cpu/o3/O3CPU.py +++ b/src/cpu/o3/O3CPU.py @@ -49,9 +49,6 @@ class DerivO3CPU(BaseCPU): checker.dtb = Parent.dtb cachePorts = Param.Unsigned(200, "Cache Ports") - icache_port = Port("Instruction Port") - dcache_port = Port("Data Port") - _cached_ports = BaseCPU._cached_ports + ['icache_port', 'dcache_port'] decodeToFetchDelay = Param.Unsigned(1, "Decode to fetch delay") renameToFetchDelay = Param.Unsigned(1 ,"Rename to fetch delay") diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 5d3af6c70..ef08c96f4 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2006 The Regents of The University of Michigan * Copyright (c) 2011 Regents of the University of California * All rights reserved. @@ -76,6 +88,42 @@ BaseO3CPU::regStats() BaseCPU::regStats(); } +template<class Impl> +bool +FullO3CPU<Impl>::IcachePort::recvTiming(PacketPtr pkt) +{ + DPRINTF(O3CPU, "Fetch unit received timing\n"); + if (pkt->isResponse()) { + // We shouldn't ever get a block in ownership state + assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted())); + + fetch->processCacheCompletion(pkt); + } + //else Snooped a coherence request, just return + return true; +} + +template<class Impl> +void +FullO3CPU<Impl>::IcachePort::recvRetry() +{ + fetch->recvRetry(); +} + +template <class Impl> +bool +FullO3CPU<Impl>::DcachePort::recvTiming(PacketPtr pkt) +{ + return lsq->recvTiming(pkt); +} + +template <class Impl> +void +FullO3CPU<Impl>::DcachePort::recvRetry() +{ + lsq->recvRetry(); +} + template <class Impl> FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) : Event(CPU_Tick_Pri), cpu(c) @@ -191,6 +239,9 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) TheISA::NumMiscRegs * numThreads, TheISA::ZeroReg), + icachePort(&fetch, this), + dcachePort(&iew.ldstQueue, this), + timeBuffer(params->backComSize, params->forwardComSize), fetchQueue(params->backComSize, params->forwardComSize), decodeQueue(params->backComSize, params->forwardComSize), @@ -215,6 +266,7 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params) if (params->checker) { BaseCPU *temp_checker = params->checker; checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker); + checker->setIcachePort(&icachePort); checker->setSystem(params->system); } else { checker = NULL; @@ -524,9 +576,9 @@ Port * FullO3CPU<Impl>::getPort(const std::string &if_name, int idx) { if (if_name == "dcache_port") - return iew.getDcachePort(); + return &dcachePort; else if (if_name == "icache_port") - return fetch.getIcachePort(); + return &icachePort; else panic("No Such Port\n"); } @@ -600,10 +652,19 @@ FullO3CPU<Impl>::init() for (ThreadID tid = 0; tid < numThreads; ++tid) thread[tid]->inSyscall = true; + // this CPU could still be unconnected if we are restoring from a + // checkpoint and this CPU is to be switched in, thus we can only + // do this here if the instruction port is actually connected, if + // not we have to do it as part of takeOverFrom + if (icachePort.isConnected()) + fetch.setIcache(); + if (FullSystem) { for (ThreadID tid = 0; tid < numThreads; tid++) { ThreadContext *src_tc = threadContexts[tid]; TheISA::initCPU(src_tc, src_tc->contextId()); + // Initialise the ThreadContext's memory proxies + thread[tid]->initMemProxies(thread[tid]->getTC()); } } @@ -969,17 +1030,6 @@ FullO3CPU<Impl>::processInterrupts(Fault interrupt) template <class Impl> void -FullO3CPU<Impl>::updateMemPorts() -{ - // Update all ThreadContext's memory ports (Functional/Virtual - // Ports) - ThreadID size = thread.size(); - for (ThreadID i = 0; i < size; ++i) - thread[i]->connectMemPorts(thread[i]->getTC()); -} - -template <class Impl> -void FullO3CPU<Impl>::trap(Fault fault, ThreadID tid, StaticInstPtr inst) { // Pass the thread's TC into the invoke method. @@ -1166,7 +1216,7 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU) activityRec.reset(); - BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort()); + BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort); fetch.takeOverFrom(); decode.takeOverFrom(); diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 7580106ad..165144c1b 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2005 The Regents of The University of Michigan * Copyright (c) 2011 Regents of the University of California * All rights reserved. @@ -117,6 +129,68 @@ class FullO3CPU : public BaseO3CPU Status _threadStatus[Impl::MaxThreads]; private: + + /** + * IcachePort class for instruction fetch. + */ + class IcachePort : public CpuPort + { + protected: + /** Pointer to fetch. */ + DefaultFetch<Impl> *fetch; + + public: + /** Default constructor. */ + IcachePort(DefaultFetch<Impl> *_fetch, FullO3CPU<Impl>* _cpu) + : CpuPort(_fetch->name() + "-iport", _cpu), fetch(_fetch) + { } + + protected: + + /** Timing version of receive. Handles setting fetch to the + * proper status to start fetching. */ + virtual bool recvTiming(PacketPtr pkt); + + /** Handles doing a retry of a failed fetch. */ + virtual void recvRetry(); + }; + + /** + * DcachePort class for the load/store queue. + */ + class DcachePort : public CpuPort + { + protected: + + /** Pointer to LSQ. */ + LSQ<Impl> *lsq; + + public: + /** Default constructor. */ + DcachePort(LSQ<Impl> *_lsq, FullO3CPU<Impl>* _cpu) + : CpuPort(_lsq->name() + "-dport", _cpu), lsq(_lsq) + { } + + protected: + + /** Timing version of receive. Handles writing back and + * completing the load or store that has returned from + * memory. */ + virtual bool recvTiming(PacketPtr pkt); + + /** Handles doing a retry of the previous send. */ + virtual void recvRetry(); + + /** + * As this CPU requires snooping to maintain the load store queue + * change the behaviour from the base CPU port. + * + * @return true since we have to snoop + */ + virtual bool isSnooping() + { return true; } + }; + class TickEvent : public Event { private: @@ -391,10 +465,6 @@ class FullO3CPU : public BaseO3CPU /** Halts the CPU. */ void halt() { panic("Halt not implemented!\n"); } - /** Update the Virt and Phys ports of all ThreadContexts to - * reflect change in memory connections. */ - void updateMemPorts(); - /** Check if this address is a valid instruction address. */ bool validInstAddr(Addr addr) { return true; } @@ -565,6 +635,12 @@ class FullO3CPU : public BaseO3CPU TheISA::ISA isa[Impl::MaxThreads]; + /** Instruction port. Note that it has to appear after the fetch stage. */ + IcachePort icachePort; + + /** Data port. Note that it has to appear after the iew stages */ + DcachePort dcachePort; + public: /** Enum to give each stage a specific index, so when calling * activateStage() or deactivateStage(), they can specify which stage @@ -701,8 +777,11 @@ class FullO3CPU : public BaseO3CPU data, store_idx); } + /** Used by the fetch unit to get a hold of the instruction port. */ + Port* getIcachePort() { return &icachePort; } + /** Get the dcache port (used to find block size for translations). */ - Port *getDcachePort() { return this->iew.ldstQueue.getDcachePort(); } + Port* getDcachePort() { return &dcachePort; } Addr lockAddr; diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index d09d7f680..f5d275593 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 ARM Limited + * Copyright (c) 2010-2011 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -85,48 +85,6 @@ class DefaultFetch typedef TheISA::MachInst MachInst; typedef TheISA::ExtMachInst ExtMachInst; - /** IcachePort class for DefaultFetch. Handles doing the - * communication with the cache/memory. - */ - class IcachePort : public Port - { - protected: - /** Pointer to fetch. */ - DefaultFetch<Impl> *fetch; - - public: - /** Default constructor. */ - IcachePort(DefaultFetch<Impl> *_fetch) - : Port(_fetch->name() + "-iport", _fetch->cpu), fetch(_fetch) - { } - - bool snoopRangeSent; - - virtual void setPeer(Port *port); - - protected: - /** Atomic version of receive. Panics. */ - virtual Tick recvAtomic(PacketPtr pkt); - - /** Functional version of receive. Panics. */ - virtual void recvFunctional(PacketPtr pkt); - - /** Receives status change. Other than range changing, panics. */ - virtual void recvStatusChange(Status status); - - /** Returns the address ranges of this device. */ - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = true; } - - /** Timing version of receive. Handles setting fetch to the - * proper status to start fetching. */ - virtual bool recvTiming(PacketPtr pkt); - - /** Handles doing a retry of a failed fetch. */ - virtual void recvRetry(); - }; - class FetchTranslation : public BaseTLB::Translation { protected: @@ -248,9 +206,6 @@ class DefaultFetch /** Registers statistics. */ void regStats(); - /** Returns the icache port. */ - Port *getIcachePort() { return icachePort; } - /** Sets the main backwards communication time buffer pointer. */ void setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer); @@ -266,6 +221,9 @@ class DefaultFetch /** Tells the fetch stage that the Icache is set. */ void setIcache(); + /** Handles retrying the fetch access. */ + void recvRetry(); + /** Processes cache completion event. */ void processCacheCompletion(PacketPtr pkt); @@ -389,9 +347,6 @@ class DefaultFetch StaticInstPtr curMacroop, TheISA::PCState thisPC, TheISA::PCState nextPC, bool trace); - /** Handles retrying the fetch access. */ - void recvRetry(); - /** Returns the appropriate thread to fetch, given the fetch policy. */ ThreadID getFetchingThread(FetchPriority &fetch_priority); @@ -440,9 +395,6 @@ class DefaultFetch /** Wire used to write any information heading to decode. */ typename TimeBuffer<FetchStruct>::wire toDecode; - /** Icache interface. */ - IcachePort *icachePort; - /** BPredUnit. */ BPredUnit branchPred; diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 28fd434fe..1b82f8a4c 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 ARM Limited + * Copyright (c) 2010-2011 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -69,68 +69,6 @@ using namespace std; template<class Impl> -void -DefaultFetch<Impl>::IcachePort::setPeer(Port *port) -{ - Port::setPeer(port); - - fetch->setIcache(); -} - -template<class Impl> -Tick -DefaultFetch<Impl>::IcachePort::recvAtomic(PacketPtr pkt) -{ - panic("DefaultFetch doesn't expect recvAtomic callback!"); - return curTick(); -} - -template<class Impl> -void -DefaultFetch<Impl>::IcachePort::recvFunctional(PacketPtr pkt) -{ - DPRINTF(Fetch, "DefaultFetch doesn't update its state from a " - "functional call.\n"); -} - -template<class Impl> -void -DefaultFetch<Impl>::IcachePort::recvStatusChange(Status status) -{ - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("DefaultFetch doesn't expect recvStatusChange callback!"); -} - -template<class Impl> -bool -DefaultFetch<Impl>::IcachePort::recvTiming(PacketPtr pkt) -{ - DPRINTF(Fetch, "Received timing\n"); - if (pkt->isResponse()) { - // We shouldn't ever get a block in ownership state - assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted())); - - fetch->processCacheCompletion(pkt); - } - //else Snooped a coherence request, just return - return true; -} - -template<class Impl> -void -DefaultFetch<Impl>::IcachePort::recvRetry() -{ - fetch->recvRetry(); -} - -template<class Impl> DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params) : cpu(_cpu), branchPred(params), @@ -189,17 +127,6 @@ DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params) // Get the size of an instruction. instSize = sizeof(TheISA::MachInst); - - // Name is finally available, so create the port. - icachePort = new IcachePort(this); - - icachePort->snoopRangeSent = false; - -#if USE_CHECKER - if (cpu->checker) { - cpu->checker->setIcachePort(icachePort); - } -#endif } template <class Impl> @@ -402,8 +329,10 @@ template<class Impl> void DefaultFetch<Impl>::setIcache() { + assert(cpu->getIcachePort()->isConnected()); + // Size of cache block. - cacheBlkSize = icachePort->peerBlockSize(); + cacheBlkSize = cpu->getIcachePort()->peerBlockSize(); // Create mask to get rid of offset bits. cacheBlkMask = (cacheBlkSize - 1); @@ -494,6 +423,10 @@ template <class Impl> void DefaultFetch<Impl>::takeOverFrom() { + // the instruction port is now connected so we can get the block + // size + setIcache(); + // Reset all state for (ThreadID i = 0; i < Impl::MaxThreads; ++i) { stalls[i].decode = 0; @@ -684,7 +617,7 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req) fetchedCacheLines++; // Access the cache. - if (!icachePort->sendTiming(data_pkt)) { + if (!cpu->getIcachePort()->sendTiming(data_pkt)) { assert(retryPkt == NULL); assert(retryTid == InvalidThreadID); DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid); @@ -1403,7 +1336,7 @@ DefaultFetch<Impl>::recvRetry() assert(retryTid != InvalidThreadID); assert(fetchStatus[retryTid] == IcacheWaitRetry); - if (icachePort->sendTiming(retryPkt)) { + if (cpu->getIcachePort()->sendTiming(retryPkt)) { fetchStatus[retryTid] = IcacheWaitResponse; retryPkt = NULL; retryTid = InvalidThreadID; diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh index 2c5858a51..0d7e0f68f 100644 --- a/src/cpu/o3/iew.hh +++ b/src/cpu/o3/iew.hh @@ -138,9 +138,6 @@ class DefaultIEW /** Initializes stage; sends back the number of free IQ and LSQ entries. */ void initStage(); - /** Returns the dcache port. */ - Port *getDcachePort() { return ldstQueue.getDcachePort(); } - /** Sets main time buffer used for backwards communication. */ void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr); diff --git a/src/cpu/o3/lsq.hh b/src/cpu/o3/lsq.hh index 1974af08f..db127a2da 100644 --- a/src/cpu/o3/lsq.hh +++ b/src/cpu/o3/lsq.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2006 The Regents of The University of Michigan * All rights reserved. * @@ -65,13 +77,6 @@ class LSQ { /** Registers statistics of each LSQ unit. */ void regStats(); - /** Returns dcache port. - * @todo: Dcache port needs to be moved up to this level for SMT - * to work. For now it just returns the port from one of the - * threads. - */ - Port *getDcachePort() { return &dcachePort; } - /** Sets the pointer to the list of active threads. */ void setActiveThreads(std::list<ThreadID> *at_ptr); /** Switches out the LSQ. */ @@ -281,61 +286,25 @@ class LSQ { Fault write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh, uint8_t *data, int store_idx); + /** + * Retry the previous send that failed. + */ + void recvRetry(); + + /** + * Handles writing back and completing the load or store that has + * returned from memory. + * + * @param pkt Response packet from the memory sub-system + */ + bool recvTiming(PacketPtr pkt); + /** The CPU pointer. */ O3CPU *cpu; /** The IEW stage pointer. */ IEW *iewStage; - /** DcachePort class for this LSQ. Handles doing the - * communication with the cache/memory. - */ - class DcachePort : public Port - { - protected: - /** Pointer to LSQ. */ - LSQ *lsq; - - public: - /** Default constructor. */ - DcachePort(LSQ *_lsq) - : Port(_lsq->name() + "-dport", _lsq->cpu), lsq(_lsq) - { } - - bool snoopRangeSent; - - virtual void setPeer(Port *port); - - protected: - /** Atomic version of receive. Panics. */ - virtual Tick recvAtomic(PacketPtr pkt); - - /** Functional version of receive. Panics. */ - virtual void recvFunctional(PacketPtr pkt); - - /** Receives status change. Other than range changing, panics. */ - virtual void recvStatusChange(Status status); - - /** Returns the address ranges of this device. */ - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = true; } - - /** Timing version of receive. Handles writing back and - * completing the load or store that has returned from - * memory. */ - virtual bool recvTiming(PacketPtr pkt); - - /** Handles doing a retry of the previous send. */ - virtual void recvRetry(); - }; - - /** D-cache port. */ - DcachePort dcachePort; - - /** Tell the CPU to update the Phys and Virt ports. */ - void updateMemPorts() { cpu->updateMemPorts(); } - protected: /** The LSQ policy for SMT mode. */ LSQPolicy lsqPolicy; diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 8b1638c70..f1642be9c 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2005-2006 The Regents of The University of Michigan * All rights reserved. * @@ -40,96 +52,14 @@ using namespace std; -template<class Impl> -void -LSQ<Impl>::DcachePort::setPeer(Port *port) -{ - Port::setPeer(port); - - // Update the ThreadContext's memory ports (Functional/Virtual - // Ports) - lsq->updateMemPorts(); -} - -template <class Impl> -Tick -LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt) -{ - panic("O3CPU model does not work with atomic mode!"); - return curTick(); -} - -template <class Impl> -void -LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) -{ - DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional.\n"); -} - -template <class Impl> -void -LSQ<Impl>::DcachePort::recvStatusChange(Status status) -{ - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - panic("O3CPU doesn't expect recvStatusChange callback!"); -} - -template <class Impl> -bool -LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt) -{ - if (pkt->isError()) - DPRINTF(LSQ, "Got error packet back for address: %#X\n", pkt->getAddr()); - if (pkt->isResponse()) { - lsq->thread[pkt->req->threadId()].completeDataAccess(pkt); - } else { - DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(), - pkt->cmdString()); - - // must be a snoop - if (pkt->isInvalidate()) { - DPRINTF(LSQ, "received invalidation for addr:%#x\n", pkt->getAddr()); - for (ThreadID tid = 0; tid < lsq->numThreads; tid++) { - lsq->thread[tid].checkSnoop(pkt); - } - } - // to provide stronger consistency model - } - return true; -} - -template <class Impl> -void -LSQ<Impl>::DcachePort::recvRetry() -{ - if (lsq->retryTid == -1) - { - //Squashed, so drop it - return; - } - int curr_retry_tid = lsq->retryTid; - // Speculatively clear the retry Tid. This will get set again if - // the LSQUnit was unable to complete its access. - lsq->retryTid = -1; - lsq->thread[curr_retry_tid].recvRetry(); -} - template <class Impl> LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params) - : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this), + : cpu(cpu_ptr), iewStage(iew_ptr), LQEntries(params->LQEntries), SQEntries(params->SQEntries), numThreads(params->numThreads), retryTid(-1) { - dcachePort.snoopRangeSent = false; - //**********************************************/ //************ Handle SMT Parameters ***********/ //**********************************************/ @@ -181,7 +111,7 @@ LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params) for (ThreadID tid = 0; tid < numThreads; tid++) { thread[tid].init(cpu, iew_ptr, params, this, maxLQEntries, maxSQEntries, tid); - thread[tid].setDcachePort(&dcachePort); + thread[tid].setDcachePort(cpu_ptr->getDcachePort()); } } @@ -371,6 +301,48 @@ LSQ<Impl>::violation() return false; } +template <class Impl> +void +LSQ<Impl>::recvRetry() +{ + if (retryTid == InvalidThreadID) + { + //Squashed, so drop it + return; + } + int curr_retry_tid = retryTid; + // Speculatively clear the retry Tid. This will get set again if + // the LSQUnit was unable to complete its access. + retryTid = -1; + thread[curr_retry_tid].recvRetry(); +} + +template <class Impl> +bool +LSQ<Impl>::recvTiming(PacketPtr pkt) +{ + if (pkt->isError()) + DPRINTF(LSQ, "Got error packet back for address: %#X\n", + pkt->getAddr()); + if (pkt->isResponse()) { + thread[pkt->req->threadId()].completeDataAccess(pkt); + } else { + DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(), + pkt->cmdString()); + + // must be a snoop + if (pkt->isInvalidate()) { + DPRINTF(LSQ, "received invalidation for addr:%#x\n", + pkt->getAddr()); + for (ThreadID tid = 0; tid < numThreads; tid++) { + thread[tid].checkSnoop(pkt); + } + } + // to provide stronger consistency model + } + return true; +} + template<class Impl> int LSQ<Impl>::getCount() diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 815c9cb64..ff6ca0093 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -96,17 +96,18 @@ class O3ThreadContext : public ThreadContext virtual TheISA::Kernel::Statistics *getKernelStats() { return thread->kernelStats; } - virtual void connectMemPorts(ThreadContext *tc) - { thread->connectMemPorts(tc); } - /** Returns a pointer to this thread's process. */ virtual Process *getProcessPtr() { return thread->getProcessPtr(); } - virtual TranslatingPort *getMemPort() { return thread->getMemPort(); } + virtual PortProxy* getPhysProxy() { return thread->getPhysProxy(); } + + virtual FSTranslatingPortProxy* getVirtProxy(); - virtual VirtualPort *getVirtPort(); + virtual void initMemProxies(ThreadContext *tc) + { thread->initMemProxies(tc); } - virtual FunctionalPort *getPhysPort() { return thread->getPhysPort(); } + virtual SETranslatingPortProxy* getMemProxy() + { return thread->getMemProxy(); } /** Returns this thread's status. */ virtual Status status() const { return thread->status(); } diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 15fc397dc..5ba454458 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -49,10 +49,10 @@ #include "debug/O3CPU.hh" template <class Impl> -VirtualPort * -O3ThreadContext<Impl>::getVirtPort() +FSTranslatingPortProxy* +O3ThreadContext<Impl>::getVirtProxy() { - return thread->getVirtPort(); + return thread->getVirtProxy(); } template <class Impl> diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 36df58ab5..ff43ad6cb 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -114,12 +114,12 @@ class OzoneCPU : public BaseCPU Process *getProcessPtr() { return thread->getProcessPtr(); } - TranslatingPort *getMemPort() { return thread->getMemPort(); } + PortProxy* getPhysProxy() { return thread->getPhysProxy(); } - VirtualPort *getVirtPort() - { return thread->getVirtPort(); } + FSTranslatingPortProxy* getVirtProxy() + { return thread->getVirtProxy(); } - FunctionalPort *getPhysPort() { return thread->getPhysPort(); } + SETranslatingPortProxy* getMemProxy() { return thread->getMemProxy(); } Status status() const { return thread->status(); } diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index e2f5dc10c..f532078fe 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -186,25 +186,7 @@ OzoneCPU<Impl>::OzoneCPU(Params *p) frontEnd->renameTable.copyFrom(thread.renameTable); backEnd->renameTable.copyFrom(thread.renameTable); - if (FullSystem) { - Port *mem_port; - FunctionalPort *phys_port; - VirtualPort *virt_port; - phys_port = new FunctionalPort(csprintf("%s-%d-funcport", - name(), 0)); - mem_port = system->physmem->getPort("functional"); - mem_port->setPeer(phys_port); - phys_port->setPeer(mem_port); - - virt_port = new VirtualPort(csprintf("%s-%d-vport", - name(), 0)); - mem_port = system->physmem->getPort("functional"); - mem_port->setPeer(virt_port); - virt_port->setPeer(mem_port); - - thread.setPhysPort(phys_port); - thread.setVirtPort(virt_port); - } + thread.connectMemPorts(tc); DPRINTF(OzoneCPU, "OzoneCPU: Created Ozone cpu object.\n"); } diff --git a/src/cpu/ozone/front_end.hh b/src/cpu/ozone/front_end.hh index 1d200ef7d..41b86aab8 100644 --- a/src/cpu/ozone/front_end.hh +++ b/src/cpu/ozone/front_end.hh @@ -87,13 +87,8 @@ class FrontEnd /** Functional version of receive. Panics. */ virtual void recvFunctional(PacketPtr pkt); - /** Receives status change. Other than range changing, panics. */ - virtual void recvStatusChange(Status status); - - /** Returns the address ranges of this device. */ - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = true; } + /** Receives range change. */ + virtual void recvRangeChange(); /** Timing version of receive. Handles setting fetch to the * proper status to start fetching. */ diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh index 88576de3d..e7255d75f 100644 --- a/src/cpu/ozone/front_end_impl.hh +++ b/src/cpu/ozone/front_end_impl.hh @@ -64,12 +64,8 @@ FrontEnd<Impl>::IcachePort::recvFunctional(PacketPtr pkt) template<class Impl> void -FrontEnd<Impl>::IcachePort::recvStatusChange(Status status) +FrontEnd<Impl>::IcachePort::recvRangeChange() { - if (status == RangeChange) - return; - - panic("FrontEnd doesn't expect recvStatusChange callback!"); } template<class Impl> diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh index 34461b9d0..dd573e5e0 100644 --- a/src/cpu/ozone/lw_lsq.hh +++ b/src/cpu/ozone/lw_lsq.hh @@ -255,11 +255,13 @@ class OzoneLWLSQ { virtual void recvFunctional(PacketPtr pkt); - virtual void recvStatusChange(Status status); + virtual void recvRangeChange(); - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = true; } + /** + * Is a snooper due to LSQ maintenance + */ + virtual bool isSnooping() + { return true; } virtual bool recvTiming(PacketPtr pkt); diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh index 3bee83176..811d66567 100644 --- a/src/cpu/ozone/lw_lsq_impl.hh +++ b/src/cpu/ozone/lw_lsq_impl.hh @@ -77,12 +77,8 @@ OzoneLWLSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) template <class Impl> void -OzoneLWLSQ<Impl>::DcachePort::recvStatusChange(Status status) +OzoneLWLSQ<Impl>::DcachePort::recvRangeChange() { - if (status == RangeChange) - return; - - panic("O3CPU doesn't expect recvStatusChange callback!"); } template <class Impl> diff --git a/src/cpu/simple/AtomicSimpleCPU.py b/src/cpu/simple/AtomicSimpleCPU.py index a4d807f86..93cd02ba7 100644 --- a/src/cpu/simple/AtomicSimpleCPU.py +++ b/src/cpu/simple/AtomicSimpleCPU.py @@ -34,8 +34,4 @@ class AtomicSimpleCPU(BaseSimpleCPU): width = Param.Int(1, "CPU width") simulate_data_stalls = Param.Bool(False, "Simulate dcache stall cycles") simulate_inst_stalls = Param.Bool(False, "Simulate icache stall cycles") - icache_port = Port("Instruction Port") - dcache_port = Port("Data Port") physmem_port = Port("Physical Memory Port") - _cached_ports = BaseSimpleCPU._cached_ports + \ - ['icache_port', 'dcache_port'] diff --git a/src/cpu/simple/TimingSimpleCPU.py b/src/cpu/simple/TimingSimpleCPU.py index 8d6888f72..61491b087 100644 --- a/src/cpu/simple/TimingSimpleCPU.py +++ b/src/cpu/simple/TimingSimpleCPU.py @@ -31,6 +31,3 @@ from BaseSimpleCPU import BaseSimpleCPU class TimingSimpleCPU(BaseSimpleCPU): type = 'TimingSimpleCPU' - icache_port = Port("Instruction Port") - dcache_port = Port("Data Port") - _cached_ports = BaseSimpleCPU._cached_ports + ['icache_port', 'dcache_port'] diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index fed94ffd8..2c12b244b 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -92,10 +92,12 @@ AtomicSimpleCPU::init() TheISA::initCPU(tc, tc->contextId()); } } + + // Initialise the ThreadContext's memory proxies + tcBase()->initMemProxies(tcBase()); + if (hasPhysMemPort) { - bool snoop = false; - AddrRangeList pmAddrList; - physmemPort.getPeerAddressRanges(pmAddrList, snoop); + AddrRangeList pmAddrList = physmemPort.getPeer()->getAddrRanges(); physMemAddr = *pmAddrList.begin(); } // Atomic doesn't do MT right now, so contextId == threadId @@ -104,59 +106,6 @@ AtomicSimpleCPU::init() data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too } -bool -AtomicSimpleCPU::CpuPort::recvTiming(PacketPtr pkt) -{ - panic("AtomicSimpleCPU doesn't expect recvTiming callback!"); - return true; -} - -Tick -AtomicSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt) -{ - //Snooping a coherence request, just return - return 0; -} - -void -AtomicSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt) -{ - //No internal storage to update, just return - return; -} - -void -AtomicSimpleCPU::CpuPort::recvStatusChange(Status status) -{ - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!"); -} - -void -AtomicSimpleCPU::CpuPort::recvRetry() -{ - panic("AtomicSimpleCPU doesn't expect recvRetry callback!"); -} - -void -AtomicSimpleCPU::DcachePort::setPeer(Port *port) -{ - Port::setPeer(port); - - if (FullSystem) { - // Update the ThreadContext's memory ports (Functional/Virtual - // Ports) - cpu->tcBase()->connectMemPorts(cpu->tcBase()); - } -} - AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p) : BaseSimpleCPU(p), tickEvent(this), width(p->width), locked(false), simulate_data_stalls(p->simulate_data_stalls), @@ -165,10 +114,6 @@ AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p) physmemPort(name() + "-iport", this), hasPhysMemPort(false) { _status = Idle; - - icachePort.snoopRangeSent = false; - dcachePort.snoopRangeSent = false; - } diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index 246afa0b2..77a9d6b0d 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -64,47 +64,31 @@ class AtomicSimpleCPU : public BaseSimpleCPU // main simulation loop (one cycle) void tick(); - class CpuPort : public Port + /** + * An AtomicCPUPort overrides the default behaviour of the + * recvAtomic and ignores the packet instead of panicking. + */ + class AtomicCPUPort : public CpuPort { + public: - CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu) - : Port(_name, _cpu), cpu(_cpu) + AtomicCPUPort(const std::string &_name, BaseCPU* _cpu) + : CpuPort(_name, _cpu) { } - bool snoopRangeSent; - protected: - AtomicSimpleCPU *cpu; - - virtual bool recvTiming(PacketPtr pkt); - - virtual Tick recvAtomic(PacketPtr pkt); - - virtual void recvFunctional(PacketPtr pkt); - - virtual void recvStatusChange(Status status); - - virtual void recvRetry(); - - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = true; } + virtual Tick recvAtomic(PacketPtr pkt) + { + // Snooping a coherence request, just return + return 0; + } }; - CpuPort icachePort; - class DcachePort : public CpuPort - { - public: - DcachePort(const std::string &_name, AtomicSimpleCPU *_cpu) - : CpuPort(_name, _cpu) - { } - - virtual void setPeer(Port *port); - }; - DcachePort dcachePort; + AtomicCPUPort icachePort; + AtomicCPUPort dcachePort; CpuPort physmemPort; bool hasPhysMemPort; diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 983672c27..fd02e8300 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -82,53 +82,24 @@ TimingSimpleCPU::init() TheISA::initCPU(tc, _cpuId); } } -} - -Tick -TimingSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt) -{ - panic("TimingSimpleCPU doesn't expect recvAtomic callback!"); - return curTick(); -} -void -TimingSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt) -{ - //No internal storage to update, jusst return - return; + // Initialise the ThreadContext's memory proxies + tcBase()->initMemProxies(tcBase()); } void -TimingSimpleCPU::CpuPort::recvStatusChange(Status status) -{ - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("TimingSimpleCPU doesn't expect recvStatusChange callback!"); -} - - -void -TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t) +TimingSimpleCPU::TimingCPUPort::TickEvent::schedule(PacketPtr _pkt, Tick t) { pkt = _pkt; cpu->schedule(this, t); } TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p) - : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this, p->clock), - dcachePort(this, p->clock), fetchEvent(this) + : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this), + dcachePort(this), fetchEvent(this) { _status = Idle; - icachePort.snoopRangeSent = false; - dcachePort.snoopRangeSent = false; - ifetch_pkt = dcache_pkt = NULL; drainEvent = NULL; previousTick = 0; @@ -874,18 +845,6 @@ TimingSimpleCPU::completeDrain() drainEvent->process(); } -void -TimingSimpleCPU::DcachePort::setPeer(Port *port) -{ - Port::setPeer(port); - - if (FullSystem) { - // Update the ThreadContext's memory ports (Functional/Virtual - // Ports) - cpu->tcBase()->connectMemPorts(cpu->tcBase()); - } -} - bool TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) { @@ -903,7 +862,7 @@ TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt) // faster than a CPU we could get two responses before // next_tick expires if (!retryEvent.scheduled()) - schedule(retryEvent, next_tick); + cpu->schedule(retryEvent, next_tick); return false; } } diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index 4301dfca7..dce3c58ff 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -137,31 +137,23 @@ class TimingSimpleCPU : public BaseSimpleCPU // This function always implicitly uses dcache_pkt. bool handleWritePacket(); - class CpuPort : public Port + /** + * A TimingCPUPort overrides the default behaviour of the + * recvTiming and recvRetry and implements events for the + * scheduling of handling of incoming packets in the following + * cycle. + */ + class TimingCPUPort : public CpuPort { - protected: - TimingSimpleCPU *cpu; - Tick lat; - public: - CpuPort(const std::string &_name, TimingSimpleCPU *_cpu, Tick _lat) - : Port(_name, _cpu), cpu(_cpu), lat(_lat), retryEvent(this) + TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu) + : CpuPort(_name, _cpu), cpu(_cpu), retryEvent(this) { } - bool snoopRangeSent; - protected: - virtual Tick recvAtomic(PacketPtr pkt); - - virtual void recvFunctional(PacketPtr pkt); - - virtual void recvStatusChange(Status status); - - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = false; } + TimingSimpleCPU* cpu; struct TickEvent : public Event { @@ -169,7 +161,7 @@ class TimingSimpleCPU : public BaseSimpleCPU TimingSimpleCPU *cpu; CpuPort *port; - TickEvent(TimingSimpleCPU *_cpu) : cpu(_cpu) {} + TickEvent(TimingSimpleCPU *_cpu) : pkt(NULL), cpu(_cpu) {} const char *description() const { return "Timing CPU tick"; } void schedule(PacketPtr _pkt, Tick t); }; @@ -177,12 +169,13 @@ class TimingSimpleCPU : public BaseSimpleCPU EventWrapper<Port, &Port::sendRetry> retryEvent; }; - class IcachePort : public CpuPort + class IcachePort : public TimingCPUPort { public: - IcachePort(TimingSimpleCPU *_cpu, Tick _lat) - : CpuPort(_cpu->name() + "-iport", _cpu, _lat), tickEvent(_cpu) + IcachePort(TimingSimpleCPU *_cpu) + : TimingCPUPort(_cpu->name() + "-iport", _cpu), + tickEvent(_cpu) { } protected: @@ -204,16 +197,14 @@ class TimingSimpleCPU : public BaseSimpleCPU }; - class DcachePort : public CpuPort + class DcachePort : public TimingCPUPort { public: - DcachePort(TimingSimpleCPU *_cpu, Tick _lat) - : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu) + DcachePort(TimingSimpleCPU *_cpu) + : TimingCPUPort(_cpu->name() + "-dport", _cpu), tickEvent(_cpu) { } - virtual void setPeer(Port *port); - protected: virtual bool recvTiming(PacketPtr pkt); diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index edde884e7..a12ab8e8a 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -47,13 +47,14 @@ #include "cpu/quiesce_event.hh" #include "cpu/simple_thread.hh" #include "cpu/thread_context.hh" -#include "mem/translating_port.hh" -#include "mem/vport.hh" #include "params/BaseCPU.hh" +#include "mem/fs_translating_port_proxy.hh" +#include "mem/se_translating_port_proxy.hh" #include "sim/full_system.hh" #include "sim/process.hh" #include "sim/serialize.hh" #include "sim/sim_exit.hh" +#include "sim/process.hh" #include "sim/system.hh" using namespace std; @@ -106,8 +107,6 @@ SimpleThread::SimpleThread() SimpleThread::~SimpleThread() { - delete physPort; - delete virtPort; delete tc; } diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index ffa89a967..f2132dc36 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -57,7 +57,6 @@ class BaseCPU; class FunctionProfile; class ProfileNode; -class FunctionalPort; class PhysicalPort; class TranslatingPort; @@ -195,13 +194,13 @@ class SimpleThread : public ThreadState System *getSystemPtr() { return system; } - FunctionalPort *getPhysPort() { return physPort; } + PortProxy* getPhysProxy() { return physProxy; } /** Return a virtual port. This port cannot be cached locally in an object. * After a CPU switch it may point to the wrong memory object which could * mean stale data. */ - VirtualPort *getVirtPort() { return virtPort; } + FSTranslatingPortProxy* getVirtProxy() { return virtProxy; } Status status() const { return _status; } diff --git a/src/cpu/testers/memtest/memtest.cc b/src/cpu/testers/memtest/memtest.cc index ef23825cd..d70dc96e6 100644 --- a/src/cpu/testers/memtest/memtest.cc +++ b/src/cpu/testers/memtest/memtest.cc @@ -84,17 +84,8 @@ MemTest::CpuPort::recvFunctional(PacketPtr pkt) } void -MemTest::CpuPort::recvStatusChange(Status status) +MemTest::CpuPort::recvRangeChange() { - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("MemTest doesn't expect recvStatusChange callback!"); } void @@ -149,9 +140,6 @@ MemTest::MemTest(const Params *p) atomic(p->atomic), suppress_func_warnings(p->suppress_func_warnings) { - cachePort.snoopRangeSent = false; - funcPort.snoopRangeSent = true; - id = TESTER_ALLOCATOR++; // Needs to be masked off once we know the block size. diff --git a/src/cpu/testers/memtest/memtest.hh b/src/cpu/testers/memtest/memtest.hh index 292e7d83d..1a59914fd 100644 --- a/src/cpu/testers/memtest/memtest.hh +++ b/src/cpu/testers/memtest/memtest.hh @@ -93,8 +93,6 @@ class MemTest : public MemObject : Port(_name, _memtest), memtest(_memtest) { } - bool snoopRangeSent; - protected: virtual bool recvTiming(PacketPtr pkt); @@ -103,20 +101,14 @@ class MemTest : public MemObject virtual void recvFunctional(PacketPtr pkt); - virtual void recvStatusChange(Status status); + virtual void recvRangeChange(); virtual void recvRetry(); - - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = false; } }; CpuPort cachePort; CpuPort funcPort; - bool snoopRangeSent; - class MemTestSenderState : public Packet::SenderState, public FastAlloc { public: diff --git a/src/cpu/testers/networktest/networktest.cc b/src/cpu/testers/networktest/networktest.cc index d78f976be..56fcc46c4 100644 --- a/src/cpu/testers/networktest/networktest.cc +++ b/src/cpu/testers/networktest/networktest.cc @@ -81,17 +81,8 @@ NetworkTest::CpuPort::recvFunctional(PacketPtr pkt) } void -NetworkTest::CpuPort::recvStatusChange(Status status) +NetworkTest::CpuPort::recvRangeChange() { - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - - panic("NetworkTest doesn't expect recvStatusChange callback!"); } void @@ -124,8 +115,6 @@ NetworkTest::NetworkTest(const Params *p) injRate(p->inj_rate), precision(p->precision) { - cachePort.snoopRangeSent = false; - // set up counters noResponseCycles = 0; schedule(tickEvent, 0); diff --git a/src/cpu/testers/networktest/networktest.hh b/src/cpu/testers/networktest/networktest.hh index 6d9d1edad..c277cfbab 100644 --- a/src/cpu/testers/networktest/networktest.hh +++ b/src/cpu/testers/networktest/networktest.hh @@ -89,8 +89,6 @@ class NetworkTest : public MemObject : Port(_name, _networktest), networktest(_networktest) { } - bool snoopRangeSent; - protected: virtual bool recvTiming(PacketPtr pkt); @@ -99,19 +97,13 @@ class NetworkTest : public MemObject virtual void recvFunctional(PacketPtr pkt); - virtual void recvStatusChange(Status status); + virtual void recvRangeChange(); virtual void recvRetry(); - - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = false; } }; CpuPort cachePort; - bool snoopRangeSent; - class NetworkTestSenderState : public Packet::SenderState, public FastAlloc { public: diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index f7879ea60..261ace7cf 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -49,9 +49,9 @@ class BaseCPU; class Checkpoint; class Decoder; class EndQuiesceEvent; -class TranslatingPort; -class FunctionalPort; -class VirtualPort; +class SETranslatingPortProxy; +class FSTranslatingPortProxy; +class PortProxy; class Process; class System; namespace TheISA { @@ -126,15 +126,21 @@ class ThreadContext virtual TheISA::Kernel::Statistics *getKernelStats() = 0; - virtual void connectMemPorts(ThreadContext *tc) = 0; + virtual PortProxy* getPhysProxy() = 0; - virtual Process *getProcessPtr() = 0; + virtual FSTranslatingPortProxy* getVirtProxy() = 0; - virtual TranslatingPort *getMemPort() = 0; + /** + * Initialise the physical and virtual port proxies and tie them to + * the data port of the CPU. + * + * tc ThreadContext for the virtual-to-physical translation + */ + virtual void initMemProxies(ThreadContext *tc) = 0; - virtual VirtualPort *getVirtPort() = 0; + virtual SETranslatingPortProxy *getMemProxy() = 0; - virtual FunctionalPort *getPhysPort() = 0; + virtual Process *getProcessPtr() = 0; virtual Status status() const = 0; @@ -288,15 +294,15 @@ class ProxyThreadContext : public ThreadContext TheISA::Kernel::Statistics *getKernelStats() { return actualTC->getKernelStats(); } - void connectMemPorts(ThreadContext *tc) { actualTC->connectMemPorts(tc); } + PortProxy* getPhysProxy() { return actualTC->getPhysProxy(); } - Process *getProcessPtr() { return actualTC->getProcessPtr(); } + FSTranslatingPortProxy* getVirtProxy() { return actualTC->getVirtProxy(); } - TranslatingPort *getMemPort() { return actualTC->getMemPort(); } + void initMemProxies(ThreadContext *tc) { actualTC->initMemProxies(tc); } - VirtualPort *getVirtPort() { return actualTC->getVirtPort(); } + SETranslatingPortProxy* getMemProxy() { return actualTC->getMemProxy(); } - FunctionalPort *getPhysPort() { return actualTC->getPhysPort(); } + Process *getProcessPtr() { return actualTC->getProcessPtr(); } Status status() const { return actualTC->status(); } diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc index ef81271a8..574be7b6d 100644 --- a/src/cpu/thread_state.cc +++ b/src/cpu/thread_state.cc @@ -34,27 +34,31 @@ #include "cpu/profile.hh" #include "cpu/quiesce_event.hh" #include "cpu/thread_state.hh" +#include "mem/fs_translating_port_proxy.hh" #include "mem/port.hh" -#include "mem/translating_port.hh" -#include "mem/vport.hh" +#include "mem/port_proxy.hh" +#include "mem/se_translating_port_proxy.hh" #include "sim/full_system.hh" #include "sim/serialize.hh" +#include "sim/system.hh" ThreadState::ThreadState(BaseCPU *cpu, ThreadID _tid, Process *_process) : numInst(0), numLoad(0), _status(ThreadContext::Halted), baseCpu(cpu), _threadId(_tid), lastActivate(0), lastSuspend(0), profile(NULL), profileNode(NULL), profilePC(0), quiesceEvent(NULL), - kernelStats(NULL), process(_process), port(NULL), virtPort(NULL), - physPort(NULL), funcExeInst(0), storeCondFailures(0) + kernelStats(NULL), process(_process), physProxy(NULL), virtProxy(NULL), + proxy(NULL), funcExeInst(0), storeCondFailures(0) { } ThreadState::~ThreadState() { - if (port) { - delete port->getPeer(); - delete port; - } + if (physProxy != NULL) + delete physProxy; + if (virtProxy != NULL) + delete virtProxy; + if (proxy != NULL) + delete proxy; } void @@ -93,38 +97,16 @@ ThreadState::unserialize(Checkpoint *cp, const std::string §ion) } void -ThreadState::connectPhysPort() -{ - // @todo: For now this disregards any older port that may have - // already existed. Fix this memory leak once the bus port IDs - // for functional ports is resolved. - if (physPort) - physPort->removeConn(); - else - physPort = new FunctionalPort(csprintf("%s-%d-funcport", - baseCpu->name(), _threadId)); - connectToMemFunc(physPort); -} - -void -ThreadState::connectVirtPort(ThreadContext *tc) -{ - // @todo: For now this disregards any older port that may have - // already existed. Fix this memory leak once the bus port IDs - // for functional ports is resolved. - if (virtPort) - virtPort->removeConn(); - else - virtPort = new VirtualPort(csprintf("%s-%d-vport", - baseCpu->name(), _threadId), tc); - connectToMemFunc(virtPort); -} - -void -ThreadState::connectMemPorts(ThreadContext *tc) +ThreadState::initMemProxies(ThreadContext *tc) { - connectPhysPort(); - connectVirtPort(tc); + // Note that this only refers to the port on the CPU side and can + // safely be done at init() time even if the CPU is not connected + // (i.e. due to restoring from a checkpoint and later switching + // in. + if (physProxy == NULL) + physProxy = new PortProxy(*baseCpu->getPort("dcache_port")); + if (virtProxy == NULL) + virtProxy = new FSTranslatingPortProxy(tc); } void @@ -141,35 +123,16 @@ ThreadState::profileSample() profile->sample(profileNode, profilePC); } -TranslatingPort * -ThreadState::getMemPort() +SETranslatingPortProxy * +ThreadState::getMemProxy() { - if (port != NULL) - return port; - - /* Use this port to for syscall emulation writes to memory. */ - port = new TranslatingPort(csprintf("%s-%d-funcport", baseCpu->name(), - _threadId), process, TranslatingPort::NextPage); - - connectToMemFunc(port); - - return port; -} - -void -ThreadState::connectToMemFunc(Port *port) -{ - Port *dcache_port, *func_mem_port; - - dcache_port = baseCpu->getPort("dcache_port"); - assert(dcache_port != NULL); - - MemObject *mem_object = dcache_port->getPeer()->getOwner(); - assert(mem_object != NULL); + if (proxy != NULL) + return proxy; - func_mem_port = mem_object->getPort("functional"); - assert(func_mem_port != NULL); + /* Use this port proxy to for syscall emulation writes to memory. */ + proxy = new SETranslatingPortProxy(*process->system->getSystemPort(), + process, + SETranslatingPortProxy::NextPage); - func_mem_port->setPeer(port); - port->setPeer(func_mem_port); + return proxy; } diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index 972ca895d..30bb64ed7 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -49,8 +49,9 @@ namespace TheISA { }; class Checkpoint; -class Port; -class TranslatingPort; +class PortProxy; +class SETranslatingPort; +class FSTranslatingPort; /** * Struct for holding general thread state that is needed across CPU @@ -83,11 +84,13 @@ struct ThreadState { Tick readLastSuspend() { return lastSuspend; } - void connectPhysPort(); - - void connectVirtPort(ThreadContext *tc); - - void connectMemPorts(ThreadContext *tc); + /** + * Initialise the physical and virtual port proxies and tie them to + * the data port of the CPU. + * + * tc ThreadContext for the virtual-to-physical translation + */ + void initMemProxies(ThreadContext *tc); void dumpFuncProfile(); @@ -99,17 +102,13 @@ struct ThreadState { TheISA::Kernel::Statistics *getKernelStats() { return kernelStats; } - Process *getProcessPtr() { return process; } - - TranslatingPort *getMemPort(); + PortProxy* getPhysProxy() { return physProxy; } - void setMemPort(TranslatingPort *_port) { port = _port; } + FSTranslatingPortProxy* getVirtProxy() { return virtProxy; } - VirtualPort *getVirtPort() { return virtPort; } - - FunctionalPort *getPhysPort() { return physPort; } + Process *getProcessPtr() { return process; } - void setPhysPort(FunctionalPort *port) { physPort = port; } + SETranslatingPortProxy* getMemProxy(); /** Reads the number of instructions functionally executed and * committed. @@ -128,9 +127,6 @@ struct ThreadState { void setStatus(Status new_status) { _status = new_status; } public: - /** Connects port to the functional port of the memory object - * below the CPU. */ - void connectToMemFunc(Port *port); /** Number of instructions committed. */ Counter numInst; @@ -177,15 +173,14 @@ struct ThreadState { protected: Process *process; - TranslatingPort *port; - - /** A functional port, outgoing only, for functional accesse to virtual - * addresses. */ - VirtualPort *virtPort; - - /** A functional port outgoing only for functional accesses to physical + /** A port proxy outgoing only for functional accesses to physical * addresses.*/ - FunctionalPort *physPort; + PortProxy *physProxy; + + /** A translating port proxy, outgoing only, for functional + * accesse to virtual addresses. */ + FSTranslatingPortProxy* virtProxy; + SETranslatingPortProxy* proxy; public: /* diff --git a/src/dev/Device.py b/src/dev/Device.py index 9cd41fe09..c32946277 100644 --- a/src/dev/Device.py +++ b/src/dev/Device.py @@ -45,7 +45,7 @@ class BasicPioDevice(PioDevice): class DmaDevice(PioDevice): type = 'DmaDevice' abstract = True - dma = Port(Self.pio.peerObj.port, "DMA port") + dma = Port("DMA port") min_backoff_delay = Param.Latency('4ns', "min time between a nack packet being received and the next request made by the device") max_backoff_delay = Param.Latency('10us', diff --git a/src/dev/Pci.py b/src/dev/Pci.py index 2f9f93a59..95cb3916f 100644 --- a/src/dev/Pci.py +++ b/src/dev/Pci.py @@ -43,7 +43,7 @@ class PciDevice(DmaDevice): type = 'PciDevice' abstract = True platform = Param.Platform(Parent.any, "Platform this device is part of.") - config = Port(Self.pio.peerObj.port, "PCI configuration space port") + config = Port("PCI configuration space port") pci_bus = Param.Int("PCI bus") pci_dev = Param.Int("PCI device number") pci_func = Param.Int("PCI function code") diff --git a/src/dev/arm/RealView.py b/src/dev/arm/RealView.py index 11905ae79..dc2219cd1 100644 --- a/src/dev/arm/RealView.py +++ b/src/dev/arm/RealView.py @@ -1,4 +1,4 @@ -# Copyright (c) 2009 ARM Limited +# Copyright (c) 2009-2011 ARM Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -178,12 +178,18 @@ class RealViewPBX(RealView): rtc_fake = AmbaFake(pio_addr=0x10017000, amba_id=0x41031) - # Attach I/O devices that are on chip - def attachOnChipIO(self, bus): + # Attach I/O devices that are on chip and also set the appropriate + # ranges for the bridge + def attachOnChipIO(self, bus, bridge): self.gic.pio = bus.port self.l2x0_fake.pio = bus.port self.a9scu.pio = bus.port self.local_cpu_timer.pio = bus.port + # Bridge ranges based on excluding what is part of on-chip I/O + # (gic, l2x0, a9scu, local_cpu_timer) + bridge.ranges = [AddrRange(self.realview_io.pio_addr, + self.a9scu.pio_addr - 1), + AddrRange(self.flash_fake.pio_addr, Addr.max)] # Attach I/O devices to specified bus object. Can't do this # earlier, since the bus object itself is typically defined at the @@ -194,9 +200,12 @@ class RealViewPBX(RealView): self.timer0.pio = bus.port self.timer1.pio = bus.port self.clcd.pio = bus.port + self.clcd.dma = bus.port self.kmi0.pio = bus.port self.kmi1.pio = bus.port self.cf_ctrl.pio = bus.port + self.cf_ctrl.config = bus.port + self.cf_ctrl.dma = bus.port self.dmac_fake.pio = bus.port self.uart1_fake.pio = bus.port self.uart2_fake.pio = bus.port @@ -249,10 +258,16 @@ class RealViewEB(RealView): - # Attach I/O devices that are on chip - def attachOnChipIO(self, bus): + # Attach I/O devices that are on chip and also set the appropriate + # ranges for the bridge + def attachOnChipIO(self, bus, bridge): self.gic.pio = bus.port self.l2x0_fake.pio = bus.port + # Bridge ranges based on excluding what is part of on-chip I/O + # (gic, l2x0) + bridge.ranges = [AddrRange(self.realview_io.pio_addr, + self.gic.cpu_addr - 1), + AddrRange(self.flash_fake.pio_addr, Addr.max)] # Attach I/O devices to specified bus object. Can't do this # earlier, since the bus object itself is typically defined at the @@ -263,6 +278,7 @@ class RealViewEB(RealView): self.timer0.pio = bus.port self.timer1.pio = bus.port self.clcd.pio = bus.port + self.clcd.dma = bus.port self.kmi0.pio = bus.port self.kmi1.pio = bus.port self.dmac_fake.pio = bus.port @@ -330,10 +346,15 @@ class VExpress_ELT(RealView): usb_fake = IsaFake(pio_addr=0xFB000000, pio_size=0x1ffff) - # Attach I/O devices that are on chip - def attachOnChipIO(self, bus): + # Attach I/O devices that are on chip and also set the appropriate + # ranges for the bridge + def attachOnChipIO(self, bus, bridge): self.gic.pio = bus.port self.a9scu.pio = bus.port + # Bridge ranges based on excluding what is part of on-chip I/O + # (gic, a9scu) + bridge.ranges = [AddrRange(self.pci_cfg_base, self.a9scu.pio_addr - 1), + AddrRange(self.local_cpu_timer.pio_addr, Addr.max)] # Attach I/O devices to specified bus object. Can't do this # earlier, since the bus object itself is typically defined at the @@ -348,13 +369,20 @@ class VExpress_ELT(RealView): self.elba_timer0.pio = bus.port self.elba_timer1.pio = bus.port self.clcd.pio = bus.port + self.clcd.dma = bus.port self.kmi0.pio = bus.port self.kmi1.pio = bus.port self.elba_kmi0.pio = bus.port self.elba_kmi1.pio = bus.port self.cf_ctrl.pio = bus.port + self.cf_ctrl.config = bus.port + self.cf_ctrl.dma = bus.port self.ide.pio = bus.port + self.ide.config = bus.port + self.ide.dma = bus.port self.ethernet.pio = bus.port + self.ethernet.config = bus.port + self.ethernet.dma = bus.port self.pciconfig.pio = bus.default bus.use_default_range = True diff --git a/src/dev/arm/gic.cc b/src/dev/arm/gic.cc index 67520f865..f686c2a13 100644 --- a/src/dev/arm/gic.cc +++ b/src/dev/arm/gic.cc @@ -705,12 +705,13 @@ Gic::postInt(uint32_t cpu, Tick when) eventq->schedule(postIntEvent[cpu], when); } -void -Gic::addressRanges(AddrRangeList &range_list) +AddrRangeList +Gic::getAddrRanges() { - range_list.clear(); - range_list.push_back(RangeSize(distAddr, DIST_SIZE)); - range_list.push_back(RangeSize(cpuAddr, CPU_SIZE)); + AddrRangeList ranges; + ranges.push_back(RangeSize(distAddr, DIST_SIZE)); + ranges.push_back(RangeSize(cpuAddr, CPU_SIZE)); + return ranges; } diff --git a/src/dev/arm/gic.hh b/src/dev/arm/gic.hh index 6988d6ed1..67d48cd86 100644 --- a/src/dev/arm/gic.hh +++ b/src/dev/arm/gic.hh @@ -261,7 +261,7 @@ class Gic : public PioDevice /** Return the address ranges used by the Gic * This is the distributor address + all cpu addresses */ - virtual void addressRanges(AddrRangeList &range_list); + virtual AddrRangeList getAddrRanges(); /** A PIO read to the device, immediately split up into * readDistributor() or readCpu() diff --git a/src/dev/arm/pl111.cc b/src/dev/arm/pl111.cc index 958f07aa7..263a3b620 100644 --- a/src/dev/arm/pl111.cc +++ b/src/dev/arm/pl111.cc @@ -735,11 +735,12 @@ Pl111::generateInterrupt() } } -void -Pl111::addressRanges(AddrRangeList& range_list) +AddrRangeList +Pl111::getAddrRanges() { - range_list.clear(); - range_list.push_back(RangeSize(pioAddr, pioSize)); + AddrRangeList ranges; + ranges.push_back(RangeSize(pioAddr, pioSize)); + return ranges; } Pl111 * diff --git a/src/dev/arm/pl111.hh b/src/dev/arm/pl111.hh index f36dc6810..b2dc1f640 100644 --- a/src/dev/arm/pl111.hh +++ b/src/dev/arm/pl111.hh @@ -325,10 +325,12 @@ class Pl111: public AmbaDmaDevice virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); - /** return the address ranges that this device responds to. - * @param range_list range list to populate with ranges + /** + * Determine the address ranges that this device responds to. + * + * @return a list of non-overlapping address ranges */ - void addressRanges(AddrRangeList &range_list); + AddrRangeList getAddrRanges(); }; #endif diff --git a/src/dev/copy_engine.hh b/src/dev/copy_engine.hh index dfe469588..581d3c80b 100644 --- a/src/dev/copy_engine.hh +++ b/src/dev/copy_engine.hh @@ -85,7 +85,6 @@ class CopyEngine : public PciDev void init(); std::string name() { assert(ce); return ce->name() + csprintf("-chan%d", channelId); } - virtual void addressRanges(AddrRangeList &range_list) { range_list.clear(); } virtual Tick read(PacketPtr pkt) { panic("CopyEngineChannel has no I/O access\n");} virtual Tick write(PacketPtr pkt) diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc index 0ad53f09e..840343dce 100644 --- a/src/dev/io_device.cc +++ b/src/dev/io_device.cc @@ -47,13 +47,10 @@ PioPort::recvAtomic(PacketPtr pkt) return pkt->isRead() ? device->read(pkt) : device->write(pkt); } -void -PioPort::getDeviceAddressRanges(AddrRangeList &resp, bool &snoop) +AddrRangeList +PioPort::getAddrRanges() { - snoop = false; - device->addressRanges(resp); - for (AddrRangeIter i = resp.begin(); i != resp.end(); i++) - DPRINTF(BusAddrRanges, "Adding Range %#x-%#x\n", i->start, i->end); + return device->getAddrRanges(); } @@ -72,7 +69,7 @@ PioDevice::init() { if (!pioPort) panic("Pio port of %s not connected to anything!", name()); - pioPort->sendStatusChange(Port::RangeChange); + pioPort->sendRangeChange(); } Port * @@ -105,13 +102,14 @@ BasicPioDevice::BasicPioDevice(const Params *p) pioDelay(p->pio_latency) {} -void -BasicPioDevice::addressRanges(AddrRangeList &range_list) +AddrRangeList +BasicPioDevice::getAddrRanges() { assert(pioSize != 0); - range_list.clear(); + AddrRangeList ranges; DPRINTF(BusAddrRanges, "registering range: %#x-%#x\n", pioAddr, pioSize); - range_list.push_back(RangeSize(pioAddr, pioSize)); + ranges.push_back(RangeSize(pioAddr, pioSize)); + return ranges; } @@ -121,7 +119,7 @@ DmaPort::DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff, pendingCount(0), actionInProgress(0), drainEvent(NULL), backoffTime(0), minBackoffDelay(min_backoff), maxBackoffDelay(max_backoff), inRetry(false), recvSnoops(recv_snoops), - snoopRangeSent(false), backoffEvent(this) + backoffEvent(this) { } bool @@ -136,7 +134,7 @@ DmaPort::recvTiming(PacketPtr pkt) else if (backoffTime < maxBackoffDelay) backoffTime <<= 1; - reschedule(backoffEvent, curTick() + backoffTime, true); + device->reschedule(backoffEvent, curTick() + backoffTime, true); DPRINTF(DMA, "Backoff time set to %d ticks\n", backoffTime); @@ -164,7 +162,8 @@ DmaPort::recvTiming(PacketPtr pkt) if (state->totBytes == state->numBytes) { if (state->completionEvent) { if (state->delay) - schedule(state->completionEvent, curTick() + state->delay); + device->schedule(state->completionEvent, + curTick() + state->delay); else state->completionEvent->process(); } @@ -234,7 +233,7 @@ DmaPort::recvRetry() if (transmitList.size() && backoffTime && !inRetry) { DPRINTF(DMA, "Scheduling backoff for %d\n", curTick()+backoffTime); if (!backoffEvent.scheduled()) - schedule(backoffEvent, backoffTime + curTick()); + device->schedule(backoffEvent, backoffTime + curTick()); } DPRINTF(DMA, "TransmitList: %d, backoffTime: %d inRetry: %d es: %d\n", transmitList.size(), backoffTime, inRetry, @@ -320,7 +319,7 @@ DmaPort::sendDma() !backoffEvent.scheduled()) { DPRINTF(DMA, "-- Scheduling backoff timer for %d\n", backoffTime+curTick()); - schedule(backoffEvent, backoffTime + curTick()); + device->schedule(backoffEvent, backoffTime + curTick()); } } else if (state == Enums::atomic) { transmitList.pop_front(); @@ -342,7 +341,8 @@ DmaPort::sendDma() if (state->totBytes == state->numBytes) { if (state->completionEvent) { assert(!state->completionEvent->scheduled()); - schedule(state->completionEvent, curTick() + lat + state->delay); + device->schedule(state->completionEvent, + curTick() + lat + state->delay); } delete state; delete pkt->req; diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh index 083ab43cb..ea2364f33 100644 --- a/src/dev/io_device.hh +++ b/src/dev/io_device.hh @@ -50,7 +50,7 @@ class System; * The PioPort class is a programmed i/o port that all devices that are * sensitive to an address range use. The port takes all the memory * access types and roles them into one read() and write() call that the device - * must respond to. The device must also provide the addressRanges() function + * must respond to. The device must also provide getAddrRanges() function * with which it returns the address ranges it is interested in. */ class PioPort : public SimpleTimingPort @@ -61,8 +61,7 @@ class PioPort : public SimpleTimingPort virtual Tick recvAtomic(PacketPtr pkt); - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop); + virtual AddrRangeList getAddrRanges(); public: @@ -132,9 +131,6 @@ class DmaPort : public Port /** Port accesses a cache which requires snooping */ bool recvSnoops; - /** Records snoop response so we only reply once to a status change */ - bool snoopRangeSent; - virtual bool recvTiming(PacketPtr pkt); virtual Tick recvAtomic(PacketPtr pkt) { @@ -149,25 +145,16 @@ class DmaPort : public Port panic("dma port shouldn't be used for pio access."); } - virtual void recvStatusChange(Status status) + virtual void recvRangeChange() { - if (recvSnoops) { - if (status == RangeChange) { - if (!snoopRangeSent) { - snoopRangeSent = true; - sendStatusChange(Port::RangeChange); - } - return; - } - panic("Unexpected recvStatusChange\n"); - } + // DMA port is a master with a single slave so there is no choice and + // thus no need to worry about any address changes } virtual void recvRetry() ; - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { resp.clear(); snoop = recvSnoops; } + virtual bool isSnooping() + { return recvSnoops; } void queueDma(PacketPtr pkt, bool front = false); void sendDma(); @@ -191,7 +178,7 @@ class DmaPort : public Port /** * This device is the base class which all devices senstive to an address range * inherit from. There are three pure virtual functions which all devices must - * implement addressRanges(), read(), and write(). The magic do choose which + * implement getAddrRanges(), read(), and write(). The magic do choose which * mode we are in, etc is handled by the PioPort so the device doesn't have to * bother. */ @@ -204,7 +191,13 @@ class PioDevice : public MemObject * that it sees. */ PioPort *pioPort; - virtual void addressRanges(AddrRangeList &range_list) = 0; + /** + * Every PIO device is obliged to provide an implementation that + * returns the address ranges the device responds to. + * + * @return a list of non-overlapping address ranges + */ + virtual AddrRangeList getAddrRanges() = 0; /** Pure virtual function that the device must implement. Called * when a read command is recieved by the port. @@ -263,10 +256,12 @@ class BasicPioDevice : public PioDevice return dynamic_cast<const Params *>(_params); } - /** return the address ranges that this device responds to. - * @param range_list range list to populate with ranges + /** + * Determine the address ranges that this device responds to. + * + * @return a list of non-overlapping address ranges */ - void addressRanges(AddrRangeList &range_list); + virtual AddrRangeList getAddrRanges(); }; diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc index a7bc6d0ab..eb6eb6353 100644 --- a/src/dev/ns_gige.cc +++ b/src/dev/ns_gige.cc @@ -465,16 +465,16 @@ NSGigE::write(PacketPtr pkt) reg & CFGR_DUPSTS || reg & CFGR_RESERVED || reg & CFGR_T64ADDR || - reg & CFGR_PCI64_DET) - - // First clear all writable bits - regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | - CFGR_RESERVED | CFGR_T64ADDR | - CFGR_PCI64_DET; - // Now set the appropriate writable bits - regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | - CFGR_RESERVED | CFGR_T64ADDR | - CFGR_PCI64_DET); + reg & CFGR_PCI64_DET) { + // First clear all writable bits + regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | + CFGR_RESERVED | CFGR_T64ADDR | + CFGR_PCI64_DET; + // Now set the appropriate writable bits + regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | + CFGR_RESERVED | CFGR_T64ADDR | + CFGR_PCI64_DET); + } // all these #if 0's are because i don't THINK the kernel needs to // have these implemented. if there is a problem relating to one of diff --git a/src/dev/pciconfigall.cc b/src/dev/pciconfigall.cc index 55b439857..e7130e11d 100644 --- a/src/dev/pciconfigall.cc +++ b/src/dev/pciconfigall.cc @@ -86,11 +86,12 @@ PciConfigAll::write(PacketPtr pkt) } -void -PciConfigAll::addressRanges(AddrRangeList &range_list) +AddrRangeList +PciConfigAll::getAddrRanges() { - range_list.clear(); - range_list.push_back(RangeSize(pioAddr, params()->size)); + AddrRangeList ranges; + ranges.push_back(RangeSize(pioAddr, params()->size)); + return ranges; } diff --git a/src/dev/pciconfigall.hh b/src/dev/pciconfigall.hh index b3f6d1472..e594838fa 100644 --- a/src/dev/pciconfigall.hh +++ b/src/dev/pciconfigall.hh @@ -80,7 +80,7 @@ class PciConfigAll : public PioDevice virtual Tick write(PacketPtr pkt); - void addressRanges(AddrRangeList &range_list); + AddrRangeList getAddrRanges(); private: Addr pioAddr; diff --git a/src/dev/pcidev.cc b/src/dev/pcidev.cc index ac315341a..42c803553 100644 --- a/src/dev/pcidev.cc +++ b/src/dev/pcidev.cc @@ -72,13 +72,13 @@ PciDev::PciConfigPort::recvAtomic(PacketPtr pkt) return pkt->isRead() ? device->readConfig(pkt) : device->writeConfig(pkt); } -void -PciDev::PciConfigPort::getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) +AddrRangeList +PciDev::PciConfigPort::getAddrRanges() { - snoop = false;; + AddrRangeList ranges; if (configAddr != ULL(-1)) - resp.push_back(RangeSize(configAddr, PCI_CONFIG_SIZE+1)); + ranges.push_back(RangeSize(configAddr, PCI_CONFIG_SIZE+1)); + return ranges; } @@ -150,9 +150,9 @@ PciDev::PciDev(const Params *p) void PciDev::init() { - if (!configPort) - panic("pci config port not connected to anything!"); - configPort->sendStatusChange(Port::RangeChange); + if (!configPort && !configPort->isConnected()) + panic("PCI config port on %s not connected to anything!\n", name()); + configPort->sendRangeChange(); PioDevice::init(); } @@ -207,14 +207,15 @@ PciDev::readConfig(PacketPtr pkt) } -void -PciDev::addressRanges(AddrRangeList &range_list) +AddrRangeList +PciDev::getAddrRanges() { + AddrRangeList ranges; int x = 0; - range_list.clear(); for (x = 0; x < 6; x++) if (BARAddrs[x] != 0) - range_list.push_back(RangeSize(BARAddrs[x],BARSize[x])); + ranges.push_back(RangeSize(BARAddrs[x],BARSize[x])); + return ranges; } Tick @@ -301,7 +302,7 @@ PciDev::writeConfig(PacketPtr pkt) BARAddrs[barnum] = BAR_IO_SPACE(he_old_bar) ? platform->calcPciIOAddr(he_new_bar) : platform->calcPciMemAddr(he_new_bar); - pioPort->sendStatusChange(Port::RangeChange); + pioPort->sendRangeChange(); } } config.baseAddr[barnum] = htole((he_new_bar & ~bar_mask) | @@ -354,7 +355,7 @@ PciDev::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_ARRAY(BARAddrs, sizeof(BARAddrs) / sizeof(BARAddrs[0])); UNSERIALIZE_ARRAY(config.data, sizeof(config.data) / sizeof(config.data[0])); - pioPort->sendStatusChange(Port::RangeChange); + pioPort->sendRangeChange(); } diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh index dae005a97..c0c3df0a6 100644 --- a/src/dev/pcidev.hh +++ b/src/dev/pcidev.hh @@ -65,8 +65,7 @@ class PciDev : public DmaDevice virtual Tick recvAtomic(PacketPtr pkt); - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop); + virtual AddrRangeList getAddrRanges(); Platform *platform; @@ -187,10 +186,12 @@ class PciDev : public DmaDevice interruptLine() { return letoh(config.interruptLine); } - /** return the address ranges that this device responds to. - * @params range_list range list to populate with ranges + /** + * Determine the address ranges that this device responds to. + * + * @return a list of non-overlapping address ranges */ - void addressRanges(AddrRangeList &range_list); + AddrRangeList getAddrRanges(); /** * Constructor for PCI Dev. This function copies data from the diff --git a/src/dev/simple_disk.cc b/src/dev/simple_disk.cc index 4bf24b1cd..9cec638b8 100644 --- a/src/dev/simple_disk.cc +++ b/src/dev/simple_disk.cc @@ -46,7 +46,7 @@ #include "debug/SimpleDiskData.hh" #include "dev/disk_image.hh" #include "dev/simple_disk.hh" -#include "mem/port.hh" +#include "mem/port_proxy.hh" #include "sim/system.hh" using namespace std; @@ -70,7 +70,7 @@ SimpleDisk::read(Addr addr, baddr_t block, int count) const for (int i = 0, j = 0; i < count; i += SectorSize, j++) image->read(data + i, block + j); - system->functionalPort->writeBlob(addr, data, count); + system->physProxy->writeBlob(addr, data, count); DPRINTF(SimpleDisk, "read block=%#x len=%d\n", (uint64_t)block, count); DDUMP(SimpleDiskData, data, count); diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc index b87dfa704..741442918 100644 --- a/src/dev/sinic.cc +++ b/src/dev/sinic.cc @@ -1714,7 +1714,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion) if (transmitTick) schedule(txEvent, curTick() + transmitTick); - pioPort->sendStatusChange(Port::RangeChange); + pioPort->sendRangeChange(); } diff --git a/src/dev/sparc/iob.cc b/src/dev/sparc/iob.cc index 008e063e0..757c50a24 100644 --- a/src/dev/sparc/iob.cc +++ b/src/dev/sparc/iob.cc @@ -323,12 +323,13 @@ Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1) return true; } -void -Iob::addressRanges(AddrRangeList &range_list) +AddrRangeList +Iob::getAddrRanges() { - range_list.clear(); - range_list.push_back(RangeSize(iobManAddr, iobManSize)); - range_list.push_back(RangeSize(iobJBusAddr, iobJBusSize)); + AddrRangeList ranges; + ranges.push_back(RangeSize(iobManAddr, iobManSize)); + ranges.push_back(RangeSize(iobJBusAddr, iobJBusSize)); + return ranges; } diff --git a/src/dev/sparc/iob.hh b/src/dev/sparc/iob.hh index 7391b1ccd..d6a47ce19 100644 --- a/src/dev/sparc/iob.hh +++ b/src/dev/sparc/iob.hh @@ -141,7 +141,7 @@ class Iob : public PioDevice bool receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1); - void addressRanges(AddrRangeList &range_list); + AddrRangeList getAddrRanges(); virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc index 877e9fb47..671d5505f 100644 --- a/src/dev/uart8250.cc +++ b/src/dev/uart8250.cc @@ -286,16 +286,14 @@ Uart8250::dataAvailable() } -void -Uart8250::addressRanges(AddrRangeList &range_list) +AddrRangeList +Uart8250::getAddrRanges() { - assert(pioSize != 0); - range_list.clear(); - range_list.push_back(RangeSize(pioAddr, pioSize)); + AddrRangeList ranges; + ranges.push_back(RangeSize(pioAddr, pioSize)); + return ranges; } - - void Uart8250::serialize(ostream &os) { diff --git a/src/dev/uart8250.hh b/src/dev/uart8250.hh index 79c31d5cf..f31def2ea 100644 --- a/src/dev/uart8250.hh +++ b/src/dev/uart8250.hh @@ -100,7 +100,7 @@ class Uart8250 : public Uart virtual Tick read(PacketPtr pkt); virtual Tick write(PacketPtr pkt); - virtual void addressRanges(AddrRangeList &range_list); + virtual AddrRangeList getAddrRanges(); /** * Inform the uart that there is data available. diff --git a/src/dev/x86/SouthBridge.py b/src/dev/x86/SouthBridge.py index c23ecf01c..baff35e0b 100644 --- a/src/dev/x86/SouthBridge.py +++ b/src/dev/x86/SouthBridge.py @@ -105,6 +105,8 @@ class SouthBridge(SimObject): self.cmos.pio = bus.port self.dma1.pio = bus.port self.ide.pio = bus.port + self.ide.config = bus.port + self.ide.dma = bus.port self.keyboard.pio = bus.port self.pic1.pio = bus.port self.pic2.pio = bus.port diff --git a/src/dev/x86/i8042.cc b/src/dev/x86/i8042.cc index a0786c95c..746a08778 100644 --- a/src/dev/x86/i8042.cc +++ b/src/dev/x86/i8042.cc @@ -43,12 +43,13 @@ const uint8_t CommandAck = 0xfa; const uint8_t CommandNack = 0xfe; const uint8_t BatSuccessful = 0xaa; -void -X86ISA::I8042::addressRanges(AddrRangeList &range_list) +AddrRangeList +X86ISA::I8042::getAddrRanges() { - range_list.clear(); - range_list.push_back(RangeSize(dataPort, 1)); - range_list.push_back(RangeSize(commandPort, 1)); + AddrRangeList ranges; + ranges.push_back(RangeSize(dataPort, 1)); + ranges.push_back(RangeSize(commandPort, 1)); + return ranges; } void diff --git a/src/dev/x86/i8042.hh b/src/dev/x86/i8042.hh index be12c4e96..61220b45d 100644 --- a/src/dev/x86/i8042.hh +++ b/src/dev/x86/i8042.hh @@ -255,7 +255,7 @@ class I8042 : public BasicPioDevice commandByte.keyboardFullInt = 1; } - void addressRanges(AddrRangeList &range_list); + AddrRangeList getAddrRanges(); Tick read(PacketPtr pkt); diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh index 00ba2800d..dfef059c3 100644 --- a/src/dev/x86/i82094aa.hh +++ b/src/dev/x86/i82094aa.hh @@ -101,19 +101,21 @@ class I82094AA : public PioDevice, public IntDev Tick read(PacketPtr pkt); Tick write(PacketPtr pkt); - void addressRanges(AddrRangeList &range_list) + AddrRangeList getAddrRanges() { - range_list.clear(); - range_list.push_back(RangeEx(pioAddr, pioAddr + 4)); - range_list.push_back(RangeEx(pioAddr + 16, pioAddr + 20)); + AddrRangeList ranges; + ranges.push_back(RangeEx(pioAddr, pioAddr + 4)); + ranges.push_back(RangeEx(pioAddr + 16, pioAddr + 20)); + return ranges; } - void getIntAddrRange(AddrRangeList &range_list) + AddrRangeList getIntAddrRange() { - range_list.clear(); - range_list.push_back(RangeEx(x86InterruptAddress(initialApicId, 0), - x86InterruptAddress(initialApicId, 0) + - PhysAddrAPICRangeSize)); + AddrRangeList ranges; + ranges.push_back(RangeEx(x86InterruptAddress(initialApicId, 0), + x86InterruptAddress(initialApicId, 0) + + PhysAddrAPICRangeSize)); + return ranges; } void writeReg(uint8_t offset, uint32_t value); diff --git a/src/dev/x86/intdev.cc b/src/dev/x86/intdev.cc index 0c0fa73cf..a991005bc 100644 --- a/src/dev/x86/intdev.cc +++ b/src/dev/x86/intdev.cc @@ -54,7 +54,7 @@ X86ISA::IntDev::init() if (!intPort) { panic("Int port not connected to anything!"); } - intPort->sendStatusChange(Port::RangeChange); + intPort->sendRangeChange(); } X86ISA::IntSourcePin * diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh index 1b3efdbb5..9713d042b 100644 --- a/src/dev/x86/intdev.hh +++ b/src/dev/x86/intdev.hh @@ -63,10 +63,9 @@ class IntDev { } - void getDeviceAddressRanges(AddrRangeList &resp, bool &snoop) + AddrRangeList getAddrRanges() { - snoop = false; - device->getIntAddrRange(resp); + return device->getIntAddrRange(); } Tick recvMessage(PacketPtr pkt) @@ -134,8 +133,8 @@ class IntDev return 0; } - virtual void - getIntAddrRange(AddrRangeList &range_list) + virtual AddrRangeList + getIntAddrRange() { panic("intAddrRange not implemented.\n"); } diff --git a/src/kern/tru64/tru64.hh b/src/kern/tru64/tru64.hh index 8b8091f0d..3b9bbd2bf 100644 --- a/src/kern/tru64/tru64.hh +++ b/src/kern/tru64/tru64.hh @@ -62,7 +62,7 @@ typedef struct stat global_stat; typedef struct statfs global_statfs; typedef struct dirent global_dirent; -class TranslatingPort; +class SETranslatingPortProxy; /// /// This class encapsulates the types, structures, constants, @@ -397,7 +397,8 @@ class Tru64 : public OperatingSystem /// memory space. Used by statfs() and fstatfs(). template <class T> static void - copyOutStatfsBuf(TranslatingPort *mem, Addr addr, global_statfs *host) + copyOutStatfsBuf(SETranslatingPortProxy *mem, Addr addr, + global_statfs *host) { using namespace TheISA; @@ -446,7 +447,7 @@ class Tru64 : public OperatingSystem // just pass basep through uninterpreted. TypedBufferArg<int64_t> basep(tgt_basep); - basep.copyIn(tc->getMemPort()); + basep.copyIn(tc->getMemProxy()); long host_basep = (off_t)htog((int64_t)*basep); int host_result = getdirentries(fd, host_buf, tgt_nbytes, &host_basep); @@ -473,7 +474,7 @@ class Tru64 : public OperatingSystem tgt_dp->d_reclen = tgt_bufsize; tgt_dp->d_namlen = namelen; strcpy(tgt_dp->d_name, host_dp->d_name); - tgt_dp.copyOut(tc->getMemPort()); + tgt_dp.copyOut(tc->getMemProxy()); tgt_buf_ptr += tgt_bufsize; host_buf_ptr += host_dp->d_reclen; @@ -482,7 +483,7 @@ class Tru64 : public OperatingSystem delete [] host_buf; *basep = htog((int64_t)host_basep); - basep.copyOut(tc->getMemPort()); + basep.copyOut(tc->getMemProxy()); return tgt_buf_ptr - tgt_buf; #endif @@ -498,7 +499,7 @@ class Tru64 : public OperatingSystem int index = 0; TypedBufferArg<Tru64::sigcontext> sc(process->getSyscallArg(tc, index)); - sc.copyIn(tc->getMemPort()); + sc.copyIn(tc->getMemProxy()); // Restore state from sigcontext structure. // Note that we'll advance PC <- NPC before the end of the cycle, @@ -533,7 +534,7 @@ class Tru64 : public OperatingSystem int index = 0; TypedBufferArg<Tru64::vm_stack> argp(process->getSyscallArg(tc, index)); - argp.copyIn(tc->getMemPort()); + argp.copyIn(tc->getMemProxy()); int stack_size = gtoh(argp->rsize) + gtoh(argp->ysize) + gtoh(argp->gsize); @@ -560,7 +561,7 @@ class Tru64 : public OperatingSystem process->allocateMem(rounded_stack_base, rounded_stack_size); argp->address = gtoh(rounded_stack_base); - argp.copyOut(tc->getMemPort()); + argp.copyOut(tc->getMemProxy()); return 0; } @@ -584,7 +585,7 @@ class Tru64 : public OperatingSystem attrp(process->getSyscallArg(tc, index)); TypedBufferArg<Addr> configptr_ptr(process->getSyscallArg(tc, index)); - attrp.copyIn(tc->getMemPort()); + attrp.copyIn(tc->getMemProxy()); if (gtoh(attrp->nxm_version) != NXM_LIB_VERSION) { cerr << "nxm_task_init: thread library version mismatch! " @@ -678,10 +679,10 @@ class Tru64 : public OperatingSystem int size = cur_addr - base_addr; process->allocateMem(base_addr, roundUp(size, VMPageSize)); - config.copyOut(tc->getMemPort()); - slot_state.copyOut(tc->getMemPort()); - rad_state.copyOut(tc->getMemPort()); - configptr_ptr.copyOut(tc->getMemPort()); + config.copyOut(tc->getMemProxy()); + slot_state.copyOut(tc->getMemProxy()); + rad_state.copyOut(tc->getMemProxy()); + configptr_ptr.copyOut(tc->getMemProxy()); return 0; } @@ -720,7 +721,7 @@ class Tru64 : public OperatingSystem int thread_index = process->getSyscallArg(tc, index); // get attribute args - attrp.copyIn(tc->getMemPort()); + attrp.copyIn(tc->getMemProxy()); if (gtoh(attrp->version) != NXM_LIB_VERSION) { cerr << "nxm_thread_create: thread library version mismatch! " @@ -745,7 +746,7 @@ class Tru64 : public OperatingSystem TypedBufferArg<Tru64::nxm_shared> rad_state(0x14000, rad_state_size); - rad_state.copyIn(tc->getMemPort()); + rad_state.copyIn(tc->getMemProxy()); uint64_t uniq_val = gtoh(attrp->pthid) - gtoh(rad_state->nxm_uniq_offset); @@ -756,7 +757,7 @@ class Tru64 : public OperatingSystem // This is supposed to be a port number. Make something up. *kidp = htog(99); - kidp.copyOut(tc->getMemPort()); + kidp.copyOut(tc->getMemProxy()); return 0; } else if (gtoh(attrp->type) == Tru64::NXM_TYPE_VP) { @@ -770,7 +771,7 @@ class Tru64 : public OperatingSystem ssp->nxm_u.pth_id = attrp->pthid; ssp->nxm_u.nxm_active = htog(uniq_val | 1); - rad_state.copyOut(tc->getMemPort()); + rad_state.copyOut(tc->getMemProxy()); Addr slot_state_addr = 0x12000 + sizeof(Tru64::nxm_config_info); int slot_state_size = @@ -780,7 +781,7 @@ class Tru64 : public OperatingSystem slot_state(slot_state_addr, slot_state_size); - slot_state.copyIn(tc->getMemPort()); + slot_state.copyIn(tc->getMemProxy()); if (slot_state[thread_index] != Tru64::NXM_SLOT_AVAIL) { cerr << "nxm_thread_createFunc: requested VP slot " @@ -792,7 +793,7 @@ class Tru64 : public OperatingSystem // doesn't work anyway slot_state[thread_index] = Tru64::NXM_SLOT_BOUND; - slot_state.copyOut(tc->getMemPort()); + slot_state.copyOut(tc->getMemProxy()); // Find a free simulator thread context. ThreadContext *tc = process->findFreeContext(); @@ -804,7 +805,7 @@ class Tru64 : public OperatingSystem // and get away with just sticking the thread index // here. *kidp = htog(thread_index); - kidp.copyOut(tc->getMemPort()); + kidp.copyOut(tc->getMemProxy()); return 0; } @@ -945,12 +946,12 @@ class Tru64 : public OperatingSystem TypedBufferArg<uint64_t> lockp(uaddr); - lockp.copyIn(tc->getMemPort()); + lockp.copyIn(tc->getMemProxy()); if (gtoh(*lockp) == 0) { // lock is free: grab it *lockp = htog(1); - lockp.copyOut(tc->getMemPort()); + lockp.copyOut(tc->getMemProxy()); } else { // lock is busy: disable until free process->waitList.push_back(Process::WaitRec(uaddr, tc)); @@ -964,7 +965,7 @@ class Tru64 : public OperatingSystem { TypedBufferArg<uint64_t> lockp(uaddr); - lockp.copyIn(tc->getMemPort()); + lockp.copyIn(tc->getMemProxy()); assert(*lockp != 0); // Check for a process waiting on the lock. @@ -973,7 +974,7 @@ class Tru64 : public OperatingSystem // clear lock field if no waiting context is taking over the lock if (num_waiting == 0) { *lockp = 0; - lockp.copyOut(tc->getMemPort()); + lockp.copyOut(tc->getMemProxy()); } } @@ -1004,12 +1005,12 @@ class Tru64 : public OperatingSystem Addr uaddr = process->getSyscallArg(tc, index); TypedBufferArg<uint64_t> lockp(uaddr); - lockp.copyIn(tc->getMemPort()); + lockp.copyIn(tc->getMemProxy()); if (gtoh(*lockp) == 0) { // lock is free: grab it *lockp = htog(1); - lockp.copyOut(tc->getMemPort()); + lockp.copyOut(tc->getMemProxy()); return 0; } else { return 1; @@ -1070,7 +1071,7 @@ class Tru64 : public OperatingSystem TypedBufferArg<uint64_t> lockp(lock_addr); // user is supposed to acquire lock before entering - lockp.copyIn(tc->getMemPort()); + lockp.copyIn(tc->getMemProxy()); assert(gtoh(*lockp) != 0); m5_unlock_mutex(lock_addr, process, tc); @@ -1159,13 +1160,13 @@ class Tru64_F64 : public Tru64 typedef F64_stat tgt_stat; /* - static void copyOutStatBuf(TranslatingPort *mem, Addr addr, + static void copyOutStatBuf(SETranslatingPortProxy *mem, Addr addr, global_stat *host) { Tru64::copyOutStatBuf<Tru64::F64_stat>(mem, addr, host); }*/ - static void copyOutStatfsBuf(TranslatingPort *mem, Addr addr, + static void copyOutStatfsBuf(SETranslatingPortProxy *mem, Addr addr, global_statfs *host) { Tru64::copyOutStatfsBuf<Tru64::F64_statfs>(mem, addr, host); @@ -1205,13 +1206,13 @@ class Tru64_PreF64 : public Tru64 typedef pre_F64_stat tgt_stat; /* - static void copyOutStatBuf(TranslatingPort *mem, Addr addr, + static void copyOutStatBuf(SETranslatingPortProxy *mem, Addr addr, global_stat *host) { Tru64::copyOutStatBuf<Tru64::pre_F64_stat>(mem, addr, host); }*/ - static void copyOutStatfsBuf(TranslatingPort *mem, Addr addr, + static void copyOutStatfsBuf(SETranslatingPortProxy *mem, Addr addr, global_statfs *host) { Tru64::copyOutStatfsBuf<Tru64::pre_F64_statfs>(mem, addr, host); diff --git a/src/kern/tru64/tru64_events.cc b/src/kern/tru64/tru64_events.cc index 216f81b86..5638a2350 100644 --- a/src/kern/tru64/tru64_events.cc +++ b/src/kern/tru64/tru64_events.cc @@ -57,12 +57,12 @@ BadAddrEvent::process(ThreadContext *tc) uint64_t a0 = tc->readIntReg(16); - AddrRangeList resp; - bool snoop; AddrRangeIter iter; bool found = false; - tc->getPhysPort()->getPeerAddressRanges(resp, snoop); + Port* dataPort = tc->getCpuPtr()->getPort("dcache_port"); + + AddrRangeList resp = dataPort->getPeer()->getAddrRanges(); for (iter = resp.begin(); iter != resp.end(); iter++) { if (*iter == (K0Seg2Phys(a0) & PAddrImplMask)) found = true; diff --git a/src/mem/Bridge.py b/src/mem/Bridge.py index b48e1684d..38b344613 100644 --- a/src/mem/Bridge.py +++ b/src/mem/Bridge.py @@ -31,16 +31,12 @@ from MemObject import MemObject class Bridge(MemObject): type = 'Bridge' - side_a = Port('Side A port') - side_b = Port('Side B port') - req_size_a = Param.Int(16, "The number of requests to buffer") - req_size_b = Param.Int(16, "The number of requests to buffer") - resp_size_a = Param.Int(16, "The number of requests to buffer") - resp_size_b = Param.Int(16, "The number of requests to buffer") + slave = Port('Slave port') + master = Port('Master port') + req_size = Param.Int(16, "The number of requests to buffer") + resp_size = Param.Int(16, "The number of requests to buffer") delay = Param.Latency('0ns', "The latency of this bridge") nack_delay = Param.Latency('0ns', "The latency of this bridge") write_ack = Param.Bool(False, "Should this bridge ack writes") - filter_ranges_a = VectorParam.AddrRange([], - "What addresses shouldn't be passed through the side of the bridge") - filter_ranges_b = VectorParam.AddrRange([], - "What addresses shouldn't be passed through the side of the bridge") + ranges = VectorParam.AddrRange([AllMemory], + "Address ranges to pass through the bridge") diff --git a/src/mem/SConscript b/src/mem/SConscript index 8418a4f51..09cc93c77 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -41,14 +41,14 @@ Source('mport.cc') Source('packet.cc') Source('port.cc') Source('tport.cc') -Source('vport.cc') +Source('fs_translating_port_proxy.cc') +Source('se_translating_port_proxy.cc') if env['TARGET_ISA'] != 'no': SimObject('PhysicalMemory.py') Source('dram.cc') Source('page_table.cc') Source('physical.cc') - Source('translating_port.cc') DebugFlag('Bus') DebugFlag('BusAddrRanges') diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc index 9e5e64069..b48662118 100644 --- a/src/mem/bridge.cc +++ b/src/mem/bridge.cc @@ -1,5 +1,16 @@ - /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * @@ -28,58 +39,67 @@ * * Authors: Ali Saidi * Steve Reinhardt + * Andreas Hansson */ /** * @file - * Definition of a simple bus bridge without buffering. + * Implementation of a memory-mapped bus bridge that connects a master + * and a slave through a request and response queue. */ -#include <algorithm> - -#include "base/range_ops.hh" #include "base/trace.hh" #include "debug/BusBridge.hh" #include "mem/bridge.hh" #include "params/Bridge.hh" -Bridge::BridgePort::BridgePort(const std::string &_name, - Bridge *_bridge, BridgePort *_otherPort, - int _delay, int _nack_delay, int _req_limit, - int _resp_limit, - std::vector<Range<Addr> > filter_ranges) - : Port(_name, _bridge), bridge(_bridge), otherPort(_otherPort), - delay(_delay), nackDelay(_nack_delay), filterRanges(filter_ranges), - outstandingResponses(0), queuedRequests(0), inRetry(false), - reqQueueLimit(_req_limit), respQueueLimit(_resp_limit), sendEvent(this) +Bridge::BridgeSlavePort::BridgeSlavePort(const std::string &_name, + Bridge* _bridge, + BridgeMasterPort* _masterPort, + int _delay, int _nack_delay, + int _resp_limit, + std::vector<Range<Addr> > _ranges) + : Port(_name, _bridge), bridge(_bridge), masterPort(_masterPort), + delay(_delay), nackDelay(_nack_delay), + ranges(_ranges.begin(), _ranges.end()), + outstandingResponses(0), inRetry(false), + respQueueLimit(_resp_limit), sendEvent(this) +{ +} + +Bridge::BridgeMasterPort::BridgeMasterPort(const std::string &_name, + Bridge* _bridge, + BridgeSlavePort* _slavePort, + int _delay, int _req_limit) + : Port(_name, _bridge), bridge(_bridge), slavePort(_slavePort), + delay(_delay), inRetry(false), reqQueueLimit(_req_limit), sendEvent(this) { } Bridge::Bridge(Params *p) : MemObject(p), - portA(p->name + "-portA", this, &portB, p->delay, p->nack_delay, - p->req_size_a, p->resp_size_a, p->filter_ranges_a), - portB(p->name + "-portB", this, &portA, p->delay, p->nack_delay, - p->req_size_b, p->resp_size_b, p->filter_ranges_b), + slavePort(p->name + "-slave", this, &masterPort, p->delay, + p->nack_delay, p->resp_size, p->ranges), + masterPort(p->name + "-master", this, &slavePort, p->delay, p->req_size), ackWrites(p->write_ack), _params(p) { if (ackWrites) panic("No support for acknowledging writes\n"); } -Port * +Port* Bridge::getPort(const std::string &if_name, int idx) { - BridgePort *port; + Port* port; - if (if_name == "side_a") - port = &portA; - else if (if_name == "side_b") - port = &portB; + if (if_name == "slave") + port = &slavePort; + else if (if_name == "master") + port = &masterPort; else return NULL; - if (port->getPeer() != NULL && !port->getPeer()->isDefaultPort()) + if (port->getPeer() != NULL) panic("bridge side %s already connected to %s.", if_name, port->getPeer()->name()); return port; @@ -89,106 +109,133 @@ Bridge::getPort(const std::string &if_name, int idx) void Bridge::init() { - // Make sure that both sides are connected to. - if (!portA.isConnected() || !portB.isConnected()) + // make sure both sides are connected and have the same block size + if (!slavePort.isConnected() || !masterPort.isConnected()) fatal("Both ports of bus bridge are not connected to a bus.\n"); - if (portA.peerBlockSize() != portB.peerBlockSize()) - fatal("port A size %d, port B size %d \n " \ + if (slavePort.peerBlockSize() != masterPort.peerBlockSize()) + fatal("Slave port size %d, master port size %d \n " \ "Busses don't have the same block size... Not supported.\n", - portA.peerBlockSize(), portB.peerBlockSize()); + slavePort.peerBlockSize(), masterPort.peerBlockSize()); + + // notify the master side of our address ranges + slavePort.sendRangeChange(); +} + +bool +Bridge::BridgeSlavePort::respQueueFull() +{ + return outstandingResponses == respQueueLimit; } bool -Bridge::BridgePort::respQueueFull() +Bridge::BridgeMasterPort::reqQueueFull() { - assert(outstandingResponses >= 0 && outstandingResponses <= respQueueLimit); - return outstandingResponses >= respQueueLimit; + return requestQueue.size() == reqQueueLimit; } bool -Bridge::BridgePort::reqQueueFull() +Bridge::BridgeMasterPort::recvTiming(PacketPtr pkt) { - assert(queuedRequests >= 0 && queuedRequests <= reqQueueLimit); - return queuedRequests >= reqQueueLimit; + // should only see responses on the master side + assert(pkt->isResponse()); + + // all checks are done when the request is accepted on the slave + // side, so we are guaranteed to have space for the response + + DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", + pkt->getSrc(), pkt->getDest(), pkt->getAddr()); + + DPRINTF(BusBridge, "Request queue size: %d\n", requestQueue.size()); + + slavePort->queueForSendTiming(pkt); + + return true; } -/** Function called by the port when the bus is receiving a Timing - * transaction.*/ bool -Bridge::BridgePort::recvTiming(PacketPtr pkt) +Bridge::BridgeSlavePort::recvTiming(PacketPtr pkt) { + // should only see requests on the slave side + assert(pkt->isRequest()); + DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", - pkt->getSrc(), pkt->getDest(), pkt->getAddr()); + pkt->getSrc(), pkt->getDest(), pkt->getAddr()); - DPRINTF(BusBridge, "Local queue size: %d outreq: %d outresp: %d\n", - sendQueue.size(), queuedRequests, outstandingResponses); - DPRINTF(BusBridge, "Remote queue size: %d outreq: %d outresp: %d\n", - otherPort->sendQueue.size(), otherPort->queuedRequests, - otherPort->outstandingResponses); + DPRINTF(BusBridge, "Response queue size: %d outresp: %d\n", + responseQueue.size(), outstandingResponses); - if (pkt->isRequest() && otherPort->reqQueueFull()) { - DPRINTF(BusBridge, "Remote queue full, nacking\n"); + if (masterPort->reqQueueFull()) { + DPRINTF(BusBridge, "Request queue full, nacking\n"); nackRequest(pkt); return true; } if (pkt->needsResponse()) { if (respQueueFull()) { - DPRINTF(BusBridge, "Local queue full, no space for response, nacking\n"); - DPRINTF(BusBridge, "queue size: %d outreq: %d outstanding resp: %d\n", - sendQueue.size(), queuedRequests, outstandingResponses); + DPRINTF(BusBridge, + "Response queue full, no space for response, nacking\n"); + DPRINTF(BusBridge, + "queue size: %d outstanding resp: %d\n", + responseQueue.size(), outstandingResponses); nackRequest(pkt); return true; } else { DPRINTF(BusBridge, "Request Needs response, reserving space\n"); + assert(outstandingResponses != respQueueLimit); ++outstandingResponses; } } - otherPort->queueForSendTiming(pkt); + masterPort->queueForSendTiming(pkt); return true; } void -Bridge::BridgePort::nackRequest(PacketPtr pkt) +Bridge::BridgeSlavePort::nackRequest(PacketPtr pkt) { // Nack the packet pkt->makeTimingResponse(); pkt->setNacked(); - //put it on the list to send + // The Nack packets are stored in the response queue just like any + // other response, but they do not occupy any space as this is + // tracked by the outstandingResponses, this guarantees space for + // the Nack packets, but implicitly means we have an (unrealistic) + // unbounded Nack queue. + + // put it on the list to send Tick readyTime = curTick() + nackDelay; PacketBuffer *buf = new PacketBuffer(pkt, readyTime, true); // nothing on the list, add it and we're done - if (sendQueue.empty()) { + if (responseQueue.empty()) { assert(!sendEvent.scheduled()); - schedule(sendEvent, readyTime); - sendQueue.push_back(buf); + bridge->schedule(sendEvent, readyTime); + responseQueue.push_back(buf); return; } assert(sendEvent.scheduled() || inRetry); // does it go at the end? - if (readyTime >= sendQueue.back()->ready) { - sendQueue.push_back(buf); + if (readyTime >= responseQueue.back()->ready) { + responseQueue.push_back(buf); return; } // ok, somewhere in the middle, fun - std::list<PacketBuffer*>::iterator i = sendQueue.begin(); - std::list<PacketBuffer*>::iterator end = sendQueue.end(); - std::list<PacketBuffer*>::iterator begin = sendQueue.begin(); + std::list<PacketBuffer*>::iterator i = responseQueue.begin(); + std::list<PacketBuffer*>::iterator end = responseQueue.end(); + std::list<PacketBuffer*>::iterator begin = responseQueue.begin(); bool done = false; while (i != end && !done) { if (readyTime < (*i)->ready) { if (i == begin) - reschedule(sendEvent, readyTime); - sendQueue.insert(i,buf); + bridge->reschedule(sendEvent, readyTime); + responseQueue.insert(i,buf); done = true; } i++; @@ -196,51 +243,60 @@ Bridge::BridgePort::nackRequest(PacketPtr pkt) assert(done); } - void -Bridge::BridgePort::queueForSendTiming(PacketPtr pkt) +Bridge::BridgeMasterPort::queueForSendTiming(PacketPtr pkt) { - if (pkt->isResponse()) { - // This is a response for a request we forwarded earlier. The - // corresponding PacketBuffer should be stored in the packet's - // senderState field. - - PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState); - assert(buf != NULL); - // set up new packet dest & senderState based on values saved - // from original request - buf->fixResponse(pkt); - - DPRINTF(BusBridge, "response, new dest %d\n", pkt->getDest()); - delete buf; + Tick readyTime = curTick() + delay; + PacketBuffer *buf = new PacketBuffer(pkt, readyTime); + + // If we're about to put this packet at the head of the queue, we + // need to schedule an event to do the transmit. Otherwise there + // should already be an event scheduled for sending the head + // packet. + if (requestQueue.empty()) { + bridge->schedule(sendEvent, readyTime); } + assert(requestQueue.size() != reqQueueLimit); - if (pkt->isRequest()) { - ++queuedRequests; - } + requestQueue.push_back(buf); +} +void +Bridge::BridgeSlavePort::queueForSendTiming(PacketPtr pkt) +{ + // This is a response for a request we forwarded earlier. The + // corresponding PacketBuffer should be stored in the packet's + // senderState field. + PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState); + assert(buf != NULL); + // set up new packet dest & senderState based on values saved + // from original request + buf->fixResponse(pkt); + + DPRINTF(BusBridge, "response, new dest %d\n", pkt->getDest()); + delete buf; Tick readyTime = curTick() + delay; - PacketBuffer *buf = new PacketBuffer(pkt, readyTime); + buf = new PacketBuffer(pkt, readyTime); // If we're about to put this packet at the head of the queue, we // need to schedule an event to do the transmit. Otherwise there // should already be an event scheduled for sending the head // packet. - if (sendQueue.empty()) { - schedule(sendEvent, readyTime); + if (responseQueue.empty()) { + bridge->schedule(sendEvent, readyTime); } - sendQueue.push_back(buf); + responseQueue.push_back(buf); } void -Bridge::BridgePort::trySend() +Bridge::BridgeMasterPort::trySend() { - assert(!sendQueue.empty()); + assert(!requestQueue.empty()); - PacketBuffer *buf = sendQueue.front(); + PacketBuffer *buf = requestQueue.front(); assert(buf->ready <= curTick()); @@ -249,110 +305,195 @@ Bridge::BridgePort::trySend() DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", buf->origSrc, pkt->getDest(), pkt->getAddr()); - bool wasReq = pkt->isRequest(); - bool was_nacked_here = buf->nackedHere; - // If the send was successful, make sure sender state was set to NULL // otherwise we could get a NACK back of a packet that didn't expect a // response and we would try to use freed memory. Packet::SenderState *old_sender_state = pkt->senderState; - if (pkt->isRequest() && !buf->expectResponse) + if (!buf->expectResponse) pkt->senderState = NULL; if (sendTiming(pkt)) { // send successful - sendQueue.pop_front(); - buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it + requestQueue.pop_front(); + // we no longer own packet, so it's not safe to look at it + buf->pkt = NULL; - if (buf->expectResponse) { - // Must wait for response - DPRINTF(BusBridge, " successful: awaiting response (%d)\n", - outstandingResponses); - } else { + if (!buf->expectResponse) { // no response expected... deallocate packet buffer now. DPRINTF(BusBridge, " successful: no response expected\n"); delete buf; } - if (wasReq) - --queuedRequests; - else if (!was_nacked_here) + // If there are more packets to send, schedule event to try again. + if (!requestQueue.empty()) { + buf = requestQueue.front(); + DPRINTF(BusBridge, "Scheduling next send\n"); + bridge->schedule(sendEvent, std::max(buf->ready, curTick() + 1)); + } + } else { + DPRINTF(BusBridge, " unsuccessful\n"); + pkt->senderState = old_sender_state; + inRetry = true; + } + + DPRINTF(BusBridge, "trySend: request queue size: %d\n", + requestQueue.size()); +} + +void +Bridge::BridgeSlavePort::trySend() +{ + assert(!responseQueue.empty()); + + PacketBuffer *buf = responseQueue.front(); + + assert(buf->ready <= curTick()); + + PacketPtr pkt = buf->pkt; + + DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", + buf->origSrc, pkt->getDest(), pkt->getAddr()); + + bool was_nacked_here = buf->nackedHere; + + // no need to worry about the sender state since we are not + // modifying it + + if (sendTiming(pkt)) { + DPRINTF(BusBridge, " successful\n"); + // send successful + responseQueue.pop_front(); + // this is a response... deallocate packet buffer now. + delete buf; + + if (!was_nacked_here) { + assert(outstandingResponses != 0); --outstandingResponses; + } // If there are more packets to send, schedule event to try again. - if (!sendQueue.empty()) { - buf = sendQueue.front(); + if (!responseQueue.empty()) { + buf = responseQueue.front(); DPRINTF(BusBridge, "Scheduling next send\n"); - schedule(sendEvent, std::max(buf->ready, curTick() + 1)); + bridge->schedule(sendEvent, std::max(buf->ready, curTick() + 1)); } } else { DPRINTF(BusBridge, " unsuccessful\n"); - pkt->senderState = old_sender_state; inRetry = true; } - DPRINTF(BusBridge, "trySend: queue size: %d outreq: %d outstanding resp: %d\n", - sendQueue.size(), queuedRequests, outstandingResponses); + DPRINTF(BusBridge, "trySend: queue size: %d outstanding resp: %d\n", + responseQueue.size(), outstandingResponses); } +void +Bridge::BridgeMasterPort::recvRetry() +{ + inRetry = false; + Tick nextReady = requestQueue.front()->ready; + if (nextReady <= curTick()) + trySend(); + else + bridge->schedule(sendEvent, nextReady); +} void -Bridge::BridgePort::recvRetry() +Bridge::BridgeSlavePort::recvRetry() { inRetry = false; - Tick nextReady = sendQueue.front()->ready; + Tick nextReady = responseQueue.front()->ready; if (nextReady <= curTick()) trySend(); else - schedule(sendEvent, nextReady); + bridge->schedule(sendEvent, nextReady); } -/** Function called by the port when the bus is receiving a Atomic - * transaction.*/ Tick -Bridge::BridgePort::recvAtomic(PacketPtr pkt) +Bridge::BridgeMasterPort::recvAtomic(PacketPtr pkt) { - return delay + otherPort->sendAtomic(pkt); + // master port should never receive any atomic access (panic only + // works once the other side, i.e. the busses, respects this) + // + //panic("Master port on %s got a recvAtomic\n", bridge->name()); + return 0; +} + +Tick +Bridge::BridgeSlavePort::recvAtomic(PacketPtr pkt) +{ + return delay + masterPort->sendAtomic(pkt); } -/** Function called by the port when the bus is receiving a Functional - * transaction.*/ void -Bridge::BridgePort::recvFunctional(PacketPtr pkt) +Bridge::BridgeMasterPort::recvFunctional(PacketPtr pkt) +{ + // master port should never receive any functional access (panic + // only works once the other side, i.e. the busses, respect this) + + // panic("Master port on %s got a recvFunctional\n", bridge->name()); +} + +void +Bridge::BridgeSlavePort::recvFunctional(PacketPtr pkt) { std::list<PacketBuffer*>::iterator i; pkt->pushLabel(name()); - for (i = sendQueue.begin(); i != sendQueue.end(); ++i) { + // check the response queue + for (i = responseQueue.begin(); i != responseQueue.end(); ++i) { if (pkt->checkFunctional((*i)->pkt)) { pkt->makeResponse(); return; } } + // also check the master port's request queue + if (masterPort->checkFunctional(pkt)) { + return; + } + pkt->popLabel(); // fall through if pkt still not satisfied - otherPort->sendFunctional(pkt); + masterPort->sendFunctional(pkt); } -/** Function called by the port when the bus is receiving a status change.*/ +bool +Bridge::BridgeMasterPort::checkFunctional(PacketPtr pkt) +{ + bool found = false; + std::list<PacketBuffer*>::iterator i = requestQueue.begin(); + + while(i != requestQueue.end() && !found) { + if (pkt->checkFunctional((*i)->pkt)) { + pkt->makeResponse(); + found = true; + } + ++i; + } + + return found; +} + +/** Function called by the port when the bridge is receiving a range change.*/ void -Bridge::BridgePort::recvStatusChange(Port::Status status) +Bridge::BridgeMasterPort::recvRangeChange() { - otherPort->sendStatusChange(status); + // no need to forward as the bridge has a fixed set of ranges } void -Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) +Bridge::BridgeSlavePort::recvRangeChange() +{ + // is a slave port so do nothing +} + +AddrRangeList +Bridge::BridgeSlavePort::getAddrRanges() { - otherPort->getPeerAddressRanges(resp, snoop); - FilterRangeList(filterRanges, resp); - // we don't allow snooping across bridges - snoop = false; + return ranges; } Bridge * diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh index 732717dd4..d389c0a5e 100644 --- a/src/mem/bridge.hh +++ b/src/mem/bridge.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * @@ -27,11 +39,13 @@ * * Authors: Ali Saidi * Steve Reinhardt + * Andreas Hansson */ /** * @file - * Declaration of a simple bus bridge object with no buffering + * Declaration of a memory-mapped bus bridge that connects a master + * and a slave through a request and response queue. */ #ifndef __MEM_BRIDGE_HH__ @@ -49,90 +63,232 @@ #include "params/Bridge.hh" #include "sim/eventq.hh" +/** + * A bridge is used to interface two different busses (or in general a + * memory-mapped master and slave), with buffering for requests and + * responses. The bridge has a fixed delay for packets passing through + * it and responds to a fixed set of address ranges. + * + * The bridge comprises a slave port and a master port, that buffer + * outgoing responses and requests respectively. Buffer space is + * reserved when a request arrives, also reserving response space + * before forwarding the request. An incoming request is always + * accepted (recvTiming returns true), but is potentially NACKed if + * there is no request space or response space. + */ class Bridge : public MemObject { protected: - /** Declaration of the buses port type, one will be instantiated for each - of the interfaces connecting to the bus. */ - class BridgePort : public Port + + /** + * A packet buffer stores packets along with their sender state + * and scheduled time for transmission. + */ + class PacketBuffer : public Packet::SenderState, public FastAlloc { + + public: + Tick ready; + PacketPtr pkt; + bool nackedHere; + Packet::SenderState *origSenderState; + short origSrc; + bool expectResponse; + + PacketBuffer(PacketPtr _pkt, Tick t, bool nack = false) + : ready(t), pkt(_pkt), nackedHere(nack), + origSenderState(_pkt->senderState), + origSrc(nack ? _pkt->getDest() : _pkt->getSrc() ), + expectResponse(_pkt->needsResponse() && !nack) + + { + if (!pkt->isResponse() && !nack) + pkt->senderState = this; + } + + void fixResponse(PacketPtr pkt) + { + assert(pkt->senderState == this); + pkt->setDest(origSrc); + pkt->senderState = origSenderState; + } + }; + + // Forward declaration to allow the slave port to have a pointer + class BridgeMasterPort; + + /** + * The port on the side that receives requests and sends + * responses. The slave port has a set of address ranges that it + * is responsible for. The slave port also has a buffer for the + * responses not yet sent. + */ + class BridgeSlavePort : public Port { + + private: + /** A pointer to the bridge to which this port belongs. */ Bridge *bridge; /** - * Pointer to the port on the other side of the bridge + * Pointer to the master port on the other side of the bridge * (connected to the other bus). */ - BridgePort *otherPort; + BridgeMasterPort* masterPort; - /** Minimum delay though this bridge. */ + /** Minimum request delay though this bridge. */ Tick delay; - /** Min delay to respond to a nack. */ + /** Min delay to respond with a nack. */ Tick nackDelay; - /** Pass ranges from one side of the bridge to the other? */ - std::vector<Range<Addr> > filterRanges; + /** Address ranges to pass through the bridge */ + AddrRangeList ranges; + + /** + * Response packet queue. Response packets are held in this + * queue for a specified delay to model the processing delay + * of the bridge. + */ + std::list<PacketBuffer*> responseQueue; - class PacketBuffer : public Packet::SenderState, public FastAlloc { + /** Counter to track the outstanding responses. */ + unsigned int outstandingResponses; + + /** If we're waiting for a retry to happen. */ + bool inRetry; + + /** Max queue size for reserved responses. */ + unsigned int respQueueLimit; + + /** + * Is this side blocked from accepting new response packets. + * + * @return true if the reserved space has reached the set limit + */ + bool respQueueFull(); + + /** + * Turn the request packet into a NACK response and put it in + * the response queue and schedule its transmission. + * + * @param pkt the request packet to NACK + */ + void nackRequest(PacketPtr pkt); + + /** + * Handle send event, scheduled when the packet at the head of + * the response queue is ready to transmit (for timing + * accesses only). + */ + void trySend(); + + /** + * Private class for scheduling sending of responses from the + * response queue. + */ + class SendEvent : public Event + { + BridgeSlavePort *port; public: - Tick ready; - PacketPtr pkt; - bool nackedHere; - Packet::SenderState *origSenderState; - short origSrc; - bool expectResponse; - - PacketBuffer(PacketPtr _pkt, Tick t, bool nack = false) - : ready(t), pkt(_pkt), nackedHere(nack), - origSenderState(_pkt->senderState), - origSrc(nack ? _pkt->getDest() : _pkt->getSrc() ), - expectResponse(_pkt->needsResponse() && !nack) - - { - if (!pkt->isResponse() && !nack) - pkt->senderState = this; - } - - void fixResponse(PacketPtr pkt) - { - assert(pkt->senderState == this); - pkt->setDest(origSrc); - pkt->senderState = origSenderState; - } + SendEvent(BridgeSlavePort *p) : port(p) {} + virtual void process() { port->trySend(); } + virtual const char *description() const { return "bridge send"; } }; + /** Send event for the response queue. */ + SendEvent sendEvent; + + public: + /** - * Outbound packet queue. Packets are held in this queue for a - * specified delay to model the processing delay of the - * bridge. + * Constructor for the BridgeSlavePort. + * + * @param _name the port name including the owner + * @param _bridge the structural owner + * @param _masterPort the master port on the other side of the bridge + * @param _delay the delay from seeing a response to sending it + * @param _nack_delay the delay from a NACK to sending the response + * @param _resp_limit the size of the response queue + * @param _ranges a number of address ranges to forward */ - std::list<PacketBuffer*> sendQueue; + BridgeSlavePort(const std::string &_name, Bridge *_bridge, + BridgeMasterPort* _masterPort, int _delay, + int _nack_delay, int _resp_limit, + std::vector<Range<Addr> > _ranges); - int outstandingResponses; - int queuedRequests; + /** + * Queue a response packet to be sent out later and also schedule + * a send if necessary. + * + * @param pkt a response to send out after a delay + */ + void queueForSendTiming(PacketPtr pkt); - /** If we're waiting for a retry to happen.*/ - bool inRetry; + protected: - /** Max queue size for outbound packets */ - int reqQueueLimit; + /** When receiving a timing request from the peer port, + pass it to the bridge. */ + virtual bool recvTiming(PacketPtr pkt); - /** Max queue size for reserved responses. */ - int respQueueLimit; + /** When receiving a retry request from the peer port, + pass it to the bridge. */ + virtual void recvRetry(); + + /** When receiving a Atomic requestfrom the peer port, + pass it to the bridge. */ + virtual Tick recvAtomic(PacketPtr pkt); + + /** When receiving a Functional request from the peer port, + pass it to the bridge. */ + virtual void recvFunctional(PacketPtr pkt); /** - * Is this side blocked from accepting outbound packets? + * When receiving a range change on the slave side do nothing. */ - bool respQueueFull(); - bool reqQueueFull(); + virtual void recvRangeChange(); - void queueForSendTiming(PacketPtr pkt); + /** When receiving a address range request the peer port, + pass it to the bridge. */ + virtual AddrRangeList getAddrRanges(); + }; - void finishSend(PacketBuffer *buf); - void nackRequest(PacketPtr pkt); + /** + * Port on the side that forwards requests and receives + * responses. The master port has a buffer for the requests not + * yet sent. + */ + class BridgeMasterPort : public Port + { + + private: + + /** A pointer to the bridge to which this port belongs. */ + Bridge* bridge; + + /** + * Pointer to the slave port on the other side of the bridge + * (connected to the other bus). + */ + BridgeSlavePort* slavePort; + + /** Minimum delay though this bridge. */ + Tick delay; + + /** + * Request packet queue. Request packets are held in this + * queue for a specified delay to model the processing delay + * of the bridge. + */ + std::list<PacketBuffer*> requestQueue; + + /** If we're waiting for a retry to happen. */ + bool inRetry; + + /** Max queue size for request packets */ + unsigned int reqQueueLimit; /** * Handle send event, scheduled when the packet at the head of @@ -141,24 +297,62 @@ class Bridge : public MemObject */ void trySend(); + /** + * Private class for scheduling sending of requests from the + * request queue. + */ class SendEvent : public Event { - BridgePort *port; + BridgeMasterPort *port; public: - SendEvent(BridgePort *p) : port(p) {} + SendEvent(BridgeMasterPort *p) : port(p) {} virtual void process() { port->trySend(); } virtual const char *description() const { return "bridge send"; } }; + /** Send event for the request queue. */ SendEvent sendEvent; public: - /** Constructor for the BusPort.*/ - BridgePort(const std::string &_name, Bridge *_bridge, - BridgePort *_otherPort, int _delay, int _nack_delay, - int _req_limit, int _resp_limit, - std::vector<Range<Addr> > filter_ranges); + + /** + * Constructor for the BridgeMasterPort. + * + * @param _name the port name including the owner + * @param _bridge the structural owner + * @param _slavePort the slave port on the other side of the bridge + * @param _delay the delay from seeing a request to sending it + * @param _req_limit the size of the request queue + */ + BridgeMasterPort(const std::string &_name, Bridge *_bridge, + BridgeSlavePort* _slavePort, int _delay, + int _req_limit); + + /** + * Is this side blocked from accepting new request packets. + * + * @return true if the occupied space has reached the set limit + */ + bool reqQueueFull(); + + /** + * Queue a request packet to be sent out later and also schedule + * a send if necessary. + * + * @param pkt a request to send out after a delay + */ + void queueForSendTiming(PacketPtr pkt); + + /** + * Check a functional request against the packets in our + * request queue. + * + * @param pkt packet to check against + * + * @return true if we find a match + */ + bool checkFunctional(PacketPtr pkt); protected: @@ -178,17 +372,17 @@ class Bridge : public MemObject pass it to the bridge. */ virtual void recvFunctional(PacketPtr pkt); - /** When receiving a status changefrom the peer port, - pass it to the bridge. */ - virtual void recvStatusChange(Status status); - - /** When receiving a address range request the peer port, - pass it to the bridge. */ - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop); + /** + * When receiving a range change, pass it through the bridge. + */ + virtual void recvRangeChange(); }; - BridgePort portA, portB; + /** Slave port of the bridge. */ + BridgeSlavePort slavePort; + + /** Master port of the bridge. */ + BridgeMasterPort masterPort; /** If this bridge should acknowledge writes. */ bool ackWrites; diff --git a/src/mem/bus.cc b/src/mem/bus.cc index db71b86b7..a20f90108 100644 --- a/src/mem/bus.cc +++ b/src/mem/bus.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * @@ -26,6 +38,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Ali Saidi + * Andreas Hansson */ /** @@ -33,9 +46,6 @@ * Definition of a bus object. */ -#include <algorithm> -#include <limits> - #include "base/misc.hh" #include "base/trace.hh" #include "debug/Bus.hh" @@ -46,8 +56,7 @@ Bus::Bus(const BusParams *p) : MemObject(p), busId(p->bus_id), clock(p->clock), headerCycles(p->header_cycles), width(p->width), tickNextIdle(0), - drainEvent(NULL), busIdle(this), inRetry(false), maxId(0), - defaultPort(NULL), funcPort(NULL), funcPortId(-4), + drainEvent(NULL), busIdle(this), inRetry(false), defaultPortId(-1), useDefaultRange(p->use_default_range), defaultBlockSize(p->block_size), cachedBlockSize(0), cachedBlockSizeValid(false) { @@ -58,65 +67,44 @@ Bus::Bus(const BusParams *p) fatal("Bus clock period must be positive\n"); if (headerCycles <= 0) fatal("Number of header cycles must be positive\n"); - clearBusCache(); clearPortCache(); } Port * Bus::getPort(const std::string &if_name, int idx) { + std::string portName; + int id = interfaces.size(); if (if_name == "default") { - if (defaultPort == NULL) { - defaultPort = new BusPort(csprintf("%s-default",name()), this, - defaultId); - cachedBlockSizeValid = false; - return defaultPort; + if (defaultPortId == -1) { + defaultPortId = id; + portName = csprintf("%s-default", name()); } else - fatal("Default port already set\n"); - } - int id; - if (if_name == "functional") { - if (!funcPort) { - id = maxId++; - funcPort = new BusPort(csprintf("%s-p%d-func", name(), id), this, id); - funcPortId = id; - interfaces[id] = funcPort; - } - return funcPort; + fatal("Default port already set on %s\n", name()); + } else { + portName = csprintf("%s-p%d", name(), id); } - - // if_name ignored? forced to be empty? - id = maxId++; - assert(maxId < std::numeric_limits<typeof(maxId)>::max()); - BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id); - interfaces[id] = bp; + BusPort *bp = new BusPort(portName, this, id); + interfaces.push_back(bp); cachedBlockSizeValid = false; return bp; } void -Bus::deletePortRefs(Port *p) -{ - - BusPort *bp = dynamic_cast<BusPort*>(p); - if (bp == NULL) - panic("Couldn't convert Port* to BusPort*\n"); - // If this is our one functional port - if (funcPort == bp) - return; - interfaces.erase(bp->getId()); - clearBusCache(); - delete bp; -} - -/** Get the ranges of anyone other buses that we are connected to. */ -void Bus::init() { - m5::hash_map<short,BusPort*>::iterator intIter; - - for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) - intIter->second->sendStatusChange(Port::RangeChange); + std::vector<BusPort*>::iterator intIter; + + // iterate over our interfaces and determine which of our neighbours + // are snooping and add them as snoopers + for (intIter = interfaces.begin(); intIter != interfaces.end(); + intIter++) { + if ((*intIter)->getPeer()->isSnooping()) { + DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n", + (*intIter)->getPeer()->name()); + snoopPorts.push_back(*intIter); + } + } } Bus::BusFreeEvent::BusFreeEvent(Bus *_bus) @@ -194,16 +182,7 @@ Bus::recvTiming(PacketPtr pkt) { short src = pkt->getSrc(); - BusPort *src_port; - if (src == defaultId) - src_port = defaultPort; - else { - src_port = checkBusCache(src); - if (src_port == NULL) { - src_port = interfaces[src]; - updateBusCache(src, src_port); - } - } + BusPort *src_port = interfaces[src]; // If the bus is busy, or other devices are in line ahead of the current // one, put this device on the retry list. @@ -229,8 +208,7 @@ Bus::recvTiming(PacketPtr pkt) if (dest == Packet::Broadcast) { dest_port_id = findPort(pkt->getAddr()); - dest_port = (dest_port_id == defaultId) ? - defaultPort : interfaces[dest_port_id]; + dest_port = interfaces[dest_port_id]; SnoopIter s_end = snoopPorts.end(); for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { BusPort *p = *s_iter; @@ -241,20 +219,10 @@ Bus::recvTiming(PacketPtr pkt) } } } else { - assert(dest < maxId); + assert(dest < interfaces.size()); assert(dest != src); // catch infinite loops dest_port_id = dest; - if (dest_port_id == defaultId) - dest_port = defaultPort; - else { - dest_port = checkBusCache(dest); - if (dest_port == NULL) { - dest_port = interfaces[dest_port_id]; - // updateBusCache(dest_port_id, dest_port); - } - } - dest_port = (dest_port_id == defaultId) ? - defaultPort : interfaces[dest_port_id]; + dest_port = interfaces[dest_port_id]; } if (dest_port_id == src) { @@ -352,7 +320,7 @@ Bus::findPort(Addr addr) for (AddrRangeIter i = defaultRange.begin(); i != a_end; i++) { if (*i == addr) { DPRINTF(Bus, " found addr %#llx on default\n", addr); - return defaultId; + return defaultPortId; } } @@ -361,7 +329,7 @@ Bus::findPort(Addr addr) DPRINTF(Bus, "Unable to find destination for addr %#llx, " "will use default port\n", addr); - return defaultId; + return defaultPortId; } @@ -385,16 +353,7 @@ Bus::recvAtomic(PacketPtr pkt) int orig_src = pkt->getSrc(); int target_port_id = findPort(pkt->getAddr()); - BusPort *target_port; - if (target_port_id == defaultId) - target_port = defaultPort; - else { - target_port = checkBusCache(target_port_id); - if (target_port == NULL) { - target_port = interfaces[target_port_id]; - updateBusCache(target_port_id, target_port); - } - } + BusPort *target_port = interfaces[target_port_id]; SnoopIter s_end = snoopPorts.end(); for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) { @@ -450,7 +409,7 @@ Bus::recvFunctional(PacketPtr pkt) assert(pkt->getDest() == Packet::Broadcast); int port_id = findPort(pkt->getAddr()); - Port *port = (port_id == defaultId) ? defaultPort : interfaces[port_id]; + Port *port = interfaces[port_id]; // The packet may be changed by another bus on snoops, restore the // id after each int src_id = pkt->getSrc(); @@ -483,30 +442,25 @@ Bus::recvFunctional(PacketPtr pkt) } } -/** Function called by the port when the bus is receiving a status change.*/ +/** Function called by the port when the bus is receiving a range change.*/ void -Bus::recvStatusChange(Port::Status status, int id) +Bus::recvRangeChange(int id) { AddrRangeList ranges; - bool snoops; AddrRangeIter iter; - if (inRecvStatusChange.count(id)) + if (inRecvRangeChange.count(id)) return; - inRecvStatusChange.insert(id); - - assert(status == Port::RangeChange && - "The other statuses need to be implemented."); + inRecvRangeChange.insert(id); DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id); clearPortCache(); - if (id == defaultId) { + if (id == defaultPortId) { defaultRange.clear(); // Only try to update these ranges if the user set a default responder. if (useDefaultRange) { - defaultPort->getPeerAddressRanges(ranges, snoops); - assert(snoops == false); + AddrRangeList ranges = interfaces[id]->getPeer()->getAddrRanges(); for(iter = ranges.begin(); iter != ranges.end(); iter++) { defaultRange.push_back(*iter); DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n", @@ -515,7 +469,7 @@ Bus::recvStatusChange(Port::Status status, int id) } } else { - assert((id < maxId && id >= 0) || id == defaultId); + assert(id < interfaces.size() && id >= 0); BusPort *port = interfaces[id]; // Clean out any previously existent ids @@ -527,20 +481,7 @@ Bus::recvStatusChange(Port::Status status, int id) portIter++; } - for (SnoopIter s_iter = snoopPorts.begin(); - s_iter != snoopPorts.end(); ) { - if ((*s_iter)->getId() == id) - s_iter = snoopPorts.erase(s_iter); - else - s_iter++; - } - - port->getPeerAddressRanges(ranges, snoops); - - if (snoops) { - DPRINTF(BusAddrRanges, "Adding id %d to snoop list\n", id); - snoopPorts.push_back(port); - } + ranges = port->getPeer()->getAddrRanges(); for (iter = ranges.begin(); iter != ranges.end(); iter++) { DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n", @@ -557,28 +498,25 @@ Bus::recvStatusChange(Port::Status status, int id) // tell all our peers that our address range has changed. // Don't tell the device that caused this change, it already knows - m5::hash_map<short,BusPort*>::iterator intIter; + std::vector<BusPort*>::const_iterator intIter; for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++) - if (intIter->first != id && intIter->first != funcPortId) - intIter->second->sendStatusChange(Port::RangeChange); + if ((*intIter)->getId() != id) + (*intIter)->sendRangeChange(); - if (id != defaultId && defaultPort) - defaultPort->sendStatusChange(Port::RangeChange); - inRecvStatusChange.erase(id); + inRecvRangeChange.erase(id); } -void -Bus::addressRanges(AddrRangeList &resp, bool &snoop, int id) +AddrRangeList +Bus::getAddrRanges(int id) { - resp.clear(); - snoop = false; + AddrRangeList ranges; DPRINTF(BusAddrRanges, "received address range request, returning:\n"); for (AddrRangeIter dflt_iter = defaultRange.begin(); dflt_iter != defaultRange.end(); dflt_iter++) { - resp.push_back(*dflt_iter); + ranges.push_back(*dflt_iter); DPRINTF(BusAddrRanges, " -- Dflt: %#llx : %#llx\n",dflt_iter->start, dflt_iter->end); } @@ -601,12 +539,21 @@ Bus::addressRanges(AddrRangeList &resp, bool &snoop, int id) } } if (portIter->second != id && !subset) { - resp.push_back(portIter->first); + ranges.push_back(portIter->first); DPRINTF(BusAddrRanges, " -- %#llx : %#llx\n", portIter->first.start, portIter->first.end); } } + return ranges; +} + +bool +Bus::isSnooping(int id) +{ + // in essence, answer the question if there are other snooping + // ports rather than the port that is asking + bool snoop = false; for (SnoopIter s_iter = snoopPorts.begin(); s_iter != snoopPorts.end(); s_iter++) { if ((*s_iter)->getId() != id) { @@ -614,6 +561,7 @@ Bus::addressRanges(AddrRangeList &resp, bool &snoop, int id) break; } } + return snoop; } unsigned diff --git a/src/mem/bus.hh b/src/mem/bus.hh index 17d22ec83..5b8b373a5 100644 --- a/src/mem/bus.hh +++ b/src/mem/bus.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -27,6 +39,7 @@ * * Authors: Ron Dreslinski * Ali Saidi + * Andreas Hansson */ /** @@ -79,7 +92,16 @@ class Bus : public MemObject void onRetryList(bool newVal) { _onRetryList = newVal; } - int getId() { return id; } + int getId() const { return id; } + + /** + * Determine if this port should be considered a snooper. This + * is determined by the bus. + * + * @return a boolean that is true if this port is snooping + */ + virtual bool isSnooping() + { return bus->isSnooping(id); } protected: @@ -98,10 +120,10 @@ class Bus : public MemObject virtual void recvFunctional(PacketPtr pkt) { pkt->setSrc(id); bus->recvFunctional(pkt); } - /** When reciving a status changefrom the peer port (at id), + /** When reciving a range change from the peer port (at id), pass it to the bus. */ - virtual void recvStatusChange(Status status) - { bus->recvStatusChange(status, id); } + virtual void recvRangeChange() + { bus->recvRangeChange(id); } /** When reciving a retry from the peer port (at id), pass it to the bus. */ @@ -112,9 +134,8 @@ class Bus : public MemObject // downstream from this bus, yes? That is, the union of all // the 'owned' address ranges of all the other interfaces on // this bus... - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { bus->addressRanges(resp, snoop, id); } + virtual AddrRangeList getAddrRanges() + { return bus->getAddrRanges(id); } // Ask the bus to ask everyone on the bus what their block size is and // take the max of it. This might need to be changed a bit if we ever @@ -147,9 +168,6 @@ class Bus : public MemObject Event * drainEvent; - - static const int defaultId = -3; //Make it unique from Broadcast - typedef range_map<Addr,int>::iterator PortIter; range_map<Addr, int> portMap; @@ -174,8 +192,8 @@ class Bus : public MemObject * requests. */ void recvRetry(int id); - /** Function called by the port when the bus is recieving a status change.*/ - void recvStatusChange(Port::Status status, int id); + /** Function called by the port when the bus is recieving a range change.*/ + void recvRangeChange(int id); /** Find which port connected to this bus (if any) should be given a packet * with this address. @@ -238,12 +256,23 @@ class Bus : public MemObject portCache[0].valid = false; } - /** Process address range request. - * @param resp addresses that we can respond to - * @param snoop addresses that we would like to snoop - * @param id ide of the busport that made the request. + /** + * Return the address ranges this port is responsible for. + * + * @param id id of the bus port that made the request + * + * @return a list of non-overlapping address ranges + */ + AddrRangeList getAddrRanges(int id); + + /** + * Determine if the bus port is snooping or not. + * + * @param id id of the bus port that made the request + * + * @return a boolean indicating if this port is snooping or not */ - void addressRanges(AddrRangeList &resp, bool &snoop, int id); + bool isSnooping(int id); /** Calculate the timing parameters for the packet. Updates the * firstWordTime and finishTime fields of the packet object. @@ -264,14 +293,11 @@ class Bus : public MemObject BusFreeEvent busIdle; bool inRetry; - std::set<int> inRecvStatusChange; + std::set<int> inRecvRangeChange; - /** max number of bus ids we've handed out so far */ - short maxId; - - /** An array of pointers to the peer port interfaces + /** An ordered vector of pointers to the peer port interfaces connected to this bus.*/ - m5::hash_map<short,BusPort*> interfaces; + std::vector<BusPort*> interfaces; /** An array of pointers to ports that retry should be called on because the * original send failed for whatever reason.*/ @@ -300,10 +326,7 @@ class Bus : public MemObject } /** Port that handles requests that don't match any of the interfaces.*/ - BusPort *defaultPort; - - BusPort *funcPort; - int funcPortId; + short defaultPortId; /** If true, use address range provided by default device. Any address not handled by another port and not in default device's @@ -315,59 +338,10 @@ class Bus : public MemObject unsigned cachedBlockSize; bool cachedBlockSizeValid; - // Cache for the peer port interfaces - struct BusCache { - bool valid; - short id; - BusPort *port; - }; - - BusCache busCache[3]; - - // Checks the peer port interfaces cache for the port id and returns - // a pointer to the matching port - inline BusPort* checkBusCache(short id) { - if (busCache[0].valid && id == busCache[0].id) { - return busCache[0].port; - } - if (busCache[1].valid && id == busCache[1].id) { - return busCache[1].port; - } - if (busCache[2].valid && id == busCache[2].id) { - return busCache[2].port; - } - - return NULL; - } - - // Replaces the earliest entry in the cache with a new entry - inline void updateBusCache(short id, BusPort *port) { - busCache[2].valid = busCache[1].valid; - busCache[2].id = busCache[1].id; - busCache[2].port = busCache[1].port; - - busCache[1].valid = busCache[0].valid; - busCache[1].id = busCache[0].id; - busCache[1].port = busCache[0].port; - - busCache[0].valid = true; - busCache[0].id = id; - busCache[0].port = port; - } - - // Invalidates the cache. Needs to be called in constructor. - inline void clearBusCache() { - busCache[2].valid = false; - busCache[1].valid = false; - busCache[0].valid = false; - } - - public: /** A function used to return the port associated with this bus object. */ virtual Port *getPort(const std::string &if_name, int idx = -1); - virtual void deletePortRefs(Port *p); virtual void init(); virtual void startup(); diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc index 09e3d0869..2b7fa4b9f 100644 --- a/src/mem/cache/base.cc +++ b/src/mem/cache/base.cc @@ -71,11 +71,9 @@ BaseCache::BaseCache(const Params *p) } void -BaseCache::CachePort::recvStatusChange(Port::Status status) +BaseCache::CachePort::recvRangeChange() const { - if (status == Port::RangeChange) { - otherPort->sendStatusChange(Port::RangeChange); - } + otherPort->sendRangeChange(); } @@ -127,7 +125,7 @@ BaseCache::CachePort::clearBlocked() mustSendRetry = false; SendRetryEvent *ev = new SendRetryEvent(this, true); // @TODO: need to find a better time (next bus cycle?) - schedule(ev, curTick() + 1); + cache->schedule(ev, curTick() + 1); } } @@ -137,7 +135,7 @@ BaseCache::init() { if (!cpuSidePort || !memSidePort) panic("Cache not hooked up on both sides\n"); - cpuSidePort->sendStatusChange(Port::RangeChange); + cpuSidePort->sendRangeChange(); } diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh index 8c39a2400..fded6fca6 100644 --- a/src/mem/cache/base.hh +++ b/src/mem/cache/base.hh @@ -105,7 +105,7 @@ class BaseCache : public MemObject CachePort(const std::string &_name, BaseCache *_cache, const std::string &_label); - virtual void recvStatusChange(Status status); + virtual void recvRangeChange() const; virtual unsigned deviceBlockSize() const; diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh index 1ed138bb5..b5c95b301 100644 --- a/src/mem/cache/cache.hh +++ b/src/mem/cache/cache.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2012 ARM Limited + * All rights reserved. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -78,8 +90,7 @@ class Cache : public BaseCache return static_cast<Cache<TagStore> *>(cache); } - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop); + virtual AddrRangeList getAddrRanges(); virtual bool recvTiming(PacketPtr pkt); @@ -106,8 +117,7 @@ class Cache : public BaseCache void processSendEvent(); - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop); + virtual bool isSnooping(); virtual bool recvTiming(PacketPtr pkt); @@ -204,7 +214,6 @@ class Cache : public BaseCache Cache(const Params *p, TagStore *tags, BasePrefetcher *prefetcher); virtual Port *getPort(const std::string &if_name, int idx = -1); - virtual void deletePortRefs(Port *p); void regStats(); @@ -225,10 +234,9 @@ class Cache : public BaseCache /** * Performs the access specified by the request. * @param pkt The request to perform. - * @return The result of the access. + * @param fromCpuSide from the CPU side port or the memory side port */ - void functionalAccess(PacketPtr pkt, CachePort *incomingPort, - CachePort *otherSidePort); + void functionalAccess(PacketPtr pkt, bool fromCpuSide); /** * Handles a response (cache line fill/write ack) from the bus. diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh index a56495abb..13484eb79 100644 --- a/src/mem/cache/cache_impl.hh +++ b/src/mem/cache/cache_impl.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 ARM Limited + * Copyright (c) 2010-2012 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -103,30 +103,13 @@ Cache<TagStore>::getPort(const std::string &if_name, int idx) return cpuSidePort; } else if (if_name == "mem_side") { return memSidePort; - } else if (if_name == "functional") { - CpuSidePort *funcPort = - new CpuSidePort(name() + "-cpu_side_funcport", this, - "CpuSideFuncPort"); - funcPort->setOtherPort(memSidePort); - return funcPort; - } else { + } else { panic("Port name %s unrecognized\n", if_name); } } template<class TagStore> void -Cache<TagStore>::deletePortRefs(Port *p) -{ - if (cpuSidePort == p || memSidePort == p) - panic("Can only delete functional ports\n"); - - delete p; -} - - -template<class TagStore> -void Cache<TagStore>::cmpAndSwap(BlkType *blk, PacketPtr pkt) { uint64_t overwrite_val; @@ -768,9 +751,7 @@ Cache<TagStore>::atomicAccess(PacketPtr pkt) template<class TagStore> void -Cache<TagStore>::functionalAccess(PacketPtr pkt, - CachePort *incomingPort, - CachePort *otherSidePort) +Cache<TagStore>::functionalAccess(PacketPtr pkt, bool fromCpuSide) { Addr blk_addr = blockAlign(pkt->getAddr()); BlkType *blk = tags->findBlock(pkt->getAddr()); @@ -796,10 +777,10 @@ Cache<TagStore>::functionalAccess(PacketPtr pkt, (mshr && mshr->inService && mshr->isPendingDirty())); bool done = have_dirty - || incomingPort->checkFunctional(pkt) + || cpuSidePort->checkFunctional(pkt) || mshrQueue.checkFunctional(pkt, blk_addr) || writeBuffer.checkFunctional(pkt, blk_addr) - || otherSidePort->checkFunctional(pkt); + || memSidePort->checkFunctional(pkt); DPRINTF(Cache, "functional %s %x %s%s%s\n", pkt->cmdString(), pkt->getAddr(), @@ -812,7 +793,15 @@ Cache<TagStore>::functionalAccess(PacketPtr pkt, if (done) { pkt->makeResponse(); } else { - otherSidePort->sendFunctional(pkt); + // if it came as a request from the CPU side then make sure it + // continues towards the memory side + if (fromCpuSide) { + memSidePort->sendFunctional(pkt); + } else if (forwardSnoops) { + // if it came from the memory side, it must be a snoop request + // and we should only forward it if we are forwarding snoops + cpuSidePort->sendFunctional(pkt); + } } } @@ -1559,14 +1548,15 @@ Cache<TagStore>::nextMSHRReadyTime() /////////////// template<class TagStore> -void +AddrRangeList Cache<TagStore>::CpuSidePort:: -getDeviceAddressRanges(AddrRangeList &resp, bool &snoop) +getAddrRanges() { // CPU side port doesn't snoop; it's a target only. It can // potentially respond to any address. - snoop = false; - resp.push_back(myCache()->getAddrRange()); + AddrRangeList ranges; + ranges.push_back(myCache()->getAddrRange()); + return ranges; } @@ -1598,7 +1588,7 @@ template<class TagStore> void Cache<TagStore>::CpuSidePort::recvFunctional(PacketPtr pkt) { - myCache()->functionalAccess(pkt, this, otherPort); + myCache()->functionalAccess(pkt, true); } @@ -1617,14 +1607,13 @@ CpuSidePort::CpuSidePort(const std::string &_name, Cache<TagStore> *_cache, /////////////// template<class TagStore> -void -Cache<TagStore>::MemSidePort:: -getDeviceAddressRanges(AddrRangeList &resp, bool &snoop) +bool +Cache<TagStore>::MemSidePort::isSnooping() { // Memory-side port always snoops, but never passes requests // through to targets on the cpu side (so we don't add anything to // the address range list). - snoop = true; + return true; } @@ -1670,7 +1659,7 @@ template<class TagStore> void Cache<TagStore>::MemSidePort::recvFunctional(PacketPtr pkt) { - myCache()->functionalAccess(pkt, this, otherPort); + myCache()->functionalAccess(pkt, false); } @@ -1723,7 +1712,7 @@ Cache<TagStore>::MemSidePort::sendPacket() // @TODO: need to facotr in prefetch requests here somehow if (nextReady != MaxTick) { DPRINTF(CachePort, "more packets to send @ %d\n", nextReady); - schedule(sendEvent, std::max(nextReady, curTick() + 1)); + cache->schedule(sendEvent, std::max(nextReady, curTick() + 1)); } else { // no more to send right now: if we're draining, we may be done if (drainEvent && !sendEvent->scheduled()) { diff --git a/src/mem/vport.cc b/src/mem/fs_translating_port_proxy.cc index ab061c019..c0898a003 100644 --- a/src/mem/vport.cc +++ b/src/mem/fs_translating_port_proxy.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * @@ -26,6 +38,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Ali Saidi + * Andreas Hansson */ /** @@ -34,49 +47,81 @@ */ #include "base/chunk_generator.hh" -#include "config/the_isa.hh" +#include "cpu/base.hh" #include "cpu/thread_context.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" + +using namespace TheISA; + +FSTranslatingPortProxy::FSTranslatingPortProxy(ThreadContext *tc) + : PortProxy(*(tc->getCpuPtr()->getPort("dcache_port"))), _tc(tc) +{ +} + +FSTranslatingPortProxy::FSTranslatingPortProxy(Port &port) + : PortProxy(port), _tc(NULL) +{ +} + +FSTranslatingPortProxy::~FSTranslatingPortProxy() +{ +} void -VirtualPort::readBlob(Addr addr, uint8_t *p, int size) +FSTranslatingPortProxy::readBlob(Addr addr, uint8_t *p, int size) { Addr paddr; for (ChunkGenerator gen(addr, size, TheISA::PageBytes); !gen.done(); - gen.next()) + gen.next()) { - if (tc) - paddr = TheISA::vtophys(tc,gen.addr()); + if (_tc) + paddr = TheISA::vtophys(_tc,gen.addr()); else paddr = TheISA::vtophys(gen.addr()); - FunctionalPort::readBlob(paddr, p, gen.size()); + PortProxy::readBlob(paddr, p, gen.size()); p += gen.size(); } } void -VirtualPort::writeBlob(Addr addr, uint8_t *p, int size) +FSTranslatingPortProxy::writeBlob(Addr addr, uint8_t *p, int size) { Addr paddr; for (ChunkGenerator gen(addr, size, TheISA::PageBytes); !gen.done(); - gen.next()) + gen.next()) { - if (tc) - paddr = TheISA::vtophys(tc,gen.addr()); + if (_tc) + paddr = TheISA::vtophys(_tc,gen.addr()); else paddr = TheISA::vtophys(gen.addr()); - FunctionalPort::writeBlob(paddr, p, gen.size()); + PortProxy::writeBlob(paddr, p, gen.size()); p += gen.size(); } } void +FSTranslatingPortProxy::memsetBlob(Addr address, uint8_t v, int size) +{ + Addr paddr; + for (ChunkGenerator gen(address, size, TheISA::PageBytes); !gen.done(); + gen.next()) + { + if (_tc) + paddr = TheISA::vtophys(_tc,gen.addr()); + else + paddr = TheISA::vtophys(gen.addr()); + + PortProxy::memsetBlob(paddr, v, gen.size()); + } +} + +void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen) { uint8_t *dst = (uint8_t *)dest; - VirtualPort *vp = tc->getVirtPort(); + FSTranslatingPortProxy* vp = tc->getVirtProxy(); vp->readBlob(src, dst, cplen); } @@ -85,7 +130,7 @@ void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) { uint8_t *src = (uint8_t *)source; - VirtualPort *vp = tc->getVirtPort(); + FSTranslatingPortProxy* vp = tc->getVirtProxy(); vp->writeBlob(dest, src, cplen); } @@ -93,21 +138,25 @@ CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen) void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen) { - int len = 0; char *start = dst; - VirtualPort *vp = tc->getVirtPort(); + FSTranslatingPortProxy* vp = tc->getVirtProxy(); - do { - vp->readBlob(vaddr++, (uint8_t*)dst++, 1); - } while (len < maxlen && start[len++] != 0 ); + bool foundNull = false; + while ((dst - start + 1) < maxlen && !foundNull) { + vp->readBlob(vaddr++, (uint8_t*)dst, 1); + if (dst == '\0') + foundNull = true; + dst++; + } - dst[len] = 0; + if (!foundNull) + *dst = '\0'; } void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr) { - VirtualPort *vp = tc->getVirtPort(); + FSTranslatingPortProxy* vp = tc->getVirtProxy(); for (ChunkGenerator gen(vaddr, strlen(src), TheISA::PageBytes); !gen.done(); gen.next()) { diff --git a/src/mem/vport.hh b/src/mem/fs_translating_port_proxy.hh index 7cf24587c..826def902 100644 --- a/src/mem/vport.hh +++ b/src/mem/fs_translating_port_proxy.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * @@ -26,44 +38,49 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Ali Saidi + * Andreas Hansson */ /** * @file - * Virtual Port Object Declaration. These ports incorporate some translation - * into their access methods. Thus you can use one to read and write data - * to/from virtual addresses. + * TranslatingPortProxy Object Declaration for FS. + * + * Port proxies are used when non structural entities need access to + * the memory system. Proxy objects replace the previous + * FunctionalPort, TranslatingPort and VirtualPort objects, which + * provided the same functionality as the proxies, but were instances + * of ports not corresponding to real structural ports of the + * simulated system. Via the port proxies all the accesses go through + * an actual port and thus are transparent to a potentially + * distributed memory and automatically adhere to the memory map of + * the system. */ -#ifndef __MEM_VPORT_HH__ -#define __MEM_VPORT_HH__ +#ifndef __MEM_FS_PORT_PROXY_HH__ +#define __MEM_FS_PORT_PROXY_HH__ #include "arch/vtophys.hh" -#include "mem/port_impl.hh" +#include "mem/port_proxy.hh" -/** A class that translates a virtual address to a physical address and then - * calls the above read/write functions. If a thread context is provided the - * address can alway be translated, If not it can only be translated if it is a - * simple address masking operation (such as alpha super page accesses). +/** + * A TranslatingPortProxy in FS mode translates a virtual address to a + * physical address and then calls the read/write functions of the + * port. If a thread context is provided the address can alway be + * translated, If not it can only be translated if it is a simple + * address masking operation (such as alpha super page accesses). */ - - -class VirtualPort : public FunctionalPort +class FSTranslatingPortProxy : public PortProxy { private: - ThreadContext *tc; + ThreadContext* _tc; public: - VirtualPort(const std::string &_name, ThreadContext *_tc = NULL) - : FunctionalPort(_name), tc(_tc) - {} - /** Return true if we have an thread context. This is used to - * prevent someone from accidently deleting the cpus statically - * allocated vport. - * @return true if a thread context isn't valid - */ - bool nullThreadContext() { return tc != NULL; } + FSTranslatingPortProxy(ThreadContext* tc); + + FSTranslatingPortProxy(Port &port); + + virtual ~FSTranslatingPortProxy(); /** Version of readblob that translates virt->phys and deals * with page boundries. */ @@ -72,13 +89,16 @@ class VirtualPort : public FunctionalPort /** Version of writeBlob that translates virt->phys and deals * with page boundries. */ virtual void writeBlob(Addr addr, uint8_t *p, int size); -}; + /** + * Fill size bytes starting at addr with byte value val. + */ + virtual void memsetBlob(Addr address, uint8_t v, int size); +}; void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen); void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen); void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen); void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr); -#endif //__MEM_VPORT_HH__ - +#endif //__MEM_FS_PORT_PROXY_HH__ diff --git a/src/mem/mem_object.cc b/src/mem/mem_object.cc index 20a1b4cd8..111d3718c 100644 --- a/src/mem/mem_object.cc +++ b/src/mem/mem_object.cc @@ -34,9 +34,3 @@ MemObject::MemObject(const Params *params) : SimObject(params) { } - -void -MemObject::deletePortRefs(Port *p) -{ - panic("This object does not support port deletion\n"); -} diff --git a/src/mem/mem_object.hh b/src/mem/mem_object.hh index b8bf4b939..5865fc935 100644 --- a/src/mem/mem_object.hh +++ b/src/mem/mem_object.hh @@ -56,10 +56,6 @@ class MemObject : public SimObject public: /** Additional function to return the Port of a memory object. */ virtual Port *getPort(const std::string &if_name, int idx = -1) = 0; - - /** Tell object that this port is about to disappear, so it should remove it - * from any structures that it's keeping it in. */ - virtual void deletePortRefs(Port *p) ; }; #endif //__MEM_MEM_OBJECT_HH__ diff --git a/src/mem/packet.cc b/src/mem/packet.cc index 64f4fcd14..4c3a785dc 100644 --- a/src/mem/packet.cc +++ b/src/mem/packet.cc @@ -168,6 +168,9 @@ MemCmd::commandInfo[] = { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" }, /* Flush Request */ { SET3(IsRequest, IsFlush, NeedsExclusive), InvalidCmd, "FlushReq" }, + /* Invalidation Request */ + { SET3(NeedsExclusive, IsInvalidate, IsRequest), + InvalidCmd, "InvalidationReq" }, }; bool diff --git a/src/mem/packet.hh b/src/mem/packet.hh index 6347c21ea..e49ce7577 100644 --- a/src/mem/packet.hh +++ b/src/mem/packet.hh @@ -108,6 +108,7 @@ class MemCmd // Fake simulator-only commands PrintReq, // Print state matching address FlushReq, //request for a cache flush + InvalidationReq, // request for address to be invalidated from lsq NUM_MEM_CMDS }; diff --git a/src/mem/physical.cc b/src/mem/physical.cc index d5c4e892f..09ed8b292 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 ARM Limited + * Copyright (c) 2010-2011 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -115,7 +115,7 @@ PhysicalMemory::init() for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { if (*pi) - (*pi)->sendStatusChange(Port::RangeChange); + (*pi)->sendRangeChange(); } } @@ -125,6 +125,65 @@ PhysicalMemory::~PhysicalMemory() munmap((char*)pmemAddr, size()); } +void +PhysicalMemory::regStats() +{ + using namespace Stats; + + bytesRead + .name(name() + ".bytes_read") + .desc("Number of bytes read from this memory") + ; + bytesInstRead + .name(name() + ".bytes_inst_read") + .desc("Number of instructions bytes read from this memory") + ; + bytesWritten + .name(name() + ".bytes_written") + .desc("Number of bytes written to this memory") + ; + numReads + .name(name() + ".num_reads") + .desc("Number of read requests responded to by this memory") + ; + numWrites + .name(name() + ".num_writes") + .desc("Number of write requests responded to by this memory") + ; + numOther + .name(name() + ".num_other") + .desc("Number of other requests responded to by this memory") + ; + bwRead + .name(name() + ".bw_read") + .desc("Total read bandwidth from this memory (bytes/s)") + .precision(0) + .prereq(bytesRead) + ; + bwInstRead + .name(name() + ".bw_inst_read") + .desc("Instruction read bandwidth from this memory (bytes/s)") + .precision(0) + .prereq(bytesInstRead) + ; + bwWrite + .name(name() + ".bw_write") + .desc("Write bandwidth from this memory (bytes/s)") + .precision(0) + .prereq(bytesWritten) + ; + bwTotal + .name(name() + ".bw_total") + .desc("Total bandwidth to/from this memory (bytes/s)") + .precision(0) + .prereq(bwTotal) + ; + bwRead = bytesRead / simSeconds; + bwInstRead = bytesInstRead / simSeconds; + bwWrite = bytesWritten / simSeconds; + bwTotal = (bytesRead + bytesWritten) / simSeconds; +} + unsigned PhysicalMemory::deviceBlockSize() const { @@ -303,6 +362,7 @@ PhysicalMemory::doAtomicAccess(PacketPtr pkt) assert(!pkt->req->isInstFetch()); TRACE_PACKET("Read/Write"); + numOther++; } else if (pkt->isRead()) { assert(!pkt->isWrite()); if (pkt->isLLSC()) { @@ -311,12 +371,18 @@ PhysicalMemory::doAtomicAccess(PacketPtr pkt) if (pmemAddr) memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read"); + numReads++; + bytesRead += pkt->getSize(); + if (pkt->req->isInstFetch()) + bytesInstRead += pkt->getSize(); } else if (pkt->isWrite()) { if (writeOK(pkt)) { if (pmemAddr) memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); assert(!pkt->req->isInstFetch()); TRACE_PACKET("Write"); + numWrites++; + bytesWritten += pkt->getSize(); } } else if (pkt->isInvalidate()) { //upgrade or invalidate @@ -371,13 +437,6 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt) Port * PhysicalMemory::getPort(const std::string &if_name, int idx) { - // Accept request for "functional" port for backwards compatibility - // with places where this function is called from C++. I'd prefer - // to move all these into Python someday. - if (if_name == "functional") { - return new MemoryPort(csprintf("%s-functional", name()), this); - } - if (if_name != "port") { panic("PhysicalMemory::getPort: unknown port %s requested", if_name); } @@ -397,36 +456,30 @@ PhysicalMemory::getPort(const std::string &if_name, int idx) return port; } - -void -PhysicalMemory::recvStatusChange(Port::Status status) -{ -} - PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, PhysicalMemory *_memory) : SimpleTimingPort(_name, _memory), memory(_memory) { } void -PhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) +PhysicalMemory::MemoryPort::recvRangeChange() { - memory->recvStatusChange(status); + // memory is a slave and thus should never have to worry about its + // neighbours address ranges } -void -PhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) +AddrRangeList +PhysicalMemory::MemoryPort::getAddrRanges() { - memory->getAddressRanges(resp, snoop); + return memory->getAddrRanges(); } -void -PhysicalMemory::getAddressRanges(AddrRangeList &resp, bool &snoop) +AddrRangeList +PhysicalMemory::getAddrRanges() { - snoop = false; - resp.clear(); - resp.push_back(RangeSize(start(), size())); + AddrRangeList ranges; + ranges.push_back(RangeSize(start(), size())); + return ranges; } unsigned diff --git a/src/mem/physical.hh b/src/mem/physical.hh index cd6d809e2..b447237c7 100644 --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -38,11 +38,13 @@ #include <string> #include "base/range.hh" +#include "base/statistics.hh" #include "mem/mem_object.hh" #include "mem/packet.hh" #include "mem/tport.hh" #include "params/PhysicalMemory.hh" #include "sim/eventq.hh" +#include "sim/stats.hh" // // Functional model for a contiguous block of physical memory. (i.e. RAM) @@ -65,10 +67,9 @@ class PhysicalMemory : public MemObject virtual void recvFunctional(PacketPtr pkt); - virtual void recvStatusChange(Status status); + virtual void recvRangeChange(); - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop); + virtual AddrRangeList getAddrRanges(); virtual unsigned deviceBlockSize() const; }; @@ -155,6 +156,28 @@ class PhysicalMemory : public MemObject uint64_t _size; uint64_t _start; + + /** Number of total bytes read from this memory */ + Stats::Scalar bytesRead; + /** Number of instruction bytes read from this memory */ + Stats::Scalar bytesInstRead; + /** Number of bytes written to this memory */ + Stats::Scalar bytesWritten; + /** Number of read requests */ + Stats::Scalar numReads; + /** Number of write requests */ + Stats::Scalar numWrites; + /** Number of other requests */ + Stats::Scalar numOther; + /** Read bandwidth from this memory */ + Stats::Formula bwRead; + /** Read bandwidth from this memory */ + Stats::Formula bwInstRead; + /** Write bandwidth from this memory */ + Stats::Formula bwWrite; + /** Total bandwidth from this memory */ + Stats::Formula bwTotal; + public: uint64_t size() { return _size; } uint64_t start() { return _start; } @@ -172,7 +195,7 @@ class PhysicalMemory : public MemObject public: unsigned deviceBlockSize() const; - void getAddressRanges(AddrRangeList &resp, bool &snoop); + AddrRangeList getAddrRanges(); virtual Port *getPort(const std::string &if_name, int idx = -1); void virtual init(); unsigned int drain(Event *de); @@ -181,9 +204,13 @@ class PhysicalMemory : public MemObject Tick doAtomicAccess(PacketPtr pkt); void doFunctionalAccess(PacketPtr pkt); virtual Tick calculateLatency(PacketPtr pkt); - void recvStatusChange(Port::Status status); public: + /** + * Register Statistics + */ + void regStats(); + virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); diff --git a/src/mem/port.cc b/src/mem/port.cc index c87785a49..fb1715db6 100644 --- a/src/mem/port.cc +++ b/src/mem/port.cc @@ -40,61 +40,8 @@ #include "mem/mem_object.hh" #include "mem/port.hh" -class DefaultPeerPort : public Port -{ - protected: - void blowUp() const - { - fatal("%s: Unconnected port!", peer->name()); - } - - public: - DefaultPeerPort() - : Port("default_port", NULL) - { } - - bool recvTiming(PacketPtr) - { - blowUp(); - return false; - } - - Tick recvAtomic(PacketPtr) - { - blowUp(); - return 0; - } - - void recvFunctional(PacketPtr) - { - blowUp(); - } - - void recvStatusChange(Status) - { - blowUp(); - } - - unsigned - deviceBlockSize() const - { - blowUp(); - return 0; - } - - void getDeviceAddressRanges(AddrRangeList &, bool &) - { - blowUp(); - } - - bool isDefaultPort() const { return true; } -}; - -DefaultPeerPort defaultPeerPort; - Port::Port(const std::string &_name, MemObject *_owner) - : EventManager(_owner), portName(_name), peer(&defaultPeerPort), - owner(_owner) + : portName(_name), peer(NULL), owner(_owner) { } @@ -113,19 +60,10 @@ Port::setPeer(Port *port) void Port::setOwner(MemObject *_owner) { - eventq = _owner->queue(); owner = _owner; } void -Port::removeConn() -{ - if (peer->getOwner()) - peer->getOwner()->deletePortRefs(peer); - peer = NULL; -} - -void Port::blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd) { Request req; diff --git a/src/mem/port.hh b/src/mem/port.hh index bb74bf497..98b3ad5f1 100644 --- a/src/mem/port.hh +++ b/src/mem/port.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -47,10 +59,8 @@ #include "base/types.hh" #include "mem/packet.hh" #include "mem/request.hh" -#include "sim/eventq.hh" -/** This typedef is used to clean up the parameter list of - * getDeviceAddressRanges() and getPeerAddressRanges(). It's declared +/** This typedef is used to clean up getAddrRanges(). It's declared * outside the Port object since it's also used by some mem objects. * Eventually we should move this typedef to wherever Addr is * defined. @@ -59,7 +69,6 @@ typedef std::list<Range<Addr> > AddrRangeList; typedef std::list<Range<Addr> >::iterator AddrRangeIter; -class EventQueue; class MemObject; /** @@ -73,7 +82,7 @@ class MemObject; * Send accessor functions are being called from the device the port is * associated with, and it will call the peer recv. accessor function. */ -class Port : public EventManager +class Port { protected: /** Descriptive name (for DPRINTF output) */ @@ -103,13 +112,6 @@ class Port : public EventManager virtual ~Port(); - // mey be better to use subclasses & RTTI? - /** Holds the ports status. Currently just that a range recomputation needs - * to be done. */ - enum Status { - RangeChange - }; - void setName(const std::string &name) { portName = name; } @@ -125,13 +127,7 @@ class Port : public EventManager /** Function to return the owner of this port. */ MemObject *getOwner() { return owner; } - /** Inform the peer port to delete itself and notify it's owner about it's - * demise. */ - void removeConn(); - - virtual bool isDefaultPort() const { return false; } - - bool isConnected() { return peer && !peer->isDefaultPort(); } + bool isConnected() { return peer != NULL; } protected: @@ -147,8 +143,8 @@ class Port : public EventManager /** Called to recive a functional call from the peer port. */ virtual void recvFunctional(PacketPtr pkt) = 0; - /** Called to recieve a status change from the peer port. */ - virtual void recvStatusChange(Status status) = 0; + /** Called to recieve an address range change from the peer port. */ + virtual void recvRangeChange() = 0; /** Called by a peer port if the send was unsuccesful, and had to wait. This shouldn't be valid for response paths (IO Devices). @@ -163,17 +159,31 @@ class Port : public EventManager */ virtual unsigned deviceBlockSize() const { return 0; } - /** The peer port is requesting us to reply with a list of the ranges we - are responsible for. - @param resp is a list of ranges responded to - @param snoop is a list of ranges snooped - */ - virtual void getDeviceAddressRanges(AddrRangeList &resp, - bool &snoop) - { panic("??"); } - public: + /** + * Get a list of the non-overlapping address ranges we are + * responsible for. The default implementation returns an empty + * list and thus no address ranges. Any slave port must override + * this function and return a populated list with at least one + * item. + * + * @return a list of ranges responded to + */ + virtual AddrRangeList getAddrRanges() + { AddrRangeList ranges; return ranges; } + + /** + * Determine if this port is snooping or not. The default + * implementation returns false and thus tells the neighbour we + * are not snooping. Any port that is to snoop (e.g. a cache + * connected to a bus) has to override this function. + * + * @return true if the port should be considered a snooper + */ + virtual bool isSnooping() + { return false; } + /** Function called by associated memory device (cache, memory, iodevice) in order to send a timing request to the port. Simply calls the peer port receive function. @@ -201,10 +211,11 @@ class Port : public EventManager void sendFunctional(PacketPtr pkt) { return peer->recvFunctional(pkt); } - /** Called by the associated device to send a status change to the device - connected to the peer interface. - */ - void sendStatusChange(Status status) {peer->recvStatusChange(status); } + /** + * Called by the associated device to send a status range to the + * peer interface. + */ + void sendRangeChange() const { peer->recvRangeChange(); } /** When a timing access doesn't return a success, some time later the Retry will be sent. @@ -216,12 +227,6 @@ class Port : public EventManager */ unsigned peerBlockSize() const { return peer->deviceBlockSize(); } - /** Called by the associated device if it wishes to find out the address - ranges connected to the peer ports devices. - */ - void getPeerAddressRanges(AddrRangeList &resp, bool &snoop) - { peer->getDeviceAddressRanges(resp, snoop); } - /** This function is a wrapper around sendFunctional() that breaks a larger, arbitrarily aligned access into appropriate chunks. The default implementation can use @@ -255,48 +260,4 @@ class Port : public EventManager void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd); }; -/** A simple functional port that is only meant for one way communication to - * physical memory. It is only meant to be used to load data into memory before - * the simulation begins. - */ - -class FunctionalPort : public Port -{ - public: - FunctionalPort(const std::string &_name, MemObject *_owner = NULL) - : Port(_name, _owner) - {} - - protected: - virtual bool recvTiming(PacketPtr pkt) { panic("FuncPort is UniDir"); - M5_DUMMY_RETURN } - virtual Tick recvAtomic(PacketPtr pkt) { panic("FuncPort is UniDir"); - M5_DUMMY_RETURN } - virtual void recvFunctional(PacketPtr pkt) { panic("FuncPort is UniDir"); } - virtual void recvStatusChange(Status status) {} - - public: - /** a write function that also does an endian conversion. */ - template <typename T> - inline void writeHtoG(Addr addr, T d); - - /** a read function that also does an endian conversion. */ - template <typename T> - inline T readGtoH(Addr addr); - - template <typename T> - inline void write(Addr addr, T d) - { - writeBlob(addr, (uint8_t*)&d, sizeof(T)); - } - - template <typename T> - inline T read(Addr addr) - { - T d; - readBlob(addr, (uint8_t*)&d, sizeof(T)); - return d; - } -}; - #endif //__MEM_PORT_HH__ diff --git a/src/mem/port_proxy.hh b/src/mem/port_proxy.hh new file mode 100644 index 000000000..31ad4c1cd --- /dev/null +++ b/src/mem/port_proxy.hh @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Andreas Hansson + */ + +/** + * @file + * PortProxy Object Declaration. + * + * Port proxies are used when non structural entities need access to + * the memory system. Proxy objects replace the previous + * FunctionalPort, TranslatingPort and VirtualPort objects, which + * provided the same functionality as the proxies, but were instances + * of ports not corresponding to real structural ports of the + * simulated system. Via the port proxies all the accesses go through + * an actual port and thus are transparent to a potentially + * distributed memory and automatically adhere to the memory map of + * the system. + */ + +#ifndef __MEM_PORT_PROXY_HH__ +#define __MEM_PORT_PROXY_HH__ + +#include "config/the_isa.hh" +#if THE_ISA != NO_ISA + #include "arch/isa_traits.hh" +#endif + +#include "base/types.hh" +#include "mem/port.hh" +#include "sim/byteswap.hh" + +/** + * This object is a proxy for a structural port, + * to be used for debug accesses. + * + * This proxy object is used when non structural entities + * (e.g. thread contexts, object file loaders) need access to the + * memory system. It calls the corresponding functions on the underlying + * structural port, and provides templatized convenience access functions. + * + * The addresses are interpreted as physical addresses. + * + * @sa SETranslatingProxy + * @sa FSTranslatingProxy + */ +class PortProxy +{ + protected: + Port &_port; + + public: + PortProxy(Port &port) : _port(port) { } + virtual ~PortProxy() { } + + public: + /** + * Read size bytes memory at address and store in p. + */ + virtual void readBlob(Addr address, uint8_t* p, int size) + { _port.readBlob(address, p, size); } + + /** + * Write size bytes from p to address. + */ + virtual void writeBlob(Addr address, uint8_t* p, int size) + { _port.writeBlob(address, p, size); } + + /** + * Fill size bytes starting at addr with byte value val. + */ + virtual void memsetBlob(Addr address, uint8_t v, int size) + { _port.memsetBlob(address, v, size); } + + /** + * Read sizeof(T) bytes from address and return as object T. + */ + template <typename T> + T read(Addr address); + + /** + * Write object T to address. Writes sizeof(T) bytes. + */ + template <typename T> + void write(Addr address, T data); + +#if THE_ISA != NO_ISA + /** + * Read sizeof(T) bytes from address and return as object T. + * Performs Guest to Host endianness transform. + */ + template <typename T> + T readGtoH(Addr address); + + /** + * Write object T to address. Writes sizeof(T) bytes. + * Performs Host to Guest endianness transform. + */ + template <typename T> + void writeHtoG(Addr address, T data); +#endif +}; + + +template <typename T> +T +PortProxy::read(Addr address) +{ + T data; + readBlob(address, (uint8_t*)&data, sizeof(T)); + return data; +} + +template <typename T> +void +PortProxy::write(Addr address, T data) +{ + writeBlob(address, (uint8_t*)&data, sizeof(T)); +} + +#if THE_ISA != NO_ISA +template <typename T> +T +PortProxy::readGtoH(Addr address) +{ + T data; + readBlob(address, (uint8_t*)&data, sizeof(T)); + return TheISA::gtoh(data); +} + +template <typename T> +void +PortProxy::writeHtoG(Addr address, T data) +{ + data = TheISA::htog(data); + writeBlob(address, (uint8_t*)&data, sizeof(T)); +} +#endif + +#endif // __MEM_PORT_PROXY_HH__ diff --git a/src/mem/protocol/MESI_CMP_directory-L1cache.sm b/src/mem/protocol/MESI_CMP_directory-L1cache.sm index f0be1fd34..934405786 100644 --- a/src/mem/protocol/MESI_CMP_directory-L1cache.sm +++ b/src/mem/protocol/MESI_CMP_directory-L1cache.sm @@ -27,14 +27,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -machine(L1Cache, "MSI Directory L1 Cache CMP") +machine(L1Cache, "MESI Directory L1 Cache CMP") : Sequencer * sequencer, CacheMemory * L1IcacheMemory, CacheMemory * L1DcacheMemory, int l2_select_num_bits, int l1_request_latency = 2, int l1_response_latency = 2, - int to_l2_latency = 1 + int to_l2_latency = 1, + bool send_evictions { // NODE L1 CACHE // From this node's L1 cache TO the network @@ -67,7 +68,6 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") IS_I, AccessPermission:Busy, desc="L1 idle, issued GETS, saw Inv before data because directory doesn't block on GETS hit"; M_I, AccessPermission:Busy, desc="L1 replacing, waiting for ACK"; - E_I, AccessPermission:Busy, desc="L1 replacing, waiting for ACK"; SINK_WB_ACK, AccessPermission:Busy, desc="This is to sink WB_Acks from L2"; } @@ -544,6 +544,12 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") } } + action(forward_eviction_to_cpu, "\cc", desc="sends eviction information to the processor") { + if (send_evictions) { + DPRINTF(RubySlicc, "Sending invalidation for %s to the CPU\n", address); + sequencer.evictionCallback(address); + } + } action(g_issuePUTX, "g", desc="send data to the L2 cache") { enqueue(requestIntraChipL1Network_out, RequestMsg, latency=l1_response_latency) { @@ -696,7 +702,7 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") //***************************************************** // Transitions for Load/Store/Replacement/WriteBack from transient states - transition({IS, IM, IS_I, M_I, E_I, SM}, {Load, Ifetch, Store, L1_Replacement}) { + transition({IS, IM, IS_I, M_I, SM}, {Load, Ifetch, Store, L1_Replacement}) { z_recycleMandatoryQueue; } @@ -748,10 +754,12 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") } transition(S, L1_Replacement, I) { + forward_eviction_to_cpu; ff_deallocateL1CacheBlock; } transition(S, Inv, I) { + forward_eviction_to_cpu; fi_sendInvAck; l_popRequestQueue; } @@ -770,6 +778,7 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") transition(E, L1_Replacement, M_I) { // silent E replacement?? + forward_eviction_to_cpu; i_allocateTBE; g_issuePUTX; // send data, but hold in case forwarded request ff_deallocateL1CacheBlock; @@ -777,11 +786,13 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") transition(E, Inv, I) { // don't send data + forward_eviction_to_cpu; fi_sendInvAck; l_popRequestQueue; } transition(E, Fwd_GETX, I) { + forward_eviction_to_cpu; d_sendDataToRequestor; l_popRequestQueue; } @@ -804,6 +815,7 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") } transition(M, L1_Replacement, M_I) { + forward_eviction_to_cpu; i_allocateTBE; g_issuePUTX; // send data, but hold in case forwarded request ff_deallocateL1CacheBlock; @@ -815,6 +827,7 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") } transition(M, Inv, I) { + forward_eviction_to_cpu; f_sendDataToL2; l_popRequestQueue; } @@ -825,6 +838,7 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") } transition(M, Fwd_GETX, I) { + forward_eviction_to_cpu; d_sendDataToRequestor; l_popRequestQueue; } @@ -866,7 +880,6 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") o_popIncomingResponseQueue; } - transition(IS, DataS_fromL1, S) { u_writeDataToL1Cache; j_sendUnblock; @@ -935,7 +948,6 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") transition(SINK_WB_ACK, {Load, Store, Ifetch, L1_Replacement}){ z_recycleMandatoryQueue; - } transition(SINK_WB_ACK, Inv){ @@ -948,6 +960,3 @@ machine(L1Cache, "MSI Directory L1 Cache CMP") o_popIncomingResponseQueue; } } - - - diff --git a/src/mem/protocol/MI_example-cache.sm b/src/mem/protocol/MI_example-cache.sm index b11fddd95..2f2e4e3d7 100644 --- a/src/mem/protocol/MI_example-cache.sm +++ b/src/mem/protocol/MI_example-cache.sm @@ -3,7 +3,8 @@ machine(L1Cache, "MI Example L1 Cache") : Sequencer * sequencer, CacheMemory * cacheMemory, int cache_response_latency = 12, - int issue_latency = 2 + int issue_latency = 2, + bool send_evictions { // NETWORK BUFFERS @@ -54,7 +55,6 @@ machine(L1Cache, "MI Example L1 Cache") DataBlock DataBlk, desc="Data in the block"; } - // TBE fields structure(TBE, desc="...") { State TBEState, desc="Transient state"; @@ -70,7 +70,6 @@ machine(L1Cache, "MI Example L1 Cache") // STRUCTURES - TBETable TBEs, template_hack="<L1Cache_TBE>"; // PROTOTYPES @@ -249,7 +248,6 @@ machine(L1Cache, "MI Example L1 Cache") } } - action(e_sendData, "e", desc="Send data from cache to requestor") { peek(forwardRequestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) { @@ -353,13 +351,18 @@ machine(L1Cache, "MI Example L1 Cache") } } + action(forward_eviction_to_cpu, "\cc", desc="sends eviction information to the processor") { + if (send_evictions) { + DPRINTF(RubySlicc, "Sending invalidation for %s to the CPU\n", address); + sequencer.evictionCallback(address); + } + } action(v_allocateTBE, "v", desc="Allocate TBE") { TBEs.allocate(address); set_tbe(TBEs[address]); } - action(w_deallocateTBE, "w", desc="Deallocate TBE") { TBEs.deallocate(address); unset_tbe(); @@ -435,6 +438,7 @@ machine(L1Cache, "MI Example L1 Cache") transition(M, Fwd_GETX, I) { e_sendData; + forward_eviction_to_cpu; o_popForwardedRequestQueue; } @@ -446,6 +450,7 @@ machine(L1Cache, "MI Example L1 Cache") v_allocateTBE; b_issuePUT; x_copyDataFromCacheToTBE; + forward_eviction_to_cpu; h_deallocateL1CacheBlock; } @@ -474,4 +479,3 @@ machine(L1Cache, "MI Example L1 Cache") o_popForwardedRequestQueue; } } - diff --git a/src/mem/protocol/MOESI_CMP_directory-L1cache.sm b/src/mem/protocol/MOESI_CMP_directory-L1cache.sm index 2845d1ad1..7a5cc6511 100644 --- a/src/mem/protocol/MOESI_CMP_directory-L1cache.sm +++ b/src/mem/protocol/MOESI_CMP_directory-L1cache.sm @@ -37,7 +37,8 @@ machine(L1Cache, "Directory protocol") CacheMemory * L1IcacheMemory, CacheMemory * L1DcacheMemory, int l2_select_num_bits, - int request_latency = 2 + int request_latency = 2, + bool send_evictions { // NODE L1 CACHE @@ -530,7 +531,6 @@ machine(L1Cache, "Directory protocol") } } - action(ee_sendDataExclusive, "\e", desc="Send data from cache to requestor, don't keep a shared copy") { peek(requestNetwork_in, RequestMsg) { assert(is_valid(cache_entry)); @@ -689,7 +689,6 @@ machine(L1Cache, "Directory protocol") useTimerTable.set(address, 50); } - action(ub_dmaUnblockL2Cache, "ub", desc="Send dma ack to l2 cache") { peek(requestNetwork_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) { @@ -775,7 +774,6 @@ machine(L1Cache, "Directory protocol") } } - // L2 will usually request data for a writeback action(qq_sendWBDataFromTBEToL2, "\q", desc="Send data from TBE to L2") { enqueue(responseNetwork_out, ResponseMsg, latency=request_latency) { @@ -811,7 +809,6 @@ machine(L1Cache, "Directory protocol") //assert(in_msg.Dirty == false); } } - } action(v_writeDataToCacheVerify, "v", desc="Write data to cache, assert it was same as before") { @@ -844,7 +841,12 @@ machine(L1Cache, "Directory protocol") } } - + action(forward_eviction_to_cpu, "\cc", desc="sends eviction information to the processor") { + if (send_evictions) { + DPRINTF(RubySlicc, "Sending invalidation for %s to the CPU\n", address); + sequencer.evictionCallback(address); + } + } action(uu_profileMiss, "\u", desc="Profile the demand miss") { peek(mandatoryQueue_in, RubyRequest) { @@ -931,11 +933,13 @@ machine(L1Cache, "Directory protocol") transition(S, L1_Replacement, SI) { i_allocateTBE; dd_issuePUTS; + forward_eviction_to_cpu; kk_deallocateL1CacheBlock; } transition(S, Inv, I) { f_sendAck; + forward_eviction_to_cpu; l_popForwardQueue; } @@ -966,11 +970,13 @@ machine(L1Cache, "Directory protocol") transition(O, L1_Replacement, OI) { i_allocateTBE; dd_issuePUTO; + forward_eviction_to_cpu; kk_deallocateL1CacheBlock; } transition(O, Fwd_GETX, I) { ee_sendDataExclusive; + forward_eviction_to_cpu; l_popForwardQueue; } @@ -999,16 +1005,19 @@ machine(L1Cache, "Directory protocol") transition(MM, L1_Replacement, MI) { i_allocateTBE; d_issuePUTX; + forward_eviction_to_cpu; kk_deallocateL1CacheBlock; } transition(MM, Fwd_GETX, I) { ee_sendDataExclusive; + forward_eviction_to_cpu; l_popForwardQueue; } transition(MM, Fwd_GETS, I) { ee_sendDataExclusive; + forward_eviction_to_cpu; l_popForwardQueue; } @@ -1037,12 +1046,14 @@ machine(L1Cache, "Directory protocol") transition(M, L1_Replacement, MI) { i_allocateTBE; d_issuePUTX; + forward_eviction_to_cpu; kk_deallocateL1CacheBlock; } transition(M, Fwd_GETX, I) { // e_sendData; ee_sendDataExclusive; + forward_eviction_to_cpu; l_popForwardQueue; } @@ -1080,6 +1091,7 @@ machine(L1Cache, "Directory protocol") // Transitions from SM transition(SM, Inv, IM) { f_sendAck; + forward_eviction_to_cpu; l_popForwardQueue; } diff --git a/src/mem/protocol/MOESI_CMP_token-L1cache.sm b/src/mem/protocol/MOESI_CMP_token-L1cache.sm index 66789b594..7cc41cc20 100644 --- a/src/mem/protocol/MOESI_CMP_token-L1cache.sm +++ b/src/mem/protocol/MOESI_CMP_token-L1cache.sm @@ -43,7 +43,8 @@ machine(L1Cache, "Token protocol") int retry_threshold = 1, int fixed_timeout_latency = 100, bool dynamic_timeout_enabled = true, - bool no_mig_atomic = true + bool no_mig_atomic = true, + bool send_evictions { // From this node's L1 cache TO the network @@ -1398,7 +1399,6 @@ machine(L1Cache, "Token protocol") } } - action(q_updateTokensFromResponse, "q", desc="Update the token count based on the incoming response message") { peek(responseNetwork_in, ResponseMsg) { assert(is_valid(cache_entry)); @@ -1522,6 +1522,13 @@ machine(L1Cache, "Token protocol") } } + action(forward_eviction_to_cpu, "\cc", desc="sends eviction information to the processor") { + if (send_evictions) { + DPRINTF(RubySlicc, "Sending invalidation for %s to the CPU\n", address); + sequencer.evictionCallback(address); + } + } + action(uu_profileMiss, "\u", desc="Profile the demand miss") { peek(mandatoryQueue_in, RubyRequest) { if (L1DcacheMemory.isTagPresent(address)) { @@ -1572,7 +1579,6 @@ machine(L1Cache, "Token protocol") zz_stallAndWaitMandatoryQueue; } - // Lockdowns transition({NP, I, S, O, M, MM, M_W, MM_W, IM, SM, OM, IS}, Own_Lock_or_Unlock) { l_popPersistentQueue; @@ -1702,6 +1708,7 @@ machine(L1Cache, "Token protocol") transition(S, L1_Replacement, I) { ta_traceStalledAddress; cc_sharedReplacement; // Only needed in some cases + forward_eviction_to_cpu; gg_deallocateL1CacheBlock; ka_wakeUpAllDependents; } @@ -1709,6 +1716,7 @@ machine(L1Cache, "Token protocol") transition(S, {Transient_GETX, Transient_Local_GETX}, I) { t_sendAckWithCollectedTokens; p_informL2AboutTokenLoss; + forward_eviction_to_cpu m_popRequestQueue; } @@ -1729,6 +1737,7 @@ machine(L1Cache, "Token protocol") transition({S, S_L}, Persistent_GETX, I_L) { e_sendAckWithCollectedTokens; p_informL2AboutTokenLoss; + forward_eviction_to_cpu l_popPersistentQueue; } @@ -1780,6 +1789,7 @@ machine(L1Cache, "Token protocol") transition(O, L1_Replacement, I) { ta_traceStalledAddress; c_ownedReplacement; + forward_eviction_to_cpu gg_deallocateL1CacheBlock; ka_wakeUpAllDependents; } @@ -1787,12 +1797,14 @@ machine(L1Cache, "Token protocol") transition(O, {Transient_GETX, Transient_Local_GETX}, I) { dd_sendDataWithAllTokens; p_informL2AboutTokenLoss; + forward_eviction_to_cpu m_popRequestQueue; } transition(O, Persistent_GETX, I_L) { ee_sendDataWithAllTokens; p_informL2AboutTokenLoss; + forward_eviction_to_cpu l_popPersistentQueue; } @@ -1803,6 +1815,7 @@ machine(L1Cache, "Token protocol") transition(O, Persistent_GETS_Last_Token, I_L) { fo_sendDataWithOwnerToken; + forward_eviction_to_cpu l_popPersistentQueue; } @@ -1867,6 +1880,7 @@ machine(L1Cache, "Token protocol") transition(MM, L1_Replacement, I) { ta_traceStalledAddress; c_ownedReplacement; + forward_eviction_to_cpu gg_deallocateL1CacheBlock; ka_wakeUpAllDependents; } @@ -1874,6 +1888,7 @@ machine(L1Cache, "Token protocol") transition(MM, {Transient_GETX, Transient_Local_GETX, Transient_GETS, Transient_Local_GETS}, I) { dd_sendDataWithAllTokens; p_informL2AboutTokenLoss; + forward_eviction_to_cpu m_popRequestQueue; } @@ -1885,6 +1900,7 @@ machine(L1Cache, "Token protocol") transition(MM, {Persistent_GETX, Persistent_GETS}, I_L) { ee_sendDataWithAllTokens; p_informL2AboutTokenLoss; + forward_eviction_to_cpu l_popPersistentQueue; } @@ -1934,6 +1950,7 @@ machine(L1Cache, "Token protocol") transition(M, L1_Replacement, I) { ta_traceStalledAddress; c_ownedReplacement; + forward_eviction_to_cpu gg_deallocateL1CacheBlock; ka_wakeUpAllDependents; } @@ -1941,6 +1958,7 @@ machine(L1Cache, "Token protocol") transition(M, {Transient_GETX, Transient_Local_GETX}, I) { dd_sendDataWithAllTokens; p_informL2AboutTokenLoss; + forward_eviction_to_cpu m_popRequestQueue; } @@ -1961,6 +1979,7 @@ machine(L1Cache, "Token protocol") transition(M, Persistent_GETX, I_L) { ee_sendDataWithAllTokens; p_informL2AboutTokenLoss; + forward_eviction_to_cpu l_popPersistentQueue; } @@ -1990,22 +2009,21 @@ machine(L1Cache, "Token protocol") transition(M_W, Use_TimeoutStarverX, I_L) { s_deallocateTBE; ee_sendDataWithAllTokens; + forward_eviction_to_cpu; p_informL2AboutTokenLoss; jj_unsetUseTimer; } - - // migratory transition(MM_W, {Use_TimeoutStarverX, Use_TimeoutStarverS}, I_L) { s_deallocateTBE; ee_sendDataWithAllTokens; + forward_eviction_to_cpu; p_informL2AboutTokenLoss; jj_unsetUseTimer; } - // Transient_GETX and Transient_GETS in transient states transition(OM, {Transient_GETX, Transient_Local_GETX, Transient_GETS, Transient_GETS_Last_Token, Transient_Local_GETS_Last_Token, Transient_Local_GETS}) { m_popRequestQueue; // Even if we have the data, we can pretend we don't have it yet. @@ -2040,6 +2058,7 @@ machine(L1Cache, "Token protocol") transition({SM, SM_L}, Persistent_GETX, IM_L) { e_sendAckWithCollectedTokens; + forward_eviction_to_cpu l_popPersistentQueue; } @@ -2054,6 +2073,7 @@ machine(L1Cache, "Token protocol") transition(OM, Persistent_GETX, IM_L) { ee_sendDataWithAllTokens; + forward_eviction_to_cpu l_popPersistentQueue; } @@ -2120,6 +2140,7 @@ machine(L1Cache, "Token protocol") transition({IM, SM}, {Transient_GETX, Transient_Local_GETX}, IM) { // We don't have the data yet, but we might have collected some tokens. We give them up here to avoid livelock t_sendAckWithCollectedTokens; + forward_eviction_to_cpu; m_popRequestQueue; } @@ -2336,7 +2357,6 @@ machine(L1Cache, "Token protocol") kd_wakeUpDependents; } - // Own_Lock_or_Unlock transition(I_L, Own_Lock_or_Unlock, I) { @@ -2364,4 +2384,3 @@ machine(L1Cache, "Token protocol") kd_wakeUpDependents; } } - diff --git a/src/mem/protocol/MOESI_hammer-cache.sm b/src/mem/protocol/MOESI_hammer-cache.sm index ce16a8777..219096d26 100644 --- a/src/mem/protocol/MOESI_hammer-cache.sm +++ b/src/mem/protocol/MOESI_hammer-cache.sm @@ -41,7 +41,8 @@ machine(L1Cache, "AMD Hammer-like protocol") int cache_response_latency = 10, int issue_latency = 2, int l2_cache_hit_latency = 10, - bool no_mig_atomic = true + bool no_mig_atomic = true, + bool send_evictions { // NETWORK BUFFERS @@ -1207,6 +1208,13 @@ machine(L1Cache, "AMD Hammer-like protocol") unset_cache_entry(); } + action(forward_eviction_to_cpu, "\cc", desc="sends eviction information to the processor") { + if (send_evictions) { + DPRINTF(RubySlicc, "Sending invalidation for %s to the CPU\n", address); + sequencer.evictionCallback(address); + } + } + action(uu_profileMiss, "\u", desc="Profile the demand miss") { peek(mandatoryQueue_in, RubyRequest) { if (L1IcacheMemory.isTagPresent(address)) { @@ -1486,17 +1494,20 @@ machine(L1Cache, "AMD Hammer-like protocol") i_allocateTBE; bf_issueGETF; uu_profileMiss; + forward_eviction_to_cpu; gg_deallocateL1CacheBlock; k_popMandatoryQueue; } transition(S, L2_Replacement, I) { + forward_eviction_to_cpu; rr_deallocateL2CacheBlock; ka_wakeUpAllDependents; } transition(S, {Other_GETX, Invalidate}, I) { f_sendAck; + forward_eviction_to_cpu; l_popForwardQueue; } @@ -1528,6 +1539,7 @@ machine(L1Cache, "AMD Hammer-like protocol") bf_issueGETF; p_decrementNumberOfMessagesByOne; uu_profileMiss; + forward_eviction_to_cpu; gg_deallocateL1CacheBlock; k_popMandatoryQueue; } @@ -1535,12 +1547,14 @@ machine(L1Cache, "AMD Hammer-like protocol") transition(O, L2_Replacement, OI) { i_allocateTBE; d_issuePUT; + forward_eviction_to_cpu; rr_deallocateL2CacheBlock; ka_wakeUpAllDependents; } transition(O, {Other_GETX, Invalidate}, I) { e_sendData; + forward_eviction_to_cpu; l_popForwardQueue; } @@ -1569,6 +1583,7 @@ machine(L1Cache, "AMD Hammer-like protocol") i_allocateTBE; bf_issueGETF; p_decrementNumberOfMessagesByOne; + forward_eviction_to_cpu; gg_deallocateL1CacheBlock; k_popMandatoryQueue; } @@ -1582,17 +1597,20 @@ machine(L1Cache, "AMD Hammer-like protocol") transition(MM, L2_Replacement, MI) { i_allocateTBE; d_issuePUT; + forward_eviction_to_cpu; rr_deallocateL2CacheBlock; ka_wakeUpAllDependents; } transition(MM, {Other_GETX, Invalidate}, I) { c_sendExclusiveData; + forward_eviction_to_cpu; l_popForwardQueue; } transition(MM, Other_GETS, I) { c_sendExclusiveData; + forward_eviction_to_cpu; l_popForwardQueue; } @@ -1625,12 +1643,14 @@ machine(L1Cache, "AMD Hammer-like protocol") transition(M, L2_Replacement, MI) { i_allocateTBE; d_issuePUT; + forward_eviction_to_cpu; rr_deallocateL2CacheBlock; ka_wakeUpAllDependents; } transition(M, {Other_GETX, Invalidate}, I) { c_sendExclusiveData; + forward_eviction_to_cpu; l_popForwardQueue; } @@ -1700,11 +1720,13 @@ machine(L1Cache, "AMD Hammer-like protocol") transition(SM, {Other_GETX, Invalidate}, IM) { f_sendAck; + forward_eviction_to_cpu; l_popForwardQueue; } transition(SM_F, {Other_GETX, Invalidate}, IM_F) { f_sendAck; + forward_eviction_to_cpu; l_popForwardQueue; } @@ -1754,12 +1776,14 @@ machine(L1Cache, "AMD Hammer-like protocol") transition(OM, {Other_GETX, Invalidate}, IM) { e_sendData; pp_incrementNumberOfMessagesByOne; + forward_eviction_to_cpu; l_popForwardQueue; } transition(OM_F, {Other_GETX, Invalidate}, IM_F) { q_sendDataFromTBEToCache; pp_incrementNumberOfMessagesByOne; + forward_eviction_to_cpu; l_popForwardQueue; } diff --git a/src/mem/protocol/MOESI_hammer-dir.sm b/src/mem/protocol/MOESI_hammer-dir.sm index a20619d46..dfb62e844 100644 --- a/src/mem/protocol/MOESI_hammer-dir.sm +++ b/src/mem/protocol/MOESI_hammer-dir.sm @@ -87,7 +87,7 @@ machine(Directory, "AMD Hammer-like protocol") O_DR_B, AccessPermission:Busy, desc="Owner, Dma Read waiting for cache responses"; WB, AccessPermission:Busy, desc="Blocked on a writeback"; WB_O_W, AccessPermission:Busy, desc="Blocked on memory write, will go to O"; - WB_E_W, AccessPermission:Busy, desc="Blocked on memory write, will go to E"; + WB_E_W, AccessPermission:Read_Write, desc="Blocked on memory write, will go to E"; NO_F, AccessPermission:Busy, desc="Blocked on a flush"; NO_F_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram"; diff --git a/src/mem/protocol/RubySlicc_Types.sm b/src/mem/protocol/RubySlicc_Types.sm index c76e0fe3e..3b90dab20 100644 --- a/src/mem/protocol/RubySlicc_Types.sm +++ b/src/mem/protocol/RubySlicc_Types.sm @@ -107,6 +107,7 @@ structure (Sequencer, external = "yes") { void writeCallback(Address, GenericMachineType, DataBlock, Time, Time, Time); void checkCoherence(Address); void profileNack(Address, int, int, uint64); + void evictionCallback(Address); } structure(RubyRequest, desc="...", interface="Message", external="yes") { diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index 64faf6aed..b60ca2a07 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2009 Advanced Micro Devices, Inc. + * Copyright (c) 2011 Mark D. Hill and David A. Wood * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -93,14 +94,6 @@ RubyPort::getPort(const std::string &if_name, int idx) return physMemPort; } - if (if_name == "functional") { - // Calls for the functional port only want to access - // functional memory. Therefore, directly pass these calls - // ports to physmem. - assert(physmem != NULL); - return physmem->getPort(if_name, idx); - } - return NULL; } @@ -464,8 +457,11 @@ RubyPort::M5Port::recvFunctional(PacketPtr pkt) // turn packet around to go back to requester if response expected if (needsResponse) { pkt->setFunctionalResponseStatus(accessSucceeded); - DPRINTF(RubyPort, "Sending packet back over port\n"); - sendFunctional(pkt); + + // @todo There should not be a reverse call since the response is + // communicated through the packet pointer + // DPRINTF(RubyPort, "Sending packet back over port\n"); + // sendFunctional(pkt); } DPRINTF(RubyPort, "Functional access %s!\n", accessSucceeded ? "successful":"failed"); @@ -668,9 +664,8 @@ RubyPort::PioPort::sendTiming(PacketPtr pkt) bool RubyPort::M5Port::isPhysMemAddress(Addr addr) { - AddrRangeList physMemAddrList; - bool snoop = false; - ruby_port->physMemPort->getPeerAddressRanges(physMemAddrList, snoop); + AddrRangeList physMemAddrList = + ruby_port->physMemPort->getPeer()->getAddrRanges(); for (AddrRangeIter iter = physMemAddrList.begin(); iter != physMemAddrList.end(); iter++) { @@ -688,3 +683,14 @@ RubyPort::M5Port::deviceBlockSize() const { return (unsigned) RubySystem::getBlockSizeBytes(); } + +void +RubyPort::ruby_eviction_callback(const Address& address) +{ + DPRINTF(RubyPort, "Sending invalidations.\n"); + Request req(address.getAddress(), 0, 0); + for (CpuPortIter it = cpu_ports.begin(); it != cpu_ports.end(); it++) { + Packet *pkt = new Packet(&req, MemCmd::InvalidationReq, -1); + (*it)->sendTiming(pkt); + } +} diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh index d8dbe0cda..2ffdef3d9 100644 --- a/src/mem/ruby/system/RubyPort.hh +++ b/src/mem/ruby/system/RubyPort.hh @@ -1,5 +1,6 @@ /* * Copyright (c) 2009 Advanced Micro Devices, Inc. + * Copyright (c) 2011 Mark D. Hill and David A. Wood * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -58,6 +59,7 @@ class RubyPort : public MemObject RubySystem*_system, bool _access_phys_mem); bool sendTiming(PacketPtr pkt); void hitCallback(PacketPtr pkt); + void evictionCallback(const Address& address); unsigned deviceBlockSize() const; bool onRetryList() @@ -129,8 +131,8 @@ class RubyPort : public MemObject protected: const std::string m_name; void ruby_hit_callback(PacketPtr pkt); - void hit(PacketPtr pkt); void testDrainComplete(); + void ruby_eviction_callback(const Address& address); int m_version; AbstractController* m_controller; diff --git a/src/mem/port_impl.hh b/src/mem/ruby/system/RubyPortProxy.cc index bc9592164..29a693ca6 100644 --- a/src/mem/port_impl.hh +++ b/src/mem/ruby/system/RubyPortProxy.cc @@ -1,6 +1,15 @@ /* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -25,29 +34,37 @@ * (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: Ali Saidi + * Authors: Andreas Hansson */ -#include "arch/isa_traits.hh" -#include "config/the_isa.hh" -#include "mem/port.hh" -#include "sim/byteswap.hh" +#include "mem/ruby/system/RubyPortProxy.hh" -template <typename T> -void -FunctionalPort::writeHtoG(Addr addr, T d) +RubyPortProxy::RubyPortProxy(const RubyPortProxyParams* p) : + RubyPort(p) { +} + +RubyPortProxy::~RubyPortProxy() { - d = TheISA::htog(d); - writeBlob(addr, (uint8_t*)&d, sizeof(T)); } +void +RubyPortProxy::init() +{ + // Merely override to not care about the m_controller being NULL +} -template <typename T> -T -FunctionalPort::readGtoH(Addr addr) +RequestStatus +RubyPortProxy::makeRequest(PacketPtr pkt) { - T d; - readBlob(addr, (uint8_t*)&d, sizeof(T)); - return TheISA::gtoh(d); + // This sequencer should only be used through the functional + // accesses made by the system port and so simply fail if this + // happens. + panic("RubyPortProxy::makeRequest should not be called"); + return RequestStatus_NULL; } +RubyPortProxy* +RubyPortProxyParams::create() +{ + return new RubyPortProxy(this); +} diff --git a/src/mem/ruby/system/RubyPortProxy.hh b/src/mem/ruby/system/RubyPortProxy.hh new file mode 100644 index 000000000..8f88541e5 --- /dev/null +++ b/src/mem/ruby/system/RubyPortProxy.hh @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * 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: Andreas Hansson + */ + +/** + * @file + * RobyPortProxy for connecting system port to Ruby + * + * A trivial wrapper that allows the system port to connect to Ruby + * and use nothing but functional accesses. + */ + +#ifndef __MEM_RUBY_SYSTEM_RUBYPORTPROXY_HH__ +#define __MEM_RUBY_SYSTEM_RUBYPORTPROXY_HH__ + +#include "mem/ruby/system/RubyPort.hh" +#include "params/RubyPortProxy.hh" + +class RubyPortProxy : public RubyPort +{ + + public: + + /** + * Create a new RubyPortProxy. + * + * @param p Parameters inherited from the RubyPort + */ + RubyPortProxy(const RubyPortProxyParams* p); + + /** + * Destruct a RubyPortProxy. + */ + virtual ~RubyPortProxy(); + + /** + * Initialise a RubyPortProxy by doing nothing and avoid + * involving the super class. + */ + void init(); + + /** + * Pure virtual member in the super class that we are forced to + * implement even if it is never used (since there are only + * functional accesses). + * + * @param pkt The packet to serve to Ruby + * @returns always a NULL status + */ + RequestStatus makeRequest(PacketPtr pkt); + + /** + * Pure virtual member in the super class that we are forced to + * implement even if it is never used (since there are only + * functional accesses). + * + * @returns always 0 + */ + int outstandingCount() const { return 0; } + + /** + * Pure virtual member in the super class that we are forced to + * implement even if it is never used (since there are only + * functional accesses). + * + * @returns always false + */ + bool isDeadlockEventScheduled() const { return false; } + + /** + * Pure virtual member in the super class that we are forced to + * implement even if it is never used (since there are only + * functional accesses). + */ + void descheduleDeadlockEvent() { } + +}; + +#endif // __MEM_RUBY_SYSTEM_RUBYPORTPROXY_HH__ diff --git a/src/mem/ruby/system/SConscript b/src/mem/ruby/system/SConscript index 66d7d95bb..cbb1da3b1 100644 --- a/src/mem/ruby/system/SConscript +++ b/src/mem/ruby/system/SConscript @@ -49,6 +49,7 @@ Source('WireBuffer.cc') Source('MemoryNode.cc') Source('PersistentTable.cc') Source('RubyPort.cc') +Source('RubyPortProxy.cc') Source('Sequencer.cc') Source('System.cc') Source('TimerTable.cc') diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index 3f9ceb34d..1cd54d45c 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -733,3 +733,9 @@ Sequencer::checkCoherence(const Address& addr) g_system_ptr->checkGlobalCoherenceInvariant(addr); #endif } + +void +Sequencer::evictionCallback(const Address& address) +{ + ruby_eviction_callback(address); +} diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh index 4a6d46c01..e262e32e8 100644 --- a/src/mem/ruby/system/Sequencer.hh +++ b/src/mem/ruby/system/Sequencer.hh @@ -117,6 +117,7 @@ class Sequencer : public RubyPort, public Consumer void markRemoved(); void removeRequest(SequencerRequest* request); + void evictionCallback(const Address& address); private: void issueRequest(PacketPtr pkt, RubyRequestType type); @@ -181,4 +182,3 @@ operator<<(std::ostream& out, const Sequencer& obj) } #endif // __MEM_RUBY_SYSTEM_SEQUENCER_HH__ - diff --git a/src/mem/ruby/system/Sequencer.py b/src/mem/ruby/system/Sequencer.py index 5d56dc000..ddf760f7b 100644 --- a/src/mem/ruby/system/Sequencer.py +++ b/src/mem/ruby/system/Sequencer.py @@ -44,6 +44,9 @@ class RubyPort(MemObject): access_phys_mem = Param.Bool(True, "should the rubyport atomically update phys_mem") ruby_system = Param.RubySystem("") + +class RubyPortProxy(RubyPort): + type = 'RubyPortProxy' class RubySequencer(RubyPort): type = 'RubySequencer' diff --git a/src/mem/translating_port.cc b/src/mem/se_translating_port_proxy.cc index 7d3123012..0f7ecb491 100644 --- a/src/mem/translating_port.cc +++ b/src/mem/se_translating_port_proxy.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2001-2005 The Regents of The University of Michigan * All rights reserved. * @@ -27,6 +39,7 @@ * * Authors: Ron Dreslinski * Steve Reinhardt + * Andreas Hansson */ #include <string> @@ -35,22 +48,22 @@ #include "base/chunk_generator.hh" #include "config/the_isa.hh" #include "mem/page_table.hh" -#include "mem/port.hh" -#include "mem/translating_port.hh" +#include "mem/se_translating_port_proxy.hh" #include "sim/process.hh" using namespace TheISA; -TranslatingPort::TranslatingPort(const std::string &_name, Process *p, - AllocType alloc) - : FunctionalPort(_name), pTable(p->pTable), process(p), allocating(alloc) +SETranslatingPortProxy::SETranslatingPortProxy(Port& port, Process *p, + AllocType alloc) + : PortProxy(port), pTable(p->pTable), process(p), + allocating(alloc) { } -TranslatingPort::~TranslatingPort() +SETranslatingPortProxy::~SETranslatingPortProxy() { } bool -TranslatingPort::tryReadBlob(Addr addr, uint8_t *p, int size) +SETranslatingPortProxy::tryReadBlob(Addr addr, uint8_t *p, int size) { int prevSize = 0; @@ -60,7 +73,7 @@ TranslatingPort::tryReadBlob(Addr addr, uint8_t *p, int size) if (!pTable->translate(gen.addr(),paddr)) return false; - Port::readBlob(paddr, p + prevSize, gen.size()); + PortProxy::readBlob(paddr, p + prevSize, gen.size()); prevSize += gen.size(); } @@ -68,7 +81,7 @@ TranslatingPort::tryReadBlob(Addr addr, uint8_t *p, int size) } void -TranslatingPort::readBlob(Addr addr, uint8_t *p, int size) +SETranslatingPortProxy::readBlob(Addr addr, uint8_t *p, int size) { if (!tryReadBlob(addr, p, size)) fatal("readBlob(0x%x, ...) failed", addr); @@ -76,7 +89,7 @@ TranslatingPort::readBlob(Addr addr, uint8_t *p, int size) bool -TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size) +SETranslatingPortProxy::tryWriteBlob(Addr addr, uint8_t *p, int size) { int prevSize = 0; @@ -98,7 +111,7 @@ TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size) pTable->translate(gen.addr(), paddr); } - Port::writeBlob(paddr, p + prevSize, gen.size()); + PortProxy::writeBlob(paddr, p + prevSize, gen.size()); prevSize += gen.size(); } @@ -107,14 +120,14 @@ TranslatingPort::tryWriteBlob(Addr addr, uint8_t *p, int size) void -TranslatingPort::writeBlob(Addr addr, uint8_t *p, int size) +SETranslatingPortProxy::writeBlob(Addr addr, uint8_t *p, int size) { if (!tryWriteBlob(addr, p, size)) fatal("writeBlob(0x%x, ...) failed", addr); } bool -TranslatingPort::tryMemsetBlob(Addr addr, uint8_t val, int size) +SETranslatingPortProxy::tryMemsetBlob(Addr addr, uint8_t val, int size) { for (ChunkGenerator gen(addr, size, VMPageSize); !gen.done(); gen.next()) { Addr paddr; @@ -128,14 +141,15 @@ TranslatingPort::tryMemsetBlob(Addr addr, uint8_t val, int size) return false; } } - Port::memsetBlob(paddr, val, gen.size()); + + PortProxy::memsetBlob(paddr, val, gen.size()); } return true; } void -TranslatingPort::memsetBlob(Addr addr, uint8_t val, int size) +SETranslatingPortProxy::memsetBlob(Addr addr, uint8_t val, int size) { if (!tryMemsetBlob(addr, val, size)) fatal("memsetBlob(0x%x, ...) failed", addr); @@ -143,7 +157,7 @@ TranslatingPort::memsetBlob(Addr addr, uint8_t val, int size) bool -TranslatingPort::tryWriteString(Addr addr, const char *str) +SETranslatingPortProxy::tryWriteString(Addr addr, const char *str) { uint8_t c; @@ -156,21 +170,21 @@ TranslatingPort::tryWriteString(Addr addr, const char *str) if (!pTable->translate(vaddr++, paddr)) return false; - Port::writeBlob(paddr, &c, 1); + PortProxy::writeBlob(paddr, &c, 1); } while (c); return true; } void -TranslatingPort::writeString(Addr addr, const char *str) +SETranslatingPortProxy::writeString(Addr addr, const char *str) { if (!tryWriteString(addr, str)) fatal("writeString(0x%x, ...) failed", addr); } bool -TranslatingPort::tryReadString(std::string &str, Addr addr) +SETranslatingPortProxy::tryReadString(std::string &str, Addr addr) { uint8_t c; @@ -182,7 +196,7 @@ TranslatingPort::tryReadString(std::string &str, Addr addr) if (!pTable->translate(vaddr++, paddr)) return false; - Port::readBlob(paddr, &c, 1); + PortProxy::readBlob(paddr, &c, 1); str += c; } while (c); @@ -190,7 +204,7 @@ TranslatingPort::tryReadString(std::string &str, Addr addr) } void -TranslatingPort::readString(std::string &str, Addr addr) +SETranslatingPortProxy::readString(std::string &str, Addr addr) { if (!tryReadString(str, addr)) fatal("readString(0x%x, ...) failed", addr); diff --git a/src/mem/translating_port.hh b/src/mem/se_translating_port_proxy.hh index 438d8fe61..71e8b4f50 100644 --- a/src/mem/translating_port.hh +++ b/src/mem/se_translating_port_proxy.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2001-2005 The Regents of The University of Michigan * All rights reserved. * @@ -27,18 +39,33 @@ * * Authors: Ron Dreslinski * Ali Saidi + * Andreas Hansson */ -#ifndef __MEM_TRANSLATING_PROT_HH__ -#define __MEM_TRANSLATING_PROT_HH__ - -#include "mem/port.hh" +#ifndef __MEM_SE_TRANSLATING_PORT_PROXY_HH__ +#define __MEM_SE_TRANSLATING_PORT_PROXY_HH__ -class PageTable; -class Process; +#include "mem/page_table.hh" +#include "mem/port_proxy.hh" +#include "sim/process.hh" -class TranslatingPort : public FunctionalPort +/** + * @file + * TranslatingPortProxy Object Declaration for SE. + * + * Port proxies are used when non structural entities need access to + * the memory system. Proxy objects replace the previous + * FunctionalPort, TranslatingPort and VirtualPort objects, which + * provided the same functionality as the proxies, but were instances + * of ports not corresponding to real structural ports of the + * simulated system. Via the port proxies all the accesses go through + * an actual port and thus are transparent to a potentially + * distributed memory and automatically adhere to the memory map of + * the system. + */ +class SETranslatingPortProxy : public PortProxy { + public: enum AllocType { Always, @@ -52,8 +79,8 @@ class TranslatingPort : public FunctionalPort AllocType allocating; public: - TranslatingPort(const std::string &_name, Process *p, AllocType alloc); - virtual ~TranslatingPort(); + SETranslatingPortProxy(Port& port, Process* p, AllocType alloc); + virtual ~SETranslatingPortProxy(); bool tryReadBlob(Addr addr, uint8_t *p, int size); bool tryWriteBlob(Addr addr, uint8_t *p, int size); @@ -69,4 +96,4 @@ class TranslatingPort : public FunctionalPort void readString(std::string &str, Addr addr); }; -#endif +#endif // __MEM_SE_TRANSLATING_PORT_PROXY_HH__ diff --git a/src/mem/tport.cc b/src/mem/tport.cc index 8e02215f2..7b1fdb850 100644 --- a/src/mem/tport.cc +++ b/src/mem/tport.cc @@ -29,12 +29,13 @@ */ #include "debug/Bus.hh" +#include "mem/mem_object.hh" #include "mem/tport.hh" using namespace std; SimpleTimingPort::SimpleTimingPort(string pname, MemObject *_owner) - : Port(pname, _owner), sendEvent(0), drainEvent(NULL), + : Port(pname, _owner), sendEvent(NULL), drainEvent(NULL), waitingOnRetry(false) { sendEvent = new EventWrapper<SimpleTimingPort, @@ -104,6 +105,20 @@ SimpleTimingPort::recvTiming(PacketPtr pkt) return true; } +void +SimpleTimingPort::schedSendEvent(Tick when) +{ + if (waitingOnRetry) { + assert(!sendEvent->scheduled()); + return; + } + + if (!sendEvent->scheduled()) { + owner->schedule(sendEvent, when); + } else if (sendEvent->when() > when) { + owner->reschedule(sendEvent, when); + } +} void SimpleTimingPort::schedSendTiming(PacketPtr pkt, Tick when) @@ -153,7 +168,7 @@ SimpleTimingPort::sendDeferredPacket() if (success) { if (!transmitList.empty() && !sendEvent->scheduled()) { Tick time = transmitList.front().tick; - schedule(sendEvent, time <= curTick() ? curTick()+1 : time); + owner->schedule(sendEvent, time <= curTick() ? curTick()+1 : time); } if (transmitList.empty() && drainEvent && !sendEvent->scheduled()) { diff --git a/src/mem/tport.hh b/src/mem/tport.hh index f081d8656..eaf5acd5d 100644 --- a/src/mem/tport.hh +++ b/src/mem/tport.hh @@ -106,21 +106,14 @@ class SimpleTimingPort : public Port Tick deferredPacketReadyTime() { return transmitList.empty() ? MaxTick : transmitList.front().tick; } - void - schedSendEvent(Tick when) - { - if (waitingOnRetry) { - assert(!sendEvent->scheduled()); - return; - } - - if (!sendEvent->scheduled()) { - schedule(sendEvent, when); - } else if (sendEvent->when() > when) { - reschedule(sendEvent, when); - } - } - + /** + * Schedule a send even if not already waiting for a retry. If the + * requested time is before an already scheduled send event it + * will be rescheduled. + * + * @param when + */ + void schedSendEvent(Tick when); /** Schedule a sendTiming() event to be called in the future. * @param pkt packet to send @@ -146,10 +139,13 @@ class SimpleTimingPort : public Port bool recvTiming(PacketPtr pkt); /** - * Simple ports generally don't care about any status - * changes... can always override this in cases where that's not - * true. */ - virtual void recvStatusChange(Status status) { } + * Simple ports are generally used as slave ports (i.e. the + * respond to requests) and thus do not expect to receive any + * range changes (as the neighbouring port has a master role and + * do not have any address ranges. A subclass can override the + * default behaviuor if needed. + */ + virtual void recvRangeChange() { } public: diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index 47ca32af2..84d70d663 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -273,8 +273,6 @@ class MetaSimObject(type): assert(not hasattr(port, 'name')) port.name = name cls._ports[name] = port - if hasattr(port, 'default'): - cls._cls_get_port_ref(name).connect(port.default) # same as _get_port_ref, effectively, but for classes def _cls_get_port_ref(cls, attr): diff --git a/src/python/m5/params.py b/src/python/m5/params.py index 05fe9b774..dfc703a40 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -1488,13 +1488,10 @@ class VectorPortRef(object): # logical port in the SimObject class, not a particular port on a # SimObject instance. The latter are represented by PortRef objects. class Port(object): - # Port("description") or Port(default, "description") + # Port("description") def __init__(self, *args): if len(args) == 1: self.desc = args[0] - elif len(args) == 2: - self.default = args[0] - self.desc = args[1] else: raise TypeError, 'wrong number of arguments' # self.name is set by SimObject class on assignment diff --git a/src/sim/System.py b/src/sim/System.py index 39505c01a..73124ecb9 100644 --- a/src/sim/System.py +++ b/src/sim/System.py @@ -37,8 +37,9 @@ from PhysicalMemory import * class MemoryMode(Enum): vals = ['invalid', 'atomic', 'timing'] -class System(SimObject): +class System(MemObject): type = 'System' + system_port = Port("System port") @classmethod def export_method_cxx_predecls(cls, code): diff --git a/src/sim/arguments.hh b/src/sim/arguments.hh index ef94cbb25..5c7941562 100644 --- a/src/sim/arguments.hh +++ b/src/sim/arguments.hh @@ -36,7 +36,7 @@ #include "arch/vtophys.hh" #include "base/refcnt.hh" #include "base/types.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" class ThreadContext; diff --git a/src/sim/process.cc b/src/sim/process.cc index c400b72ee..45362fe1b 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -44,7 +44,7 @@ #include "cpu/thread_context.hh" #include "mem/page_table.hh" #include "mem/physical.hh" -#include "mem/translating_port.hh" +#include "mem/se_translating_port_proxy.hh" #include "params/LiveProcess.hh" #include "params/Process.hh" #include "sim/debug.hh" @@ -234,12 +234,8 @@ Process::initState() // mark this context as active so it will start ticking. tc->activate(0); - Port *mem_port; - mem_port = system->physmem->getPort("functional"); - initVirtMem = new TranslatingPort("process init port", this, - TranslatingPort::Always); - mem_port->setPeer(initVirtMem); - initVirtMem->setPeer(mem_port); + initVirtMem = new SETranslatingPortProxy(*system->getSystemPort(), this, + SETranslatingPortProxy::Always); } // map simulator fd sim_fd to target fd tgt_fd diff --git a/src/sim/process.hh b/src/sim/process.hh index f738bb38a..3896492b7 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -48,7 +48,7 @@ class LiveProcessParams; class SyscallDesc; class System; class ThreadContext; -class TranslatingPort; +class SETranslatingPortProxy; template<class IntType> struct AuxVector @@ -123,7 +123,7 @@ class Process : public SimObject protected: /// Memory object for initialization (image loading) - TranslatingPort *initVirtMem; + SETranslatingPortProxy *initVirtMem; public: PageTable *pTable; diff --git a/src/sim/process_impl.hh b/src/sim/process_impl.hh index 944c55ec0..401e16f52 100644 --- a/src/sim/process_impl.hh +++ b/src/sim/process_impl.hh @@ -35,7 +35,7 @@ #include <string> #include <vector> -#include "mem/translating_port.hh" +#include "mem/se_translating_port_proxy.hh" #include "sim/byteswap.hh" //This needs to be templated for cases where 32 bit pointers are needed. @@ -43,21 +43,21 @@ template<class AddrType> void copyStringArray(std::vector<std::string> &strings, AddrType array_ptr, AddrType data_ptr, - TranslatingPort* memPort) + SETranslatingPortProxy* memProxy) { AddrType data_ptr_swap; for (std::vector<std::string>::size_type i = 0; i < strings.size(); ++i) { data_ptr_swap = htog(data_ptr); - memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, + memProxy->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, sizeof(AddrType)); - memPort->writeString(data_ptr, strings[i].c_str()); + memProxy->writeString(data_ptr, strings[i].c_str()); array_ptr += sizeof(AddrType); data_ptr += strings[i].size() + 1; } // add NULL terminator data_ptr = 0; - memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType)); + memProxy->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType)); } #endif diff --git a/src/sim/stat_control.cc b/src/sim/stat_control.cc index 7cf77174f..eb5fe1307 100644 --- a/src/sim/stat_control.cc +++ b/src/sim/stat_control.cc @@ -53,6 +53,7 @@ using namespace std; Stats::Formula simSeconds; Stats::Value simTicks; +Stats::Value finalTick; Stats::Value simFreq; namespace Stats { @@ -85,6 +86,12 @@ statElapsedTicks() return curTick() - startTick; } +Tick +statFinalTick() +{ + return curTick(); +} + SimTicksReset simTicksReset; struct Global @@ -126,6 +133,13 @@ Global::Global() .desc("Number of ticks simulated") ; + finalTick + .functor(statFinalTick) + .name("final_tick") + .desc("Number of ticks from beginning of simulation \ +(restored from checkpoints and never reset)") + ; + hostInstRate .name("host_inst_rate") .desc("Simulator instruction rate (inst/s)") diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 203eaff2a..dc8a9a5c8 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -171,7 +171,7 @@ brkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) // if the address is already there, zero it out else { uint8_t zero = 0; - TranslatingPort *tp = tc->getMemPort(); + SETranslatingPortProxy *tp = tc->getMemProxy(); // split non-page aligned accesses Addr next_page = roundUp(gen.addr(), VMPageSize); @@ -221,7 +221,7 @@ readFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) int bytes_read = read(fd, bufArg.bufferPtr(), nbytes); if (bytes_read != -1) - bufArg.copyOut(tc->getMemPort()); + bufArg.copyOut(tc->getMemProxy()); return bytes_read; } @@ -235,7 +235,7 @@ writeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) int nbytes = p->getSyscallArg(tc, index); BufferArg bufArg(bufPtr, nbytes); - bufArg.copyIn(tc->getMemPort()); + bufArg.copyIn(tc->getMemProxy()); int bytes_written = write(fd, bufArg.bufferPtr(), nbytes); @@ -284,7 +284,7 @@ _llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) // target platform BufferArg result_buf(result_ptr, sizeof(result)); memcpy(result_buf.bufferPtr(), &result, sizeof(result)); - result_buf.copyOut(tc->getMemPort()); + result_buf.copyOut(tc->getMemProxy()); return 0; } @@ -313,7 +313,7 @@ gethostnameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) strncpy((char *)name.bufferPtr(), hostname, name_len); - name.copyOut(tc->getMemPort()); + name.copyOut(tc->getMemProxy()); return 0; } @@ -346,7 +346,7 @@ getcwdFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) } } - buf.copyOut(tc->getMemPort()); + buf.copyOut(tc->getMemProxy()); return (result == -1) ? -errno : result; } @@ -358,7 +358,7 @@ readlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) + if (!tc->getMemProxy()->tryReadString(path, p->getSyscallArg(tc, index))) return (TheISA::IntReg)-EFAULT; // Adjust path for current working directory @@ -371,7 +371,7 @@ readlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) int result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz); - buf.copyOut(tc->getMemPort()); + buf.copyOut(tc->getMemProxy()); return (result == -1) ? -errno : result; } @@ -382,7 +382,7 @@ unlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) + if (!tc->getMemProxy()->tryReadString(path, p->getSyscallArg(tc, index))) return (TheISA::IntReg)-EFAULT; // Adjust path for current working directory @@ -399,7 +399,7 @@ mkdirFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) + if (!tc->getMemProxy()->tryReadString(path, p->getSyscallArg(tc, index))) return (TheISA::IntReg)-EFAULT; // Adjust path for current working directory @@ -417,12 +417,12 @@ renameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) string old_name; int index = 0; - if (!tc->getMemPort()->tryReadString(old_name, p->getSyscallArg(tc, index))) + if (!tc->getMemProxy()->tryReadString(old_name, p->getSyscallArg(tc, index))) return -EFAULT; string new_name; - if (!tc->getMemPort()->tryReadString(new_name, p->getSyscallArg(tc, index))) + if (!tc->getMemProxy()->tryReadString(new_name, p->getSyscallArg(tc, index))) return -EFAULT; // Adjust path for current working directory @@ -439,7 +439,7 @@ truncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) + if (!tc->getMemProxy()->tryReadString(path, p->getSyscallArg(tc, index))) return -EFAULT; off_t length = p->getSyscallArg(tc, index); @@ -474,7 +474,7 @@ truncate64Func(SyscallDesc *desc, int num, int index = 0; string path; - if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, index))) + if (!tc->getMemProxy()->tryReadString(path, process->getSyscallArg(tc, index))) return -EFAULT; int64_t length = process->getSyscallArg(tc, index, 64); @@ -527,7 +527,7 @@ chownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, index))) + if (!tc->getMemProxy()->tryReadString(path, p->getSyscallArg(tc, index))) return -EFAULT; /* XXX endianess */ diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 5c480272d..45c87f0ab 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -62,7 +62,7 @@ #include "cpu/thread_context.hh" #include "debug/SyscallVerbose.hh" #include "mem/page_table.hh" -#include "mem/translating_port.hh" +#include "mem/se_translating_port_proxy.hh" #include "sim/byteswap.hh" #include "sim/process.hh" #include "sim/syscallreturn.hh" @@ -121,18 +121,18 @@ class BaseBufferArg { // // copy data into simulator space (read from target memory) // - virtual bool copyIn(TranslatingPort *memport) + virtual bool copyIn(SETranslatingPortProxy* memproxy) { - memport->readBlob(addr, bufPtr, size); + memproxy->readBlob(addr, bufPtr, size); return true; // no EFAULT detection for now } // // copy data out of simulator space (write to target memory) // - virtual bool copyOut(TranslatingPort *memport) + virtual bool copyOut(SETranslatingPortProxy* memproxy) { - memport->writeBlob(addr, bufPtr, size); + memproxy->writeBlob(addr, bufPtr, size); return true; // no EFAULT detection for now } @@ -464,7 +464,7 @@ convertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) //Here are a couple convenience functions template<class OS> static void -copyOutStatBuf(TranslatingPort * mem, Addr addr, +copyOutStatBuf(SETranslatingPortProxy* mem, Addr addr, hst_stat *host, bool fakeTTY = false) { typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; @@ -475,7 +475,7 @@ copyOutStatBuf(TranslatingPort * mem, Addr addr, template<class OS> static void -copyOutStat64Buf(TranslatingPort * mem, Addr addr, +copyOutStat64Buf(SETranslatingPortProxy* mem, Addr addr, hst_stat64 *host, bool fakeTTY = false) { typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; @@ -530,7 +530,7 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process, std::string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, + if (!tc->getMemProxy()->tryReadString(path, process->getSyscallArg(tc, index))) return -EFAULT; @@ -594,7 +594,7 @@ sysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, sysinfo->uptime=seconds_since_epoch; sysinfo->totalram=process->system->memSize(); - sysinfo.copyOut(tc->getMemPort()); + sysinfo.copyOut(tc->getMemProxy()); return 0; } @@ -608,7 +608,7 @@ chmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, std::string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, + if (!tc->getMemProxy()->tryReadString(path, process->getSyscallArg(tc, index))) { return -EFAULT; } @@ -714,7 +714,7 @@ statFunc(SyscallDesc *desc, int callnum, LiveProcess *process, std::string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, + if (!tc->getMemProxy()->tryReadString(path, process->getSyscallArg(tc, index))) { return -EFAULT; } @@ -729,7 +729,7 @@ statFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf); + copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); return 0; } @@ -744,7 +744,7 @@ stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, std::string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, + if (!tc->getMemProxy()->tryReadString(path, process->getSyscallArg(tc, index))) return -EFAULT; Addr bufPtr = process->getSyscallArg(tc, index); @@ -763,7 +763,7 @@ stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf); + copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); return 0; } @@ -794,7 +794,7 @@ fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1)); + copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); return 0; } @@ -809,7 +809,7 @@ lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, std::string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, + if (!tc->getMemProxy()->tryReadString(path, process->getSyscallArg(tc, index))) { return -EFAULT; } @@ -824,7 +824,7 @@ lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf); + copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); return 0; } @@ -838,7 +838,7 @@ lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, std::string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, + if (!tc->getMemProxy()->tryReadString(path, process->getSyscallArg(tc, index))) { return -EFAULT; } @@ -858,7 +858,7 @@ lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf); + copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); return 0; } @@ -884,7 +884,7 @@ fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1)); + copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (fd == 1)); return 0; } @@ -899,7 +899,7 @@ statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, std::string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, + if (!tc->getMemProxy()->tryReadString(path, process->getSyscallArg(tc, index))) { return -EFAULT; } @@ -914,7 +914,7 @@ statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf); + OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); return 0; } @@ -939,7 +939,7 @@ fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if (result < 0) return -errno; - OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf); + OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); return 0; } @@ -958,7 +958,7 @@ writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, return -EBADF; } - TranslatingPort *p = tc->getMemPort(); + SETranslatingPortProxy *p = tc->getMemProxy(); uint64_t tiov_base = process->getSyscallArg(tc, index); size_t count = process->getSyscallArg(tc, index); struct iovec hiov[count]; @@ -1103,7 +1103,7 @@ getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, break; } - rlp.copyOut(tc->getMemPort()); + rlp.copyOut(tc->getMemProxy()); return 0; } @@ -1121,7 +1121,7 @@ gettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, tp->tv_sec = TheISA::htog(tp->tv_sec); tp->tv_usec = TheISA::htog(tp->tv_usec); - tp.copyOut(tc->getMemPort()); + tp.copyOut(tc->getMemProxy()); return 0; } @@ -1136,14 +1136,14 @@ utimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, std::string path; int index = 0; - if (!tc->getMemPort()->tryReadString(path, + if (!tc->getMemProxy()->tryReadString(path, process->getSyscallArg(tc, index))) { return -EFAULT; } TypedBufferArg<typename OS::timeval [2]> tp(process->getSyscallArg(tc, index)); - tp.copyIn(tc->getMemPort()); + tp.copyIn(tc->getMemProxy()); struct timeval hostTimeval[2]; for (int i = 0; i < 2; ++i) @@ -1209,7 +1209,7 @@ getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, who); } - rup.copyOut(tc->getMemPort()); + rup.copyOut(tc->getMemProxy()); return 0; } @@ -1234,7 +1234,7 @@ timesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, bufp->tms_utime = htog(bufp->tms_utime); // Write back - bufp.copyOut(tc->getMemPort()); + bufp.copyOut(tc->getMemProxy()); // Return clock ticks since system boot return clocks; @@ -1255,7 +1255,7 @@ timeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, if(taddr != 0) { typename OS::time_t t = sec; t = htog(t); - TranslatingPort *p = tc->getMemPort(); + SETranslatingPortProxy *p = tc->getMemProxy(); p->writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); } return sec; diff --git a/src/sim/system.cc b/src/sim/system.cc index d3bee1ad1..14c44d063 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 ARM Limited + * Copyright (c) 2011-2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -57,9 +57,9 @@ #include "debug/Loader.hh" #include "debug/WorkItems.hh" #include "kern/kernel_stats.hh" +#include "mem/fs_translating_port_proxy.hh" #include "mem/mem_object.hh" #include "mem/physical.hh" -#include "mem/vport.hh" #include "params/System.hh" #include "sim/byteswap.hh" #include "sim/debug.hh" @@ -74,7 +74,9 @@ vector<System *> System::systemList; int System::numSystemsRunning = 0; System::System(Params *p) - : SimObject(p), physmem(p->physmem), _numContexts(0), pagePtr(0), + : MemObject(p), _systemPort("system_port", this), + physmem(p->physmem), + _numContexts(0), init_param(p->init_param), loadAddrMask(p->load_addr_mask), nextPID(0), @@ -104,68 +106,12 @@ System::System(Params *p) if (!debugSymbolTable) debugSymbolTable = new SymbolTable; - /** - * Get a functional port to memory - */ - Port *mem_port; - functionalPort = new FunctionalPort(name() + "-fport"); - mem_port = physmem->getPort("functional"); - functionalPort->setPeer(mem_port); - mem_port->setPeer(functionalPort); - - virtPort = new VirtualPort(name() + "-fport"); - mem_port = physmem->getPort("functional"); - virtPort->setPeer(mem_port); - mem_port->setPeer(virtPort); - - - /** - * Load the kernel code into memory + * Get a port proxy to memory */ - if (params()->kernel == "") { - inform("No kernel set for full system simulation. " - "Assuming you know what you're doing...\n"); - } else { - // Load kernel code - kernel = createObjectFile(params()->kernel); - inform("kernel located at: %s", params()->kernel); - - if (kernel == NULL) - fatal("Could not load kernel file %s", params()->kernel); - - // Load program sections into memory - kernel->loadSections(functionalPort, loadAddrMask); - - // setup entry points - kernelStart = kernel->textBase(); - kernelEnd = kernel->bssBase() + kernel->bssSize(); - kernelEntry = kernel->entryPoint(); - - // load symbols - if (!kernel->loadGlobalSymbols(kernelSymtab)) - fatal("could not load kernel symbols\n"); - - if (!kernel->loadLocalSymbols(kernelSymtab)) - fatal("could not load kernel local symbols\n"); - - if (!kernel->loadGlobalSymbols(debugSymbolTable)) - fatal("could not load kernel symbols\n"); - - if (!kernel->loadLocalSymbols(debugSymbolTable)) - fatal("could not load kernel local symbols\n"); - - DPRINTF(Loader, "Kernel start = %#x\n", kernelStart); - DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd); - DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry); - DPRINTF(Loader, "Kernel loaded...\n"); - } + physProxy = new PortProxy(*getSystemPort()); + virtProxy = new FSTranslatingPortProxy(*getSystemPort()); } - - // increment the number of running systms - numSystemsRunning++; - - activeCpus.clear(); } System::~System() @@ -178,6 +124,21 @@ System::~System() } void +System::init() +{ + // check that the system port is connected + if (!_systemPort.isConnected()) + panic("System port on %s is not connected.\n", name()); +} + +Port* +System::getPort(const std::string &if_name, int idx) +{ + // no need to distinguish at the moment (besides checking) + return &_systemPort; +} + +void System::setMemoryMode(Enums::MemoryMode mode) { assert(getState() == Drained); @@ -261,6 +222,59 @@ System::initState() int i; for (i = 0; i < threadContexts.size(); i++) TheISA::startupCPU(threadContexts[i], i); + // Moved from the constructor to here since it relies on the + // address map being resolved in the interconnect + /** + * Load the kernel code into memory + */ + if (params()->kernel == "") { + inform("No kernel set for full system simulation. " + "Assuming you know what you're doing...\n"); + } else { + // Load kernel code + kernel = createObjectFile(params()->kernel); + inform("kernel located at: %s", params()->kernel); + + if (kernel == NULL) + fatal("Could not load kernel file %s", params()->kernel); + + // Load program sections into memory + kernel->loadSections(physProxy, loadAddrMask); + + // setup entry points + kernelStart = kernel->textBase(); + kernelEnd = kernel->bssBase() + kernel->bssSize(); + kernelEntry = kernel->entryPoint(); + + // load symbols + if (!kernel->loadGlobalSymbols(kernelSymtab)) + fatal("could not load kernel symbols\n"); + + if (!kernel->loadLocalSymbols(kernelSymtab)) + fatal("could not load kernel local symbols\n"); + + if (!kernel->loadGlobalSymbols(debugSymbolTable)) + fatal("could not load kernel symbols\n"); + + if (!kernel->loadLocalSymbols(debugSymbolTable)) + fatal("could not load kernel local symbols\n"); + + DPRINTF(Loader, "Kernel start = %#x\n", kernelStart); + DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd); + DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry); + DPRINTF(Loader, "Kernel loaded...\n"); + } + } + + // increment the number of running systms + numSystemsRunning++; + + activeCpus.clear(); + + if (FullSystem) { + int i; + for (i = 0; i < threadContexts.size(); i++) + TheISA::startupCPU(threadContexts[i], i); } } diff --git a/src/sim/system.hh b/src/sim/system.hh index d675eb727..eb192fb99 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2012 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * Copyright (c) 2011 Regents of the University of California * All rights reserved. @@ -44,24 +56,81 @@ #include "cpu/pc_event.hh" #include "enums/MemoryMode.hh" #include "kern/system_events.hh" +#include "mem/mem_object.hh" #include "mem/port.hh" #include "params/System.hh" -#include "sim/sim_object.hh" class BaseCPU; class BaseRemoteGDB; -class FunctionalPort; +class FSTranslatingPortProxy; class GDBListener; class ObjectFile; class PhysicalMemory; class Platform; +class PortProxy; class ThreadContext; class VirtualPort; -class System : public SimObject +class System : public MemObject { + private: + + /** + * Private class for the system port which is only used as a + * master for debug access and for non-structural entities that do + * not have a port of their own. + */ + class SystemPort : public Port + { + public: + + /** + * Create a system port with a name and an owner. + */ + SystemPort(const std::string &_name, MemObject *_owner) + : Port(_name, _owner) + { } + bool recvTiming(PacketPtr pkt) + { panic("SystemPort does not receive timing!\n"); return false; } + Tick recvAtomic(PacketPtr pkt) + { panic("SystemPort does not receive atomic!\n"); return 0; } + void recvFunctional(PacketPtr pkt) + { panic("SystemPort does not receive functional!\n"); } + + /** + * The system port is a master port connected to a single + * slave and thus do not care about what ranges the slave + * covers (as there is nothing to choose from). + */ + void recvRangeChange() { } + + }; + + SystemPort _systemPort; + public: + /** + * After all objects have been created and all ports are + * connected, check that the system port is connected. + */ + virtual void init(); + + /** + * Get a pointer to the system port that can be used by + * non-structural simulation objects like processes or threads, or + * external entities like loaders and debuggers, etc, to access + * the memory system. + * + * @return a pointer to the system port we own + */ + Port* getSystemPort() { return &_systemPort; } + + /** + * Additional function to return the Port of a memory object. + */ + Port *getPort(const std::string &if_name, int idx = -1); + static const char *MemoryModeStrings[3]; Enums::MemoryMode @@ -112,8 +181,8 @@ class System : public SimObject /** Port to physical memory used for writing object files into ram at * boot.*/ - FunctionalPort *functionalPort; - VirtualPort *virtPort; + PortProxy* physProxy; + FSTranslatingPortProxy* virtProxy; /** kernel symbol table */ SymbolTable *kernelSymtab; diff --git a/src/sim/vptr.hh b/src/sim/vptr.hh index 2033339f9..eee575b6b 100644 --- a/src/sim/vptr.hh +++ b/src/sim/vptr.hh @@ -33,7 +33,7 @@ #include "arch/isa_traits.hh" #include "arch/vtophys.hh" -#include "mem/vport.hh" +#include "mem/fs_translating_port_proxy.hh" class ThreadContext; @@ -71,8 +71,8 @@ class VPtr if (!ptr) return; - VirtualPort *port = tc->getVirtPort(); - port->readBlob(ptr, buffer, sizeof(T)); + FSTranslatingPortProxy* proxy = tc->getVirtProxy(); + proxy->readBlob(ptr, buffer, sizeof(T)); } bool |